issue #1378 add Activity tab in user manager

This commit is contained in:
MatthieuLP 2021-04-09 09:34:01 +02:00 committed by plegall
parent d784822664
commit ec4d677cf7
11 changed files with 1394 additions and 8 deletions

View file

@ -36,6 +36,12 @@ function add_core_tabs($sheets, $tab_id)
$sheets['search'] = array('caption' => '<span class="icon-search"></span>'.l10n('Search'), 'url' => $my_base_url.'cat_search');
break;
case 'users':
global $my_base_url;
$sheets['user_list'] = array('caption' => '<span class="icon-users"></span>'.l10n('User list'), 'url' => $my_base_url.'user_list');
$sheets['user_activity'] = array('caption' => '<span class="icon-eye"></span>'.l10n('Activity'), 'url' => $my_base_url.'user_activity');
break;
case 'batch_manager':
global $manager_link;
$sheets['global'] = array('caption' => '<span class="icon-th"></span>'.l10n('global mode'), 'url' => $manager_link.'global');

View file

@ -0,0 +1,18 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=';
$tabsheet = new tabsheet();
$tabsheet->set_id('users');
$tabsheet->select($page['tab']);
$tabsheet->assign();
?>

View file

@ -0,0 +1,907 @@
{include file='include/colorbox.inc.tpl'}
{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
{combine_script id='jquery.selectize' load='footer' path='themes/default/js/plugins/selectize.min.js'}
{combine_css id='jquery.selectize' path="themes/default/js/plugins/selectize.{$themeconf.colorscheme}.css"}
{combine_script id='LocalStorageCache' load='footer' path='admin/themes/default/js/LocalStorageCache.js'}
{combine_css path="admin/themes/default/fontello/css/animation.css" order=10} {* order 10 is required, see issue 1080 *}
{footer_script}
{* <!-- USERS --> *}
var usersCache = new UsersCache({
serverKey: '{$CACHE_KEYS.users}',
serverId: '{$CACHE_KEYS._hash}',
rootUrl: '{$ROOT_URL}'
});
usersCache.selectize(jQuery('[data-selectize=users]'));
jQuery(".cancel-icon").click(function() {
jQuery(".user-selecter")[0].selectize.setValue(null);
return false;
});
const color_icons = ["icon-red", "icon-blue", "icon-yellow", "icon-purple", "icon-green"];
{*<-- Translation keys -->*}
var actionType_add = "{'add'|translate}";
var actionType_delete = "{'deletion'|translate}";
var actionType_move = "{'move'|translate}";
var actionType_edit = "{'edit'|translate}";
var actionType_log = "{'log'|translate}";
{* Album keys *}
var actionInfos_album_added = "{'%d album added'|translate}";
var actionInfos_album_deleted = "{'%d album deleted'|translate}";
var actionInfos_album_edited = "{'%d album edited'|translate}";
var actionInfos_album_moved = "{'%d album moved'|translate}";
var actionInfos_albums_added = "{'%d albums added'|translate}";
var actionInfos_albums_deleted = "{'%d albums deleted'|translate}";
var actionInfos_albums_edited = "{'%d albums edited'|translate}";
var actionInfos_albums_moved = "{'%d albums moved'|translate}";
{* User keys *}
var actionInfos_user_added = "{'%d user added'|translate}";
var actionInfos_user_deleted = "{'%d user deleted'|translate}";
var actionInfos_user_edited = "{'%d user edited'|translate}";
var actionInfos_user_logged_in = "{'%d user logged in'|translate}";
var actionInfos_user_logged_out = "{'%d user logged out'|translate}";
var actionInfos_users_added = "{'%d users added'|translate}";
var actionInfos_users_deleted = "{'%d users deleted'|translate}";
var actionInfos_users_edited = "{'%d users edited'|translate}";
var actionInfos_users_logged_in = "{'%d users logged in'|translate}";
var actionInfos_users_logged_out = "{'%d users logged out'|translate}";
{* Photo keys *}
var actionInfos_photo_added = "{'%d photo added'|translate}";
var actionInfos_photo_deleted = "{'%d photo deleted'|translate}";
var actionInfos_photo_edited = "{'%d photo edited'|translate}";
var actionInfos_photo_moved = "{'%d photo moved'|translate}";
var actionInfos_photos_added = "{'%d photos added'|translate}";
var actionInfos_photos_deleted = "{'%d photos deleted'|translate}";
var actionInfos_photos_edited = "{'%d photos edited'|translate}";
var actionInfos_photos_moved = "{'%d photos moved'|translate}";
{* Group keys *}
var actionInfos_group_added = "{'%d group added'|translate}";
var actionInfos_group_deleted = "{'%d group deleted'|translate}";
var actionInfos_group_edited = "{'%d group edited'|translate}";
var actionInfos_group_moved = "{'%d group moved'|translate}";
var actionInfos_groups_added = "{'%d groups added'|translate}";
var actionInfos_groups_deleted = "{'%d groups deleted'|translate}";
var actionInfos_groups_edited = "{'%d groups edited'|translate}";
var actionInfos_groups_moved = "{'%d groups moved'|translate}";
{* Tags keys *}
var actionInfos_tag_added = "{'%d tag added'|translate}";
var actionInfos_tag_deleted = "{'%d tag deleted'|translate}";
var actionInfos_tag_edited = "{'%d tag edited'|translate}";
var actionInfos_tag_moved = "{'%d tag moved'|translate}";
var actionInfos_tags_added = "{'%d tags added'|translate}";
var actionInfos_tags_deleted = "{'%d tags deleted'|translate}";
var actionInfos_tags_edited = "{'%d tags edited'|translate}";
var actionInfos_tags_moved = "{'%d tags moved'|translate}";
{*<-- Getting and Displaying Activities -->*}
get_user_activity();
function get_user_activity() {
$.ajax({
url: "ws.php?format=json&method=pwg.activity.getList",
type: "POST",
dataType: "json",
data: {
a: 1,
b: 2
},
success: (data) => {
/* console log to help debug */
{* console.log(data); *}
setCreationDate(data.result[data.result.length-1].date, data.result[0].date);
$(".loading").hide();
data.result.forEach(line => {
lineConstructor(line);
});
displayLine(data);
},
error: (e) => {
console.log("ajax call failed");
console.log(e);
}
})
}
function lineConstructor(line) {
let newLine = $("#-1").clone();
newLine.removeClass("hide");
/* console log to help debug */
{* console.log(line); *}
newLine.attr("id", line.id);
var final_albumInfos;
{* Determines wich string need to be placed in the line constructed *}
if (line.counter > 1) {
// pluriel
switch (line.action) {
case "edit":
newLine.find(".action-type").addClass("icon-blue");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-pencil");
newLine.find(".action-name").html(actionType_edit);
switch (line.object) {
case "user":
final_albumInfos = actionInfos_users_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-user-1");
break;
case "album":
final_albumInfos = actionInfos_albums_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_groups_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photos_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tags_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "add":
newLine.find(".action-type").addClass("icon-green");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-plus");
newLine.find(".action-name").html(actionType_add);
switch (line.object) {
case "user":
final_albumInfos = actionInfos_users_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-user-1");
break;
case "album":
final_albumInfos = actionInfos_albums_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_groups_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photos_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tags_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "delete":
newLine.find(".action-type").addClass("icon-red");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-trash-1");
newLine.find(".action-name").html(actionType_delete);
switch (line.object) {
case "user":
final_albumInfos = actionInfos_users_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-user-1");
break;
case "album":
final_albumInfos = actionInfos_albums_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_groups_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photos_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tags_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "move":
newLine.find(".action-type").addClass("icon-yellow");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-move");
newLine.find(".action-name").html(actionType_move);
switch (line.object) {
case "album":
final_albumInfos = actionInfos_albums_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_groups_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photos_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tags_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "login":
newLine.find(".action-type").addClass("icon-purple");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-key");
newLine.find(".action-section").addClass("icon-user-1");
newLine.find(".action-name").html(actionType_log);
console.log("userS Logged in");
final_albumInfos = actionInfos_users_logged_in.replace('%d', line.counter);
break;
case "logout":
newLine.find(".action-type").addClass("icon-purple");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-key");
newLine.find(".action-section").addClass("icon-user-1");
newLine.find(".action-name").html(actionType_log);
console.log("userS Logged in");
final_albumInfos = actionInfos_users_logged_out.replace('%d', line.counter);
break;
default:
newLine.find(".action-type").addClass("icon-purple");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
break;
}
} else {
// singulier
switch (line.action) {
case "edit":
newLine.find(".action-type").addClass("icon-blue");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-pencil");
newLine.find(".action-name").html(actionType_edit);
switch (line.object) {
case "user":
final_albumInfos = actionInfos_user_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-user-1");
break;
case "album":
final_albumInfos = actionInfos_album_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_group_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photo_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tag_edited.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "add":
newLine.find(".action-type").addClass("icon-green");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-plus");
newLine.find(".action-name").html(actionType_add);
switch (line.object) {
case "user":
final_albumInfos = actionInfos_user_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-user-1");
break;
case "album":
final_albumInfos = actionInfos_album_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_group_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photo_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tag_added.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "delete":
newLine.find(".action-type").addClass("icon-red");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-trash-1");
newLine.find(".action-name").html(actionType_delete);
switch (line.object) {
case "user":
final_albumInfos = actionInfos_user_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-user-1");
break;
case "album":
final_albumInfos = actionInfos_album_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_group_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photo_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tag_deleted.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "move":
newLine.find(".action-type").addClass("icon-yellow");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-move");
newLine.find(".action-name").html(actionType_move);
switch (line.object) {
case "album":
final_albumInfos = actionInfos_album_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-folder-open");
break;
case "group":
final_albumInfos = actionInfos_group_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-users-1");
break;
case "photo":
final_albumInfos = actionInfos_photo_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-picture");
break;
case "tag":
final_albumInfos = actionInfos_tag_moved.replace('%d', line.counter);
newLine.find(".action-section").addClass("icon-tags");
break;
default:
final_albumInfos = line.counter + " " +line.object + " " + line.action;
break;
}
break;
case "login":
newLine.find(".action-type").addClass("icon-purple");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-key");
newLine.find(".action-section").addClass("icon-user-1");
newLine.find(".action-name").html(actionType_log);
final_albumInfos = actionInfos_user_logged_in.replace('%d', line.counter);
break;
case "logout":
newLine.find(".action-type").addClass("icon-purple");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
newLine.find(".action-icon").addClass("icon-key");
newLine.find(".action-section").addClass("icon-user-1");
newLine.find(".action-name").html(actionType_log);
final_albumInfos = actionInfos_user_logged_out.replace('%d', line.counter);
break;
default:
newLine.find(".action-type").addClass("icon-purple");
newLine.find(".user-pic").addClass(color_icons[line.user_id % 5]);
break;
}
}
newLine.find(".action-infos-test").html(final_albumInfos);
/* Action_section */
newLine.find(".nb_items").html(line.counter);
/* Date_section */
newLine.find(".date-day").html(line.date);
newLine.find(".date-hour").html(line.hour);
/* User _Section */
newLine.find(".user-pic").html(get_initials(line.username));
newLine.find(".user-name").html(line.username);
/* Detail_section */
newLine.find(".detail-item-1").html(line.ip_address);
newLine.find(".detail-item-1").attr("title", "IP");
if (line.detailsType == "script") {
newLine.find(".detail-item-2").html(line.details.script);
newLine.find(".detail-item-2").attr('title', 'Script');
} else if (line.detailsType == "method") {
newLine.find(".detail-item-2").html(line.details.method);
newLine.find(".detail-item-2").attr('title', 'API Method');
}
if (line.details.agent) {
newLine.find(".detail-item-3").html(line.details.agent);
newLine.find(".detail-item-3").attr('title', line.details.agent);
} else {
newLine.find(".detail-item-3").remove();
}
displayLine(newLine);
}
function displayLine(line) {
$(".tab").append(line);
}
function get_initials(username) {
let words = username.toUpperCase().split(" ");
let res = words[0][0];
if (words.length > 1 && words[1][0] !== undefined ) {
res += words[1][0];
}
return res;
}
function filterUsers(username) {
let lines = $(".line");
showAllLines()
let resultLines = [];
for (let index = 1; index < lines.length; index++) {
if (username != lines[index].children[2].children[1].innerHTML) {
$("#" + lines[index].id).hide();
} else {
resultLines.push(lines[index].getElementsByClassName("date-day")[0].textContent)
}
}
setCreationDate((!resultLines[resultLines.length-1]) ? "{'N/A'|translate}" : resultLines[resultLines.length-1], (!resultLines[0]) ? "{'N/A'|translate}" : resultLines[0])
}
function showAllLines() {
let lines = $(".line");
for (let index = 1; index < lines.length; index++) {
$("#" + lines[index].id).show();
}
$("#-1").hide();
}
function setCreationDate(startDate, endDate) {
$(".start-date").html(startDate)
$(".end-date").html(endDate)
}
$(document).ready(function () {
$('select').on('change', function (user) {
try {
filterUsers($(".selectize-input .item")[0].innerHTML);
} catch (error) {
showAllLines();
let lines = $(".line");
let resultLines = [];
for (let index = 1; index < lines.length; index++) {
resultLines.push(lines[index].getElementsByClassName("date-day")[0].textContent)
}
setCreationDate((!resultLines[resultLines.length-1]) ? "-" : resultLines[resultLines.length-1], (!resultLines[0]) ? "-" : resultLines[0])
}
});
});
{/footer_script}
<div class="container">
<div class="activity-header">
<div class="select-user">
<span class="select-user-title"> {'Selected user'|translate} </span>
<select class="user-selecter" data-selectize="users" placeholder="{'none'|translate}"
single style="width:250px; height: 10px;"></select>
<span class="icon-cancel cancel-icon"> </span>
</div>
<div class="acivity-time">
<span class="acivity-time-text"> {'Activity time from'|translate}</span>
<span class="start-date">
<span class="icon-spin6 animate-spin"></span>
</span>
<span class="acivity-time-text"> {'to'|translate}</span>
<span class="end-date">
<span class="icon-spin6 animate-spin"></span>
</span>
</div>
<a class="download_csv tiptip" title="{'Download all activities'|translate}" href="ws.php?format=json&method=pwg.activity.downloadLog">
<i class="icon-download"> </i>
</a>
</div>
<div class="tab-title">
<div class="action-title">
{'Action'|translate}
</div>
<div class="date-title">
{'Date'|translate}
</div>
<div class="user-title">
{'User'|translate}
</div>
<div class="detail-title">
{'Details'|translate}
</div>
</div>
<div class="tab">
<div class="loading">
<span class="icon-spin6 animate-spin"> </span>
</div>
<div class="line hide" id="-1">
<div class="action-section">
<div class="action-type">
<span class="action-icon"></span>
<span class="action-name"> Edit </span>
</div>
<div class="action-infos">
<span class="action-infos-test"> T </span>
</div>
</div>
<div class="date-section">
<span class="icon-clock"> </span>
<span class="date-day">1 Janvier 1970</span>
<span class="date-hour">a 00:00</span>
</div>
<div class="user-section">
<div class="user-pic">
</div>
<div class="user-name">
Username
</div>
</div>
<div class="detail-section">
<div class="detail-item detail-item-1">
detail 1
</div>
<div class=" detail-item detail-item-2">
detail 2
</div>
<div class="detail-item detail-item-3">
detail 3
</div>
</div>
</div>
</div>
</div>
<style>
.container {
padding: 0 30px;
}
.container,
.tab {
display: flex;
flex-direction: column;
}
.tab-title {
display: flex;
flex-direction: row;
}
.hide {
display: none !important;
}
.tab-title div {
text-align: left;
font-size: 1.1em;
font-weight: bold;
margin: 0 20px 10px 0px;
color: #9e9e9e;
padding-bottom: 5px;
}
.tab-title div:first-child {
margin: 0 0 10px 35px;
}
.tab-title .action-title,
.line .action-section {
min-width: 310px;
max-width: 340px;
}
.tab-title .action-title {
min-width: 298px !important;
}
.tab-title .date-title,
.line .date-section {
min-width: 240px;
max-width: 300px;
}
.tab-title .user-title,
.line .user-section {
min-width: 200px;
max-width: 250px;
}
.line .action-section,
.line .date-section,
.line .user-section,
.tab-title .action-title,
.tab-title .date-title,
.tab-title .user-title {
text-align: left;
{* width: 22%; *}
}
.line .action-section,
.line .date-section,
.line .user-section {
margin: 0 20px 0 0;
}
.line .detail-section,
.tab-title .detail-title {
display: flex;
flex-grow: 1;
margin-right: 0;
}
.action-section {
display: flex;
flex-direction: row;
align-items: center;
}
.action-type {
margin: 0 10px 0 15px;
padding: 3px 10px;
border-radius: 20px;
white-space: nowrap;
}
.action-infos {
display: flex;
flex-direction: row;
}
.action-infos span {
margin-right: 5px;
}
.date-section .date-day {
font-weight: bold;
}
.user-section {
display: flex;
flex-direction: row;
align-items: center;
}
.user-section .user-pic {
width: 30px;
height: 30px;
min-width: 30px;
border-radius: 50%;
margin-right: 10px;
display: flex;
justify-content: center;
align-items: center;
font-weight: 600;
font-size: 17px;
}
.user-section .user-name {
font-weight: bold;
}
/* Activity Header */
.activity-header {
display: flex;
flex-direction: row;
align-items: center;
height: 100px;
width: 100%;
}
.select-user span {
font-size: 15px;
font-weight: bold;
margin-right: 20px;
}
.acivity-time {
margin: 0 25px;
}
.user-selecter {
width: 150px;
}
/* Selectize */
.selectize-control.single.user-selecter {
height: 30px;
}
.selectize-control.single .selectize-input {
height: 30px;
padding: 0 10px;
display: flex;
align-items: center;
justify-content: left;
}
.selectize-input {
text-align: left;
}
.selectize-control.single .selectize-input input{
height: 30px;
}
.selectize-dropdown {
text-align: left;
}
.cancel-icon {
margin: 0 0 0 10px !important;
cursor: pointer;
}
.loading {
font-size: 25px;
}
.action-section::before {
margin: 0 -5px 0 10px;
opacity: 0.6;
}
</style>

View file

@ -5120,3 +5120,82 @@ color:#FF7B00;
.user-property-input.user-property-input-password:hover {
background-color: #f0f0f0;
}
/* Activity Tab in user manager */
.select-user {
background: #fafafa;
height: 50%;
display: flex;
align-items: center;
padding: 0 20px;
box-shadow: 0px 2px 4px #00000024;
border-radius: 5px;
}
.start-date,
.end-date {
padding: 5px 10px;
background: #eaeaea;
border-radius: 50px;
margin: 5px;
white-space: nowrap;
}
.acivity-time-text {
font-size: 13px;
font-weight: bold;
}
.line {
background: #fafafa;
box-shadow: 0px 2px 4px #00000024;
display: flex;
flex-direction: row;
height: 40px;
align-items: center;
margin-bottom: 10px;
}
.line .detail-item {
background: #f0f0f0f0;
margin: 0 10px 0 0;
padding: 3px 6px;
border-radius: 20px;
max-width: 120px;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
cursor: default;
white-space: nowrap;
}
.download_csv {
margin-left: auto;
height: 25px;
width: 30px;
background: #dddddd;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
color:black;
cursor: pointer;
border-radius: 5px;
}
.download_csv:hover {
background: #aaaaaa;
color: black;
}

View file

@ -1327,3 +1327,89 @@ li.plupload_delete a:hover {background: url("images/cancelhover.svg")!important;
.cache-lastCalculated-value, .cache-lastCalculated-text, .cache-size-text, .picture-deletion-size, #label-delete-size-checkbox {
color: #c1c1c1;
}
/* Activity Tab in user manager */
.select-user {
background: #555555;
height: 50%;
display: flex;
align-items: center;
padding: 0 20px;
box-shadow: 0px 2px 4px #00000024;
border-radius: 5px;
}
.select-user-title {
color: #bbbbbb;
}
.start-date,
.end-date {
padding: 5px 10px;
background: #555555;
border-radius: 50px;
margin: 5px;
color: #bbbbbb;
}
.acivity-time-text {
font-size: 13px;
font-weight: bold;
color: #bbbbbb;
}
.line {
background: #333333;
box-shadow: 0px 2px 4px #00000024;
display: flex;
flex-direction: row;
height: 40px;
align-items: center;
margin-bottom: 10px;
color: #bbbbbb;
}
.line .detail-item {
background: #555555;
margin: 0 10px 0 0;
padding: 3px 6px;
border-radius: 20px;
min-width: 50px;
max-width: 150px;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
cursor: default;
white-space: nowrap;
}
.download_csv {
margin-left: auto;
height: 25px;
width: 30px;
background: #555555;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
color:#b8b8b8;
cursor: pointer;
border-radius: 5px;
}
.download_csv:hover {
background: #777777;
color: #dddddd;
}

39
admin/user_activity.php Normal file
View file

@ -0,0 +1,39 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
$page['tab'] = 'user_activity';
include(PHPWG_ROOT_PATH.'admin/include/user_tabs.inc.php');
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
$template->set_filename('user_activity', 'user_activity.tpl');
$template->assign('ADMIN_PAGE_TITLE', l10n('User Activity logs'));
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'user_activity');
?>

View file

@ -16,14 +16,8 @@ check_input_parameter('group', $_GET, false, PATTERN_ID);
// | tabs |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=';
$tabsheet = new tabsheet();
$tabsheet->set_id('users');
$tabsheet->select('user_list');
$tabsheet->assign();
$page['tab'] = 'user_list';
include(PHPWG_ROOT_PATH.'admin/include/user_tabs.inc.php');
// +-----------------------------------------------------------------------+
// | groups list |

View file

@ -341,4 +341,143 @@ function ws_session_getStatus($params, &$service)
return $res;
}
/**
* API method
* Returns lines of users activity
*/
function ws_getActivityList($param, &$service) {
/* Test Lantency */
// sleep(1);
$output_lines = array();
$current_key = '';
$query = '
SELECT
activity_id,
performed_by,
object, action,
session_idx,
ip_address,
occured_on,
details,
username
FROM piwigo_activity,
piwigo_users
WHERE piwigo_activity.performed_by = piwigo_users.id
ORDER BY activity_id DESC;
';
$line_id = 0;
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$row['details'] = str_replace('`groups`', 'groups', $row['details']);
$row['details'] = str_replace('`rank`', 'rank', $row['details']);
$details = unserialize($row['details']);
if (isset($details['method']))
{
$detailsType = 'method';
}
if (isset($details['script']))
{
$detailsType = 'script';
}
$line_key = $row['session_idx'].'~'.$row['object'].'~'.$row['action'].'~'; // idx~photo~add
if ($line_key === $current_key)
{
// j'incrémente le counter de la ligne précédente
$output_lines[count($output_lines)-1]['counter']++;
}
else
{
list($date, $hour) = explode(' ', $row['occured_on']);
// New line
$output_lines[] = array(
'id' => $line_id,
'object' => $row['object'],
'action' => $row['action'],
'ip_address' => $row['ip_address'],
'date' => format_date($date),
'hour' => $hour,
'username' => $row['username'],
'user_id' => $row['performed_by'],
'detailsType' => $detailsType,
'details' => $details,
'counter' => 1,
);
$current_key = $line_key;
$line_id++;
}
}
return $output_lines;
}
/**
* API method
* Returns lines of users activity
*/
function ws_activity_downloadLog($param, &$service) {
$output_lines = array();
$query = '
SELECT
activity_id,
performed_by,
object,
object_id,
action,
ip_address,
occured_on,
details,
username
FROM piwigo_activity,
piwigo_users
WHERE piwigo_activity.performed_by = piwigo_users.id
ORDER BY activity_id DESC;
';
$result = pwg_query($query);
array_push($output_lines, ['User', 'ID_User', 'Object', 'Object_ID', 'Action', 'Date', 'Hour', 'IP_Address', 'Details']);
while ($row = pwg_db_fetch_assoc($result))
{
$row['details'] = str_replace('`groups`', 'groups', $row['details']);
$row['details'] = str_replace('`rank`', 'rank', $row['details']);
list($date, $hour) = explode(' ', $row['occured_on']);
$output_lines[] = array(
'username' => $row['username'],
'user_id' => $row['performed_by'],
'object' => $row['object'],
'object_id' => $row['object_id'],
'action' => $row['action'],
'date' => $date,
'hour' => $hour,
'ip_address' => $row['ip_address'],
'details' => $row['details'],
);
$line_id++;
}
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename='.date('YmdGis').'piwigo_activity_log.csv');
header("Content-Transfer-Encoding: UTF-8");
$f = fopen('php://output', 'w');
foreach ($output_lines as $line) {
fputcsv($f, $line, ";");
}
fclose($f);
}
?>

View file

@ -1172,3 +1172,53 @@ $lang['Cache size'] = "Cache size";
$lang['calculated'] = "calculated";
$lang['months ago'] = "months ago";
$lang['Delete these sizes'] = 'Delete these sizes';
$lang['Activity'] = 'Activity';
$lang['Selected user'] = 'Selected user';
$lang['Activity time from'] = 'Activity time from';
$lang['to'] = 'à';
$lang['add'] = 'add';
$lang['deletion'] = 'deletion';
$lang['move'] = 'move';
$lang['edit'] = 'edit';
$lang['log'] = 'log';
$lang['%d album added'] = '%d album added';
$lang['%d album deleted'] = '%d album deleted';
$lang['%d album edited'] = '%d album edited';
$lang['%d albums added'] = '%d albums added';
$lang['%d albums deleted'] = '%d albums deleted';
$lang['%d albums edited'] = '%d albums edited';
$lang['%d user added'] = '%d user added';
$lang['%d user deleted'] = '%d user deleted';
$lang['%d user edited'] = '%d user edited';
$lang['%d user logged in'] = '%d user logged in';
$lang['%d user logged out'] = '%d user logged out';
$lang['%d users added'] = '%d users added';
$lang['%d users deleted'] = '%d users deleted';
$lang['%d users edited'] = '%d users edited';
$lang['%d users logged in'] = '%d users logged in';
$lang['%d users logged out'] = '%d users logged out';
$lang['%d photo added'] = '%d photo added';
$lang['%d photo deleted'] = '%d photo deleted';
$lang['%d photo edited'] = '%d photo edited';
$lang['%d photo moved'] = '%d photo moved';
$lang['%d photos added'] = '%d photos added';
$lang['%d photos deleted'] = '%d photos deleted';
$lang['%d photos edited'] = '%d photos edited';
$lang['%d photos moved'] = '%d photos moved';
$lang['%d group added'] = '%d groupe added';
$lang['%d group deleted'] = '%d group deleted';
$lang['%d group edited'] = '%d group edited';
$lang['%d group moved'] = '%d group moved';
$lang['%d groups added'] = '%d groups added';
$lang['%d groups deleted'] = '%d groups deleted';
$lang['%d groups edited'] = '%d groups edited';
$lang['%d groups moved'] = '%d groups moved';
$lang['%d tag added'] = '%d tag added';
$lang['%d tag deleted'] = '%d tag deleted';
$lang['%d tag edited'] = '%d tag edited';
$lang['%d tag moved'] = '%d tag déplacé';
$lang['%d tags added'] = '%d tags added';
$lang['%d tags deleted'] = '%d tags deleted';
$lang['%d tags edited'] = '%d tags edited';
$lang['%d tags moved'] = '%d tags moved';
$lang['Download all activities'] = 'Download all activities';

View file

@ -1174,3 +1174,53 @@ $lang['Cache size'] = "Taille du cache";
$lang['calculated'] = "calculé il y a";
$lang['months ago'] = "mois";
$lang['Delete these sizes'] = 'Supprimer les tailles';
$lang['Activity'] = 'Activité';
$lang['Selected user'] = 'Utilisateur sélectionné';
$lang['Activity time from'] = 'Période d\'activité de';
$lang['to'] = 'à';
$lang['add'] = 'ajout';
$lang['deletion'] = 'suppression';
$lang['move'] = 'déplacement';
$lang['edit'] = 'édition';
$lang['log'] = 'connexion';
$lang['%d album added'] = '%d album ajouté';
$lang['%d album deleted'] = '%d album supprimé';
$lang['%d album edited'] = '%d album édité';
$lang['%d albums added'] = '%d albums ajoutés';
$lang['%d albums deleted'] = '%d albums supprimés';
$lang['%d albums edited'] = '%d albums édité';
$lang['%d user added'] = '%d utilisateur ajouté';
$lang['%d user deleted'] = '%d utilisateur suppprimé';
$lang['%d user edited'] = '%d utilisateur édité';
$lang['%d user logged in'] = '%d utilisateur connecté';
$lang['%d user logged out'] = '%d utilisateur déconnecté';
$lang['%d users added'] = '%d utilisateurs ajoutés';
$lang['%d users deleted'] = '%d utilisateurs supprimés';
$lang['%d users edited'] = '%d utilisateurs édités';
$lang['%d users logged in'] = '%d utilisateurs connectés';
$lang['%d users logged out'] = '%d utilisateurs déconnectés';
$lang['%d photo added'] = '%d photo ajoutée';
$lang['%d photo deleted'] = '%d photo supprimée';
$lang['%d photo edited'] = '%d photo éditée';
$lang['%d photo moved'] = '%d photo déplacée';
$lang['%d photos added'] = '%d photos ajoutées';
$lang['%d photos deleted'] = '%d photos supprimées';
$lang['%d photos edited'] = '%d photos éditées';
$lang['%d photos moved'] = '%d photos déplacées';
$lang['%d group added'] = '%d groupe ajouté';
$lang['%d group deleted'] = '%d groupe supprimé';
$lang['%d group edited'] = '%d groupe édité';
$lang['%d group moved'] = '%d groupe déplacé';
$lang['%d groups added'] = '%d groupes ajoutés';
$lang['%d groups deleted'] = '%d groupes supprimés';
$lang['%d groups edited'] = '%d groupes édités';
$lang['%d groups moved'] = '%d groupes déplacés';
$lang['%d tag added'] = '%d tag ajouté';
$lang['%d tag deleted'] = '%d tag supprimé';
$lang['%d tag edited'] = '%d tag édité';
$lang['%d tag moved'] = '%d tag déplacé';
$lang['%d tags added'] = '%d tags ajoutés';
$lang['%d tags deleted'] = '%d tags supprimés';
$lang['%d tags edited'] = '%d tags édités';
$lang['%d tags moved'] = '%d tags déplacés';
$lang['Download all activities'] = 'Télécharger toutes les activités';

18
ws.php
View file

@ -128,6 +128,24 @@ function ws_addDefaultMethods( $arr )
array('admin_only'=>true)
);
$service->addMethod(
'pwg.activity.getList',
'ws_getActivityList',
null,
'Returns general informations.',
$ws_functions_root . 'pwg.php',
array('admin_only'=>true)
);
$service->addMethod(
'pwg.activity.downloadLog',
'ws_activity_downloadLog',
null,
'Returns general informations.',
$ws_functions_root . 'pwg.php',
array('admin_only'=>true)
);
$service->addMethod(
'pwg.caddie.add',
'ws_caddie_add',