mirror of
https://github.com/Piwigo/Piwigo.git
synced 2026-03-28 17:42:57 +01:00
Issue #1193 : Tag Manager redesign
* Create the new design of tag manager * Replace all actions by ajax actions * Add delete, rename, duplicate and merge tag's functions in the Piwigo API * Modification of group manager to match both designs
This commit is contained in:
171
admin/tags.php
171
admin/tags.php
@@ -14,16 +14,6 @@ if( !defined("PHPWG_ROOT_PATH") )
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
check_status(ACCESS_ADMINISTRATOR);
|
||||
|
||||
if (!empty($_POST))
|
||||
{
|
||||
check_pwg_token();
|
||||
check_input_parameter('tags', $_POST, true, PATTERN_ID);
|
||||
check_input_parameter('selectAction', $_POST, false, '/^[a-zA-Z0-9_-]+$/');
|
||||
check_input_parameter('edit_list', $_POST, false, '/^\d+(,\d+)*$/');
|
||||
check_input_parameter('merge_list', $_POST, false, '/^\d+(,\d+)*$/');
|
||||
check_input_parameter('destination_tag', $_POST, false, PATTERN_ID);
|
||||
}
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | tabs |
|
||||
// +-----------------------------------------------------------------------+
|
||||
@@ -37,64 +27,6 @@ $tabsheet->set_id('tags');
|
||||
$tabsheet->select('');
|
||||
$tabsheet->assign();
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | edit tags |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
if (isset($_POST['edit_submit']))
|
||||
{
|
||||
$query = '
|
||||
SELECT name
|
||||
FROM '.TAGS_TABLE.'
|
||||
;';
|
||||
$existing_names = array_from_query($query, 'name');
|
||||
|
||||
|
||||
$current_name_of = array();
|
||||
$query = '
|
||||
SELECT id, name
|
||||
FROM '.TAGS_TABLE.'
|
||||
WHERE id IN ('.$_POST['edit_list'].')
|
||||
;';
|
||||
$result = pwg_query($query);
|
||||
while ($row = pwg_db_fetch_assoc($result))
|
||||
{
|
||||
$current_name_of[ $row['id'] ] = $row['name'];
|
||||
}
|
||||
|
||||
$updates = array();
|
||||
// we must not rename tag with an already existing name
|
||||
foreach (explode(',', $_POST['edit_list']) as $tag_id)
|
||||
{
|
||||
$tag_name = stripslashes($_POST['tag_name-'.$tag_id]);
|
||||
|
||||
if ($tag_name != $current_name_of[$tag_id])
|
||||
{
|
||||
if (in_array($tag_name, $existing_names))
|
||||
{
|
||||
$page['errors'][] = l10n('Tag "%s" already exists', $tag_name);
|
||||
}
|
||||
else if (!empty($tag_name))
|
||||
{
|
||||
$updates[] = array(
|
||||
'id' => $tag_id,
|
||||
'name' => addslashes($tag_name),
|
||||
'url_name' => trigger_change('render_tag_url', $tag_name),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
mass_updates(
|
||||
TAGS_TABLE,
|
||||
array(
|
||||
'primary' => array('id'),
|
||||
'update' => array('name', 'url_name'),
|
||||
),
|
||||
$updates
|
||||
);
|
||||
|
||||
pwg_activity('tag', explode(',', $_POST['edit_list']), 'edit');
|
||||
}
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | dulicate tags |
|
||||
// +-----------------------------------------------------------------------+
|
||||
@@ -282,67 +214,21 @@ SELECT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | delete tags |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
if (isset($_POST['delete']) and isset($_POST['tags']))
|
||||
{
|
||||
if (!isset($_POST['confirm_deletion']))
|
||||
{
|
||||
$page['errors'][] = l10n('You need to confirm deletion');
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = '
|
||||
SELECT name
|
||||
FROM '.TAGS_TABLE.'
|
||||
WHERE id IN ('.implode(',', $_POST['tags']).')
|
||||
;';
|
||||
$tag_names = array_from_query($query, 'name');
|
||||
|
||||
delete_tags($_POST['tags']);
|
||||
|
||||
$page['infos'][] = l10n_dec(
|
||||
'The following tag was deleted', 'The %d following tags were deleted',
|
||||
count($tag_names)
|
||||
)
|
||||
.' : '.implode(', ', $tag_names);
|
||||
}
|
||||
}
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | delete orphan tags |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
$message_tags = "";
|
||||
|
||||
if (isset($_GET['action']) and 'delete_orphans' == $_GET['action'])
|
||||
{
|
||||
check_pwg_token();
|
||||
|
||||
delete_orphan_tags();
|
||||
$_SESSION['page_infos'] = array(l10n('Orphan tags deleted'));
|
||||
$message_tags = array(l10n('Orphan tags deleted'));
|
||||
redirect(get_root_url().'admin.php?page=tags');
|
||||
}
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | add a tag |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
if (isset($_POST['add']) and !empty($_POST['add_tag']))
|
||||
{
|
||||
$ret = create_tag($_POST['add_tag']);
|
||||
|
||||
if (isset($ret['error']))
|
||||
{
|
||||
$page['errors'][] = $ret['error'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$page['infos'][] = $ret['info'];
|
||||
}
|
||||
}
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | template init |
|
||||
// +-----------------------------------------------------------------------+
|
||||
@@ -360,6 +246,8 @@ $template->assign(
|
||||
// | orphan tags |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
$warning_tags = "";
|
||||
|
||||
$orphan_tags = get_orphan_tags();
|
||||
|
||||
$orphan_tag_names = array();
|
||||
@@ -370,14 +258,23 @@ foreach ($orphan_tags as $tag)
|
||||
|
||||
if (count($orphan_tag_names) > 0)
|
||||
{
|
||||
$page['warnings'][] = sprintf(
|
||||
l10n('You have %d orphan tags: %s.').' <a href="%s" class="icon-trash">'.l10n('Delete orphan tags').'</a>',
|
||||
$warning_tags = sprintf(
|
||||
l10n('You have %d orphan tags: %s.'),
|
||||
count($orphan_tag_names),
|
||||
implode(', ', $orphan_tag_names),
|
||||
get_root_url().'admin.php?page=tags&action=delete_orphans&pwg_token='.get_pwg_token()
|
||||
'<a
|
||||
data-tags=\'["'.implode('" ,"', $orphan_tag_names).'"]\'
|
||||
data-url="'.get_root_url().'admin.php?page=tags&action=delete_orphans&pwg_token='.get_pwg_token().'">'
|
||||
.l10n('See details').'</a>'
|
||||
);
|
||||
}
|
||||
|
||||
$template->assign(
|
||||
array(
|
||||
'warning_tags' => $warning_tags,
|
||||
'message_tags' => $message_tags
|
||||
)
|
||||
);
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | form creation |
|
||||
// +-----------------------------------------------------------------------+
|
||||
@@ -423,38 +320,6 @@ $template->assign(
|
||||
)
|
||||
);
|
||||
|
||||
if ((isset($_POST['edit']) or isset($_POST['duplicate']) or isset($_POST['merge'])) and isset($_POST['tags']))
|
||||
{
|
||||
$list_name = 'EDIT_TAGS_LIST';
|
||||
if (isset($_POST['duplicate']))
|
||||
{
|
||||
$list_name = 'DUPLIC_TAGS_LIST';
|
||||
}
|
||||
elseif (isset($_POST['merge']))
|
||||
{
|
||||
$list_name = 'MERGE_TAGS_LIST';
|
||||
}
|
||||
|
||||
$template->assign($list_name, implode(',', $_POST['tags']));
|
||||
|
||||
$query = '
|
||||
SELECT id, name
|
||||
FROM '.TAGS_TABLE.'
|
||||
WHERE id IN ('.implode(',', $_POST['tags']).')
|
||||
;';
|
||||
$result = pwg_query($query);
|
||||
while ($row = pwg_db_fetch_assoc($result))
|
||||
{
|
||||
$template->append(
|
||||
'tags',
|
||||
array(
|
||||
'ID' => $row['id'],
|
||||
'NAME' => $row['name'],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | sending html code |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
@@ -513,12 +513,12 @@ input:focus + .slider {
|
||||
color:#a0a0a0;
|
||||
}
|
||||
|
||||
.SelectionModeGroup button{
|
||||
#selection-mode-block button{
|
||||
border: 1px solid #e7e7e7;
|
||||
}
|
||||
|
||||
|
||||
.SelectionModeGroup button:hover{
|
||||
#selection-mode-block button:hover{
|
||||
background-color: #ffa744;
|
||||
border: 1px solid #ffa744;
|
||||
}
|
||||
|
||||
@@ -125,4 +125,137 @@ function sprintf() {
|
||||
}
|
||||
|
||||
return o.join('');
|
||||
}
|
||||
|
||||
// Class to implement a temporary state and reverse it
|
||||
class TemporaryState {
|
||||
//Arrays to reverse changes
|
||||
attrChanges = []; //Attribute changes : {object(s), attribute, value}
|
||||
classChanges = []; //Class changes : {object(s), state(add:true/remove:false), class}
|
||||
htmlChanges = []; //Html changes : {object(s), html}
|
||||
|
||||
/**
|
||||
* Change temporaly an attribute of an object
|
||||
* @param {Jquery Object(s)} obj HTML Object(s)
|
||||
* @param {String} attr Attribute
|
||||
* @param {String} tempVal Temporary value of the attribute
|
||||
*/
|
||||
changeAttribute(obj, attr, tempVal) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
this.attrChanges.push({
|
||||
object: $(obj[i]),
|
||||
attribute: attr,
|
||||
value: $(obj[i]).attr(attr)
|
||||
})
|
||||
}
|
||||
obj.attr(attr, tempVal)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/remove a class temporarily
|
||||
* @param {Jquery Object(s)} obj HTML Object
|
||||
* @param {Boolean} st Add (true) or Remove (false) the class
|
||||
* @param {String} loadclass Class Name
|
||||
*/
|
||||
changeClass(obj, st, tempclass) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
if (!($(obj[i]).hasClass(tempclass) && st)) {
|
||||
this.classChanges.push({
|
||||
object: $(obj[i]),
|
||||
state: !st,
|
||||
class: tempclass
|
||||
})
|
||||
if (st)
|
||||
$(obj[i]).addClass(tempclass)
|
||||
else
|
||||
$(obj[i]).removeClass(tempclass)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add temporarily a class to the object
|
||||
* @param {Jquery Object(s)} obj
|
||||
* @param {string} tempclass
|
||||
*/
|
||||
addClass(obj, tempclass) {
|
||||
this.changeClass(obj, true, tempclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove temporarily a class to the object
|
||||
* @param {Jquery Object(s)} obj
|
||||
* @param {string} tempclass
|
||||
*/
|
||||
removeClass(obj, tempclass) {
|
||||
this.changeClass(obj, false, tempclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change temporaly the html of objects (remove event handlers on the actual content)
|
||||
* @param {Jquery Object(s)} obj
|
||||
* @param {string} temphtml
|
||||
*/
|
||||
changeHTML(obj, temphtml) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
this.htmlChanges.push({
|
||||
object:$(obj[i]),
|
||||
html:$(obj[i]).html()
|
||||
})
|
||||
}
|
||||
obj.html(temphtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse all the changes and clear the history
|
||||
*/
|
||||
reverse() {
|
||||
this.attrChanges.forEach(function(change) {
|
||||
if (change.value == undefined) {
|
||||
change.object.removeAttr(change.attribute);
|
||||
} else {
|
||||
change.object.attr(change.attribute, change.value)
|
||||
}
|
||||
})
|
||||
this.classChanges.forEach(function(change) {
|
||||
if (change.state)
|
||||
change.object.addClass(change.class)
|
||||
else
|
||||
change.object.removeClass(change.class)
|
||||
})
|
||||
this.htmlChanges.forEach(function(change) {
|
||||
change.object.html(change.html);
|
||||
})
|
||||
this.attrChanges = [];
|
||||
this.classChanges = [];
|
||||
this.htmlChanges = [];
|
||||
}
|
||||
}
|
||||
|
||||
const jConfirm_alert_options = {
|
||||
icon: 'icon-ok',
|
||||
titleClass: "jconfirmAlert",
|
||||
theme:"modern",
|
||||
closeIcon: true,
|
||||
draggable: false,
|
||||
animation: "zoom",
|
||||
boxWidth: '20%',
|
||||
useBootstrap: false,
|
||||
backgroundDismiss: true,
|
||||
animateFromElement: false,
|
||||
typeAnimated: false,
|
||||
}
|
||||
|
||||
const jConfirm_confirm_options = {
|
||||
draggable: false,
|
||||
titleClass: "jconfirmDeleteConfirm",
|
||||
theme: "modern",
|
||||
content: "",
|
||||
animation: "zoom",
|
||||
boxWidth: '30%',
|
||||
useBootstrap: false,
|
||||
type: 'red',
|
||||
animateFromElement: false,
|
||||
backgroundDismiss: true,
|
||||
typeAnimated: false,
|
||||
}
|
||||
@@ -1,17 +1,4 @@
|
||||
const DELAY_FEEDBACK = 3000;
|
||||
const jConfirm_alert_options = {
|
||||
icon: 'icon-ok',
|
||||
titleClass: "groupAlert",
|
||||
theme:"modern",
|
||||
closeIcon: true,
|
||||
draggable: false,
|
||||
animation: "zoom",
|
||||
boxWidth: '20%',
|
||||
useBootstrap: false,
|
||||
backgroundDismiss: true,
|
||||
animateFromElement: false,
|
||||
typeAnimated: false,
|
||||
}
|
||||
/*-------
|
||||
Group Popin
|
||||
-------*/
|
||||
@@ -265,7 +252,7 @@ var deleteGroup = function (id) {
|
||||
$.confirm({
|
||||
title: str_delete.replace("%s",$("#group-"+id+" #group_name").html()),
|
||||
draggable: false,
|
||||
titleClass: "groupDeleteConfirm",
|
||||
titleClass: "jconfirmDeleteConfirm",
|
||||
theme: "modern",
|
||||
content: "",
|
||||
animation: "zoom",
|
||||
@@ -939,109 +926,4 @@ $(".input-user-name").on("input", function() {
|
||||
while ($(".UsersInGroupList").height() > maxOffsetUserCont) {
|
||||
$(".UsernameBlock").last().remove();
|
||||
}
|
||||
})
|
||||
|
||||
// Class to implement a temporary state and reverse it
|
||||
class TemporaryState {
|
||||
//Arrays to reverse changes
|
||||
attrChanges = []; //Attribute changes : {object(s), attribute, (old) value}
|
||||
classChanges = []; //Class changes : {object(s), state(add:true/remove:false), class}
|
||||
htmlChanges = []; //Html changes : {object(s), (old) html}
|
||||
|
||||
/**
|
||||
* Change temporaly an attribute of an object
|
||||
* @param {Jquery Object(s)} obj HTML Object(s)
|
||||
* @param {String} attr Attribute
|
||||
* @param {String} tempVal Temporary value of the attribute
|
||||
*/
|
||||
changeAttribute(obj, attr, tempVal) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
this.attrChanges.push({
|
||||
object: $(obj[i]),
|
||||
attribute: attr,
|
||||
value: $(obj[i]).attr(attr)
|
||||
})
|
||||
}
|
||||
obj.attr(attr, tempVal)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/remove a class temporarily
|
||||
* @param {Jquery Object(s)} obj HTML Object
|
||||
* @param {Boolean} st Add (true) or Remove (false) the class
|
||||
* @param {String} loadclass Class Name
|
||||
*/
|
||||
changeClass(obj, st, tempclass) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
if (!($(obj[i]).hasClass(tempclass) && st)) {
|
||||
this.classChanges.push({
|
||||
object: $(obj[i]),
|
||||
state: !st,
|
||||
class: tempclass
|
||||
})
|
||||
if (st)
|
||||
$(obj[i]).addClass(tempclass)
|
||||
else
|
||||
$(obj[i]).removeClass(tempclass)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add temporarily a class to the object
|
||||
* @param {Jquery Object(s)} obj
|
||||
* @param {string} tempclass
|
||||
*/
|
||||
addClass(obj, tempclass) {
|
||||
this.changeClass(obj, true, tempclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove temporarily a class to the object
|
||||
* @param {Jquery Object(s)} obj
|
||||
* @param {string} tempclass
|
||||
*/
|
||||
removeClass(obj, tempclass) {
|
||||
this.changeClass(obj, false, tempclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change temporaly the html of objects (remove event handlers on the actual content)
|
||||
* @param {Jquery Object(s)} obj
|
||||
* @param {string} temphtml
|
||||
*/
|
||||
changeHTML(obj, temphtml) {
|
||||
for (let i = 0; i < obj.length; i++) {
|
||||
this.htmlChanges.push({
|
||||
object:$(obj[i]),
|
||||
html:$(obj[i]).html()
|
||||
})
|
||||
}
|
||||
obj.html(temphtml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse all the changes and clear the history
|
||||
*/
|
||||
reverse() {
|
||||
this.attrChanges.forEach(function(change) {
|
||||
if (change.value == undefined) {
|
||||
change.object.removeAttr(change.attribute);
|
||||
} else {
|
||||
change.object.attr(change.attribute, change.value)
|
||||
}
|
||||
})
|
||||
this.classChanges.forEach(function(change) {
|
||||
if (change.state)
|
||||
change.object.addClass(change.class)
|
||||
else
|
||||
change.object.removeClass(change.class)
|
||||
})
|
||||
this.htmlChanges.forEach(function(change) {
|
||||
change.object.html(change.html);
|
||||
})
|
||||
this.attrChanges = [];
|
||||
this.classChanges = [];
|
||||
this.htmlChanges = [];
|
||||
}
|
||||
}
|
||||
})
|
||||
568
admin/themes/default/js/tags.js
Normal file
568
admin/themes/default/js/tags.js
Normal file
@@ -0,0 +1,568 @@
|
||||
//Orphan tags
|
||||
$('.tag-warning p a').on('click', () => {
|
||||
let url = $('.tag-warning p a').data('url');
|
||||
let tags = $('.tag-warning p a').data('tags');
|
||||
let str_orphans = str_orphan_tags.replace('%s1', tags.length).replace('%s2', tags.join(', '));
|
||||
$.confirm({
|
||||
content : str_orphans,
|
||||
title : str_delete_orphan_tags,
|
||||
draggable: false,
|
||||
theme: "modern",
|
||||
animation: "zoom",
|
||||
boxWidth: '30%',
|
||||
useBootstrap: false,
|
||||
type: 'red',
|
||||
animateFromElement: false,
|
||||
backgroundDismiss: true,
|
||||
typeAnimated: false,
|
||||
buttons: {
|
||||
delete : {
|
||||
text:str_delete_them,
|
||||
btnClass: 'btn-red',
|
||||
action: function() {
|
||||
window.location.href = url.replaceAll('amp;', '');
|
||||
}
|
||||
},
|
||||
keep : {
|
||||
text:str_keep_them,
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//Add a tag
|
||||
$('.add-tag-container').on('click', function() {
|
||||
$('#add-tag').addClass('input-mode');
|
||||
})
|
||||
|
||||
$('#add-tag .icon-cancel').on('click', function() {
|
||||
$('#add-tag').removeClass('input-mode');
|
||||
})
|
||||
|
||||
//Display/Hide tag option
|
||||
$('.tag-box').each(function() {
|
||||
setupTagbox($(this))
|
||||
})
|
||||
|
||||
/*-------
|
||||
Add a tag
|
||||
-------*/
|
||||
|
||||
$('#add-tag').submit(function (e) {
|
||||
e.preventDefault();
|
||||
if ($('#add-tag-input').val() != "") {
|
||||
loadState = new TemporaryState();
|
||||
loadState.removeClass($('#add-tag .icon-validate'),'icon-plus-circled');
|
||||
loadState.changeHTML($('#add-tag .icon-validate') , "<i class='icon-spin6 animate-spin'> </i>")
|
||||
loadState.changeAttribute($('#add-tag .icon-validate'), 'style','pointer-event:none')
|
||||
addTag($('#add-tag-input').val()).then(function () {
|
||||
showMessage(str_tag_created.replace('%s', $('#add-tag-input').val()))
|
||||
loadState.reverse();
|
||||
$('#add-tag-input').val("");
|
||||
$('#add-tag').removeClass('input-mode');
|
||||
}).catch(message => {
|
||||
loadState.reverse();
|
||||
showError(message)
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
$('#add-tag .icon-validate').on('click', function () {
|
||||
if ($('#add-tag').hasClass('input-mode')) {
|
||||
$('#add-tag').submit();
|
||||
}
|
||||
})
|
||||
|
||||
function addTag(name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.tags.add",
|
||||
type: "POST",
|
||||
data: "name=" + name + "&pwg_token=" + pwg_token,
|
||||
success: function (raw_data) {
|
||||
data = jQuery.parseJSON(raw_data);
|
||||
if (data.stat === "ok") {
|
||||
newTag = createTagBox(data.result.id, name);
|
||||
$('.tag-container').prepend(newTag);
|
||||
setupTagbox(newTag);
|
||||
resolve();
|
||||
} else {
|
||||
reject(str_already_exist.replace('%s', name));
|
||||
}
|
||||
},
|
||||
error : function (err) {
|
||||
reject(err);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function createTagBox(id, name) {
|
||||
let u_edit = 'admin.php?page=batch_manager&filter=tag-'+id;
|
||||
let u_view = 'index.php?/tags/'+id+'-'+name.toLowerCase().replace(' ', '_');
|
||||
let html = $('.tag-template').html()
|
||||
.replaceAll('%name%', unescape(name))
|
||||
.replace('%U_VIEW%', u_view)
|
||||
.replace('%U_EDIT%', u_edit);
|
||||
newTag = $('<div class="tag-box" data-id='+data.result.id+' data-selected="0">'+html+'</div>');
|
||||
if ($("#toggleSelectionMode").is(":checked")) {
|
||||
newTag.addClass('selection');
|
||||
newTag.find(".in-selection-mode").show();
|
||||
newTag.find(".not-in-selection-mode").hide();
|
||||
}
|
||||
return newTag;
|
||||
}
|
||||
|
||||
/*-------
|
||||
Setup Tag Box
|
||||
-------*/
|
||||
|
||||
function setupTagbox(tagBox) {
|
||||
|
||||
let id = tagBox.data('id');
|
||||
let name = tagBox.find('.tag-name').html();
|
||||
|
||||
//Dropdown options
|
||||
tagBox.find('.showOptions').on('click', function () {
|
||||
tagBox.find(".tag-dropdown-block").css('display', 'grid');
|
||||
})
|
||||
|
||||
$(document).mouseup(function (e) {
|
||||
e.stopPropagation();
|
||||
let option_is_clicked = false
|
||||
tagBox.find('.tag-dropdown-action').each(function () {
|
||||
if (!($(this).has(e.target).length === 0)) {
|
||||
option_is_clicked = true;
|
||||
}
|
||||
})
|
||||
if (!option_is_clicked) {
|
||||
tagBox.find(".tag-dropdown-block").hide();
|
||||
}
|
||||
});
|
||||
|
||||
tagBox.on('click', function() {
|
||||
if (tagBox.hasClass('selection')) {
|
||||
if (tagBox.attr('data-selected') == '1') {
|
||||
tagBox.attr('data-selected', '0');
|
||||
} else {
|
||||
tagBox.attr('data-selected', '1');
|
||||
}
|
||||
updateListItem();
|
||||
}
|
||||
})
|
||||
|
||||
//Edit Name
|
||||
tagBox.find('.tag-dropdown-action.edit').on('click', function() {
|
||||
tagBox.addClass('edit-name');
|
||||
})
|
||||
|
||||
tagBox.find('.tag-rename .icon-cancel').on('click', function() {
|
||||
tagBox.removeClass('edit-name');
|
||||
})
|
||||
|
||||
tagBox.find('.tag-rename .validate').on('click', function() {
|
||||
tagBox.find('.tag-rename form').submit();
|
||||
})
|
||||
|
||||
tagBox.find('.tag-rename form').submit(function (e) {
|
||||
e.preventDefault();
|
||||
new_name = tagBox.find('.tag-rename .tag-name-editable').val();
|
||||
if (new_name != "") {
|
||||
let loadState = new TemporaryState();
|
||||
loadState.removeClass(tagBox.find('.tag-rename .validate'), 'icon-ok');
|
||||
loadState.changeHTML(tagBox.find('.tag-rename .validate'), "<i class='icon-spin6 animate-spin'> </i>");
|
||||
renameTag(id, new_name).then(() => {
|
||||
showMessage(str_tag_renamed.replace('%s1', name).replace('%s2', new_name));
|
||||
loadState.reverse();
|
||||
tagBox.removeClass('edit-name');
|
||||
name = new_name;
|
||||
}).catch((message) => {
|
||||
loadState.reverse();
|
||||
showError(message);
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
//Delete Tag
|
||||
tagBox.find('.tag-dropdown-action.delete').on('click', function () {
|
||||
$.confirm({
|
||||
title: str_delete.replace("%s",name),
|
||||
buttons: {
|
||||
confirm: {
|
||||
text: str_yes_delete_confirmation,
|
||||
btnClass: 'btn-red',
|
||||
action: function () {
|
||||
removeTag(id, name);
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
text: str_no_delete_confirmation
|
||||
}
|
||||
},
|
||||
...jConfirm_confirm_options
|
||||
})
|
||||
})
|
||||
|
||||
//Duplicate Tag
|
||||
tagBox.find('.tag-dropdown-action.duplicate').on('click', function () {
|
||||
duplicateTag(id, name).then((data) => {
|
||||
showMessage(str_tag_created.replace('%s',data.result.name))
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function removeTag(id, name) {
|
||||
$.alert({
|
||||
title : str_tag_deleted.replace("%s",name),
|
||||
content: function() {
|
||||
return jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.tags.delete",
|
||||
type: "POST",
|
||||
data: "tag_id=" + id + "&pwg_token=" + pwg_token,
|
||||
success: function (raw_data) {
|
||||
data = jQuery.parseJSON(raw_data);
|
||||
showMessage(str_tag_deleted.replace('%s', name));
|
||||
if (data.stat === "ok") {
|
||||
$('.tag-box[data-id='+id+']').remove();
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
...jConfirm_alert_options
|
||||
});
|
||||
}
|
||||
|
||||
function renameTag(id, new_name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.tags.rename",
|
||||
type: "POST",
|
||||
data: "tag_id=" + id + "&new_name=" + new_name + "&pwg_token=" + pwg_token,
|
||||
success: function (raw_data) {
|
||||
data = jQuery.parseJSON(raw_data);
|
||||
if (data.stat === "ok") {
|
||||
$('.tag-box[data-id='+id+'] p').html(data.result.name);
|
||||
$('.tag-box[data-id='+id+'] .tag-name-editable').attr('placeholder', data.result.name);
|
||||
resolve(data);
|
||||
} else {
|
||||
reject(str_already_exist.replace('%s', new_name))
|
||||
}
|
||||
},
|
||||
error:function(XMLHttpRequest) {
|
||||
reject(XMLHttpRequest.statusText);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function duplicateTag(id, name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
copy_name = name + str_copy;
|
||||
|
||||
let name_exist = function(name) {
|
||||
exist = false;
|
||||
$(".tag-box .tag-name").each(function () {
|
||||
if ($(this).html() === name)
|
||||
exist = true
|
||||
})
|
||||
return exist;
|
||||
}
|
||||
|
||||
let i = 1;
|
||||
while (name_exist(copy_name))
|
||||
{
|
||||
copy_name = name + str_other_copy.replace("%s", i++)
|
||||
}
|
||||
|
||||
jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.tags.duplicate",
|
||||
type: "POST",
|
||||
data: "tag_id=" + id + "©_name=" + copy_name + "&pwg_token=" + pwg_token,
|
||||
success: function (raw_data) {
|
||||
data = jQuery.parseJSON(raw_data);
|
||||
if (data.stat === "ok") {
|
||||
newTag = createTagBox(data.result.id, data.result.name);
|
||||
newTag.insertAfter($('.tag-box[data-id='+id+']'));
|
||||
if ($('.tag-box[data-id='+id+'] .tag-dropdown-action.view').css('display') == 'inline') {
|
||||
newTag.find('.tag-dropdown-action.view').show();
|
||||
newTag.find('.tag-dropdown-action.manage').show();
|
||||
}
|
||||
setupTagbox(newTag);
|
||||
resolve(data);
|
||||
}
|
||||
},
|
||||
error:function(XMLHttpRequest) {
|
||||
reject(XMLHttpRequest.statusText);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*-------
|
||||
Selection mode
|
||||
-------*/
|
||||
$("#toggleSelectionMode").attr("checked", false)
|
||||
$("#toggleSelectionMode").click(function () {
|
||||
if ($(this).is(":checked")) {
|
||||
$(".in-selection-mode").show();
|
||||
$(".not-in-selection-mode").removeAttr('style');
|
||||
$(".tag-box").addClass("selection");
|
||||
$(".tag-box").removeClass('edit-name');
|
||||
} else {
|
||||
$(".in-selection-mode").removeAttr('style');
|
||||
$(".not-in-selection-mode").show();
|
||||
$(".tag-box").removeClass("selection");
|
||||
$(".tag-box").attr("data-selected", '0');
|
||||
updateListItem();
|
||||
}
|
||||
});
|
||||
|
||||
function updateListItem() {
|
||||
|
||||
let nowSelected = [];
|
||||
let selected = [];
|
||||
let shouldBeItem = [];
|
||||
let shouldNotBeItem = [];
|
||||
let names = {};
|
||||
$('.tag-box[data-selected="1"]').each(function () {
|
||||
let id = $(this).attr('data-id');
|
||||
nowSelected.push(id);
|
||||
names[id] = $(this).find('.tag-name').html();
|
||||
});
|
||||
|
||||
$('.selection-mode-tag .tag-list div').each(function () {
|
||||
let id = $(this).attr('data-id');
|
||||
selected.push(id);
|
||||
});
|
||||
|
||||
shouldNotBeItem = [...selected];
|
||||
shouldNotBeItem = shouldNotBeItem.filter(x => !nowSelected.includes(x));
|
||||
shouldBeItem = [...nowSelected];
|
||||
shouldBeItem = shouldBeItem.filter(x => !selected.includes(x));
|
||||
selected = nowSelected;
|
||||
|
||||
shouldBeItem.forEach(function(id) {
|
||||
let newItemStructure = $('<div data-id="'+id+'"><a class="icon-cancel"></a><p>'+names[id]+'</p> </div>');
|
||||
$('.selection-mode-tag .tag-list').prepend(newItemStructure);
|
||||
$('.selection-mode-tag .tag-list div[data-id='+id+'] a').on('click', function () {
|
||||
$('.tag-box[data-id='+id+']').attr('data-selected', '0');
|
||||
updateListItem();
|
||||
})
|
||||
})
|
||||
|
||||
shouldNotBeItem.forEach(function(id) {
|
||||
$('.selection-mode-tag .tag-list div[data-id='+id+']').remove();
|
||||
})
|
||||
|
||||
$('#MergeOptionsChoices').html('');
|
||||
nowSelected.forEach(id => {
|
||||
$('#MergeOptionsChoices').append(
|
||||
$('<option value="'+id+'">'+names[id]+'</option>')
|
||||
)
|
||||
})
|
||||
|
||||
updateSelectionContent()
|
||||
}
|
||||
|
||||
mergeOption = false;
|
||||
|
||||
function updateSelectionContent() {
|
||||
number = $('.tag-box[data-selected="1"]').length;
|
||||
if (number == 0) {
|
||||
$('#nothing-selected').show();
|
||||
$('.selection-mode-tag').hide();
|
||||
$('#MergeOptionsBlock').hide();
|
||||
} else if (number == 1) {
|
||||
mergeOption = false;
|
||||
$('#nothing-selected').hide();
|
||||
$('.selection-mode-tag').show();
|
||||
$('#MergeOptionsBlock').hide();
|
||||
$('#MergeSelectionMode').addClass('unavailable');
|
||||
} else if (number > 1) {
|
||||
$('#MergeSelectionMode').removeClass('unavailable');
|
||||
if (mergeOption) {
|
||||
$('#MergeOptionsBlock').show();
|
||||
$('.selection-mode-tag').hide();
|
||||
} else {
|
||||
$('#MergeOptionsBlock').hide();
|
||||
$('.selection-mode-tag').show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$('#MergeSelectionMode').on('click', function() {
|
||||
mergeOption = true;
|
||||
updateSelectionContent()
|
||||
});
|
||||
|
||||
$('#CancelMerge').on('click', function() {
|
||||
mergeOption = false;
|
||||
updateSelectionContent()
|
||||
});
|
||||
|
||||
/*-------
|
||||
Actions in selection mode
|
||||
-------*/
|
||||
|
||||
//Remove tags
|
||||
$('#DeleteSelectionMode').on('click', function() {
|
||||
names = [];
|
||||
|
||||
$('.tag-box[data-selected=1]').each(function() {
|
||||
names.push($(this).find('.tag-name').html());
|
||||
})
|
||||
|
||||
$.confirm({
|
||||
title: str_delete_tags.replace("%s",names.join(', ')),
|
||||
buttons: {
|
||||
confirm: {
|
||||
text: str_yes_delete_confirmation,
|
||||
btnClass: 'btn-red',
|
||||
action: function () {
|
||||
removeSelectedTags();
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
text: str_no_delete_confirmation
|
||||
}
|
||||
},
|
||||
...jConfirm_confirm_options
|
||||
});
|
||||
})
|
||||
|
||||
function removeSelectedTags() {
|
||||
str_id = "";
|
||||
names = [];
|
||||
ids = [];
|
||||
|
||||
$('.tag-box[data-selected=1]').each(function() {
|
||||
id = $(this).data('id');
|
||||
ids.push(id);
|
||||
names.push($(this).find('.tag-name').html());
|
||||
str_id += "tag_id[]=" + id + "&";
|
||||
})
|
||||
|
||||
console.log(names);
|
||||
|
||||
$.alert({
|
||||
title : str_tags_deleted.replace("%s",names.join(', ')),
|
||||
content: function() {
|
||||
return jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.tags.delete",
|
||||
type: "POST",
|
||||
data: str_id + "pwg_token=" + pwg_token,
|
||||
success: function (raw_data) {
|
||||
data = jQuery.parseJSON(raw_data);
|
||||
if (data.stat === "ok") {
|
||||
ids.forEach(function(id) {
|
||||
$('.tag-box[data-id='+id+']').remove();
|
||||
})
|
||||
updateListItem();
|
||||
showMessage(str_tags_deleted.replace('%s', names.join(', ')));
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
...jConfirm_alert_options
|
||||
});
|
||||
}
|
||||
|
||||
//Merge Tags
|
||||
$('.ConfirmMergeButton').on('click',() => {
|
||||
merge_ids = [];
|
||||
$('.tag-box[data-selected=1]').each(function() {
|
||||
merge_ids.push($(this).data('id'))
|
||||
})
|
||||
dest_id = $('#MergeOptionsChoices').val();
|
||||
mergeGroups(dest_id, merge_ids)
|
||||
})
|
||||
|
||||
function mergeGroups(destination_id, merge_ids) {
|
||||
|
||||
destination_name = $('.tag-box[data-id='+destination_id+'] .tag-name').html();
|
||||
merge_name = [];
|
||||
|
||||
merge_ids.forEach((id) =>{
|
||||
merge_name.push($('.tag-box[data-id='+id+'] .tag-name').html());
|
||||
})
|
||||
|
||||
str_message = str_merged_into
|
||||
.replace('%s1', merge_name.join(', '))
|
||||
.replace('%s2', destination_name)
|
||||
|
||||
$.alert({
|
||||
title : str_message,
|
||||
content: function() {
|
||||
return jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.tags.merge",
|
||||
type: "POST",
|
||||
data: "destination_tag_id=" + destination_id
|
||||
+ "&merge_tag_id[]=" + merge_ids.join('&merge_tag_id[]=')
|
||||
+ "&pwg_token=" + pwg_token,
|
||||
success: function (raw_data) {
|
||||
data = jQuery.parseJSON(raw_data);
|
||||
if (data.stat === "ok") {
|
||||
console.log()
|
||||
data.result.deleted_tag.forEach((id) => {
|
||||
if (data.result.destination_tag != id)
|
||||
$('.tag-box[data-id='+id+']').remove();
|
||||
})
|
||||
if (data.result.images_in_merged_tag.length > 0) {
|
||||
tagBox = $('.tag-box[data-id='+data.result.destination_tag+']')
|
||||
tagBox.find('.tag-dropdown-action.view, .tag-dropdown-action.manage').show();
|
||||
}
|
||||
showMessage(str_message);
|
||||
$(".tag-box").attr("data-selected", '0');
|
||||
updateListItem();
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
...jConfirm_alert_options
|
||||
});
|
||||
}
|
||||
|
||||
/*-------
|
||||
Filter research
|
||||
-------*/
|
||||
|
||||
$("#search-tag .search-input").on("input", function() {
|
||||
let text = $(this).val().toLowerCase();
|
||||
var searchNumber = 0;
|
||||
$('.tag-box').each(function () {
|
||||
if (text == "") {
|
||||
$(this).fadeIn()
|
||||
searchNumber++;
|
||||
} else {
|
||||
let name = $(this).find("p").text().toLowerCase();
|
||||
if (name.search(text) != -1){
|
||||
$(this).delay(300).fadeIn()
|
||||
searchNumber++;
|
||||
} else {
|
||||
$(this).fadeOut()
|
||||
}
|
||||
}
|
||||
})
|
||||
if (searchNumber == 0) {
|
||||
$('.emptyResearch').delay(300).fadeIn();
|
||||
} else {
|
||||
$('.emptyResearch').fadeOut();
|
||||
}
|
||||
})
|
||||
|
||||
/*-------
|
||||
Show Info
|
||||
-------*/
|
||||
function showError(message) {
|
||||
$('.tag-error p').html(message);
|
||||
$('.tag-info').hide()
|
||||
$('.tag-error').css('display', 'flex');
|
||||
}
|
||||
|
||||
function showMessage(message) {
|
||||
$('.tag-message p').html(message);
|
||||
$('.tag-info').hide()
|
||||
$('.tag-message').css('display', 'flex');
|
||||
}
|
||||
@@ -24,6 +24,9 @@ var serverId = '{$CACHE_KEYS._hash}'
|
||||
var rootUrl = '{$ROOT_URL}'
|
||||
{/footer_script}
|
||||
|
||||
{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
|
||||
{combine_script id='group_list' load='footer' path='admin/themes/default/js/group_list.js'}
|
||||
|
||||
{combine_script id='jquery.selectize' load='footer' path='themes/default/js/plugins/selectize.min.js'}
|
||||
{combine_css path="themes/default/js/plugins/selectize.{$themeconf.colorscheme}.css"}
|
||||
|
||||
@@ -33,8 +36,6 @@ var rootUrl = '{$ROOT_URL}'
|
||||
{combine_css path="themes/default/js/plugins/jquery-confirm.min.css"}
|
||||
{combine_css path="admin/themes/default/fontello/css/animation.css"}
|
||||
|
||||
{combine_script id='common' load='footer' path='admin/themes/default/js/group_list.js'}
|
||||
|
||||
{* Define template function for the content of Groups*}
|
||||
{function name=groupContent}
|
||||
{function groupContent}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{footer_script require='jquery'}{literal}
|
||||
jQuery(document).ready(function(){
|
||||
jQuery(".tagSelection").on("click", "label", function () {
|
||||
var parent = jQuery(this).parent('li');
|
||||
var checkbox = jQuery(this).children("input[type=checkbox]");
|
||||
|
||||
if (jQuery(checkbox).is(':checked')) {
|
||||
parent.addClass("tagSelected");
|
||||
}
|
||||
else {
|
||||
parent.removeClass('tagSelected');
|
||||
}
|
||||
});
|
||||
});
|
||||
{/literal}{/footer_script}
|
||||
@@ -1,336 +1,135 @@
|
||||
{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
|
||||
{include file='include/tag_selection.inc.tpl'}
|
||||
|
||||
{html_style}
|
||||
.showInfo { text-indent:5px; }
|
||||
form fieldset p { margin-left:0; }
|
||||
{/html_style}
|
||||
|
||||
{footer_script require='jquery'}
|
||||
/**
|
||||
* Add tag
|
||||
*/
|
||||
jQuery("#addTag").click(function() {
|
||||
jQuery("#addTagForm").toggle();
|
||||
jQuery("input[name=add_tag]").focus();
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery("#addTagClose").click(function() {
|
||||
jQuery("#addTagForm").hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery("#selectionMode").click(function() {
|
||||
if (jQuery(this).hasClass("icon-check-empty")) {
|
||||
jQuery("#selectionMode").removeClass("icon-check-empty").addClass("icon-check");
|
||||
jQuery('label.font-checkbox span').show();
|
||||
jQuery('ul.tagSelection a.showInfo').hide();
|
||||
jQuery('fieldset#action').show();
|
||||
jQuery('fieldset#selectTags legend').html("{'Tag selection'|translate|escape:javascript}");
|
||||
}
|
||||
else {
|
||||
jQuery("#selectionMode").removeClass("icon-check").addClass("icon-check-empty");
|
||||
jQuery('label.font-checkbox span').hide();
|
||||
jQuery('ul.tagSelection a.showInfo').show();
|
||||
jQuery('fieldset#action').hide();
|
||||
jQuery('fieldset#selectTags legend').html("{'Tags'|translate|escape:javascript}");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
jQuery('.showInfo').tipTip({
|
||||
'delay' : 0,
|
||||
'fadeIn' : 200,
|
||||
'fadeOut' : 200,
|
||||
'maxWidth':'300px',
|
||||
'keepAlive':true,
|
||||
'activation':'click'
|
||||
});
|
||||
|
||||
function displayDeletionWarnings() {
|
||||
jQuery(".warningDeletion").show();
|
||||
jQuery("input[name=destination_tag]:checked").parent("label").children(".warningDeletion").hide();
|
||||
}
|
||||
|
||||
displayDeletionWarnings();
|
||||
|
||||
jQuery("#mergeTags label").click(function() {
|
||||
displayDeletionWarnings();
|
||||
});
|
||||
|
||||
$("#searchInput").on("keydown", function(e) {
|
||||
var $this = $(this),
|
||||
timer = $this.data("timer");
|
||||
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
|
||||
$this.data("timer", setTimeout(function() {
|
||||
var val = $this.val();
|
||||
if (!val) {
|
||||
$(".tagSelection>li").show();
|
||||
$("#filterIcon").css("visibility","hidden");
|
||||
}
|
||||
else {
|
||||
$("#filterIcon").css("visibility","visible");
|
||||
var regex = new RegExp( val.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"), "i" );
|
||||
$(".tagSelection>li").each(function() {
|
||||
var $li = $(this),
|
||||
text = $.trim( $("label", $li).text() );
|
||||
$li.toggle(regex.test(text));
|
||||
});
|
||||
}
|
||||
|
||||
}, 300) );
|
||||
|
||||
if (e.keyCode == 13) { // Enter
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('input[name="tags[]"]').click(function() {
|
||||
var nbSelected = 0;
|
||||
nbSelected = jQuery('input[name="tags[]"]').filter(':checked').length;
|
||||
|
||||
if (nbSelected == 0) {
|
||||
jQuery("#permitAction").hide();
|
||||
jQuery("#forbidAction").show();
|
||||
}
|
||||
else {
|
||||
jQuery("#permitAction").show();
|
||||
jQuery("#forbidAction").hide();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery("[id^=action_]").hide();
|
||||
|
||||
jQuery("select[name=selectAction]").change(function () {
|
||||
jQuery("[id^=action_]").hide();
|
||||
|
||||
jQuery("#action_"+jQuery(this).prop("value")).show();
|
||||
|
||||
jQuery("#displayFormBlock").hide();
|
||||
jQuery("#applyActionBlock").hide();
|
||||
|
||||
if (jQuery(this).val() != -1 ) {
|
||||
if (jQuery(this).val() == 'delete') {
|
||||
jQuery("#applyActionBlock").show();
|
||||
jQuery("#applyAction").attr("name", jQuery(this).val());
|
||||
}
|
||||
else {
|
||||
jQuery("#displayForm").attr("name", jQuery(this).val());
|
||||
jQuery("#displayFormBlock").show();
|
||||
}
|
||||
}
|
||||
else {
|
||||
}
|
||||
});
|
||||
|
||||
jQuery("form").submit(function() {
|
||||
if (jQuery("select[name=selectAction]").val() == "delete") {
|
||||
if (!jQuery("input[name=confirm_deletion]").is(":checked")) {
|
||||
jQuery("#action_delete .errors").show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (jQuery("select[name=selectAction]").val() == "merge") {
|
||||
if (jQuery("ul.tagSelection input[type=checkbox]:checked").length < 2) {
|
||||
alert("{'Select at least two tags for merging'|@translate}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery("input[name=confirm_deletion]").change(function() {
|
||||
jQuery("#action_delete .errors").hide();
|
||||
});
|
||||
{footer_script}
|
||||
var pwg_token = "{$PWG_TOKEN}";
|
||||
var str_delete = '{'Delete tag "%s"?'|@translate}'
|
||||
var str_delete_tags = '{'Delete tags \{%s\}?'|@translate}'
|
||||
var str_yes_delete_confirmation = "{'Yes, delete'|@translate}"
|
||||
var str_no_delete_confirmation = "{"No, I have changed my mind"|@translate}"
|
||||
var str_tag_deleted = '{'Tag "%s" succesfully deleted'|@translate}'
|
||||
var str_tags_deleted = '{'Tags \{%s\} succesfully deleted'|@translate}'
|
||||
var str_already_exist = '{'Tag "%s" already exists'|@translate}'
|
||||
var str_tag_created = '{'Tag "%s" created'|@translate}'
|
||||
var str_tag_renamed = '{'Tag "%s1" renamed in "%s2"'|@translate}'
|
||||
var str_delete_orphan_tags = '{'Delete orphan tags ?'|@translate}'
|
||||
var str_orphan_tags = '{'You have %s1 orphan : %s2'|@translate}';
|
||||
var str_delete_them = '{'Delete them'|@translate}';
|
||||
var str_keep_them = '{'Keep them'|@translate}';
|
||||
var str_copy = '{' (copy)'|@translate}'
|
||||
var str_other_copy = '{' (copy %s)'|@translate}'
|
||||
var str_merged_into = '{'Tag(s) \{%s1\} succesfully merged into "%s2"'|@translate}'
|
||||
{/footer_script}
|
||||
|
||||
{combine_script id='common' load='footer' path='admin/themes/default/js/common.js'}
|
||||
{combine_script id='jquery.confirm' load='footer' require='jquery' path='themes/default/js/plugins/jquery-confirm.min.js'}
|
||||
{combine_css path="themes/default/js/plugins/jquery-confirm.min.css"}
|
||||
{combine_css path="admin/themes/default/fontello/css/animation.css"}
|
||||
{combine_script id='tiptip' load='header' path='themes/default/js/plugins/jquery.tipTip.minified.js'}
|
||||
{combine_script id='tags' load='footer' path='admin/themes/default/js/tags.js'}
|
||||
|
||||
{function name=tagContent}
|
||||
{function tagContent}
|
||||
<p class='tag-name'>{$tag_name}</p>
|
||||
<a class="icon-ellipsis-vert showOptions not-in-selection-mode"></a>
|
||||
<div class="tag-dropdown-block">
|
||||
<a class='tag-dropdown-action icon-eye view' href="{$tag_U_VIEW}" {if !$has_image} style='display:none' {/if}>{'View in gallery'|@translate}</a>
|
||||
<a class='tag-dropdown-action icon-picture manage' href="{$tag_U_EDIT}" {if !$has_image} style='display:none' {/if}>{'Manage photos'|@translate}</a>
|
||||
<a class='tag-dropdown-action icon-pencil edit'> {'Edit'|@translate}</a>
|
||||
<a class='tag-dropdown-action icon-trash delete'> {'Delete'|@translate}</a>
|
||||
<a class='tag-dropdown-action icon-docs duplicate'> {'Duplicate'|@translate}</a>
|
||||
</div>
|
||||
<span class="select-checkbox in-selection-mode">
|
||||
<i class="icon-ok"> </i>
|
||||
</span>
|
||||
<div class="tag-rename">
|
||||
<form>
|
||||
<input type="text" class="tag-name-editable" placeholder="{$tag_name}">
|
||||
<input type="submit" hidden>
|
||||
</form>
|
||||
<span class="icon-ok validate"></span>
|
||||
<span class="icon-cancel"></span>
|
||||
</div>
|
||||
{/function}
|
||||
{/function}
|
||||
|
||||
<div class="titrePage">
|
||||
<h2>{'Manage tags'|@translate}</h2>
|
||||
</div>
|
||||
|
||||
{if !isset($EDIT_TAGS_LIST) and !isset($DUPLIC_TAGS_LIST) and !isset($MERGE_TAGS_LIST)}
|
||||
<p class="showCreateAlbum" id="showAddTag">
|
||||
<a class="icon-plus-circled" href="#" id="addTag">{'Add a tag'|translate}</a>
|
||||
<a class="icon-check-empty" href="#" id="selectionMode">{'Select tags'|translate}</a>
|
||||
</p>
|
||||
<div class="selection-mode-group-manager">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="toggleSelectionMode">
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
<p>{'Selection mode'|@translate}</p>
|
||||
</div>
|
||||
|
||||
<form method="post" style="display:none" id="addTagForm" name="add_user" action="{$F_ACTION}" class="properties">
|
||||
<input type="hidden" name="pwg_token" value="{$PWG_TOKEN}">
|
||||
<div id="selection-mode-block" class="in-selection-mode tag-selection">
|
||||
<div class="tag-selection-content">
|
||||
|
||||
<fieldset class="with-border">
|
||||
<legend>{'Add a tag'|@translate}</legend>
|
||||
<p id="nothing-selected">{'No tag selected, no action possible.'|@translate}</p>
|
||||
|
||||
<label>
|
||||
{'New tag'|@translate}
|
||||
<input type="text" name="add_tag" size="50">
|
||||
</label>
|
||||
<div class="selection-mode-tag">
|
||||
<p>{'Your selection'|@translate}</p>
|
||||
<div class="tag-list">
|
||||
|
||||
</div>
|
||||
<button id="MergeSelectionMode" class="icon-object-group unavailable">{'Merge'|@translate}</button>
|
||||
<button id="DeleteSelectionMode" class="icon-trash-1">{'Delete selected tags'|@translate}</button>
|
||||
</div>
|
||||
|
||||
<p class="actionButtons">
|
||||
<input class="submit" type="submit" name="add" value="{'Submit'|@translate}">
|
||||
<a href="#" id="addTagClose">{'Cancel'|@translate}</a>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
<form action="{$F_ACTION}" method="post">
|
||||
<input type="hidden" name="pwg_token" value="{$PWG_TOKEN}">
|
||||
|
||||
{if isset($EDIT_TAGS_LIST)}
|
||||
<fieldset>
|
||||
<legend>{'Edit tags'|@translate}</legend>
|
||||
<input type="hidden" name="edit_list" value="{$EDIT_TAGS_LIST}">
|
||||
<table class="table2">
|
||||
<tr class="throw">
|
||||
<th>{'Current name'|@translate}</th>
|
||||
<th>{'New name'|@translate}</th>
|
||||
</tr>
|
||||
{foreach from=$tags item=tag}
|
||||
<tr>
|
||||
<td>{$tag.NAME}</td>
|
||||
<td><input type="text" name="tag_name-{$tag.ID}" value="{$tag.NAME}" size="50"></td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<input type="submit" name="edit_submit" value="{'Submit'|@translate}">
|
||||
<input type="submit" name="edit_cancel" value="{'Cancel'|@translate}">
|
||||
</p>
|
||||
</fieldset>
|
||||
{/if}
|
||||
|
||||
{if isset($DUPLIC_TAGS_LIST)}
|
||||
<fieldset>
|
||||
<legend>{'Edit tags'|@translate}</legend>
|
||||
<input type="hidden" name="edit_list" value="{$DUPLIC_TAGS_LIST}">
|
||||
<table class="table2">
|
||||
<tr class="throw">
|
||||
<th>{'Source tag'|@translate}</th>
|
||||
<th>{'Name of the duplicate'|@translate}</th>
|
||||
</tr>
|
||||
{foreach from=$tags item=tag}
|
||||
<tr>
|
||||
<td>{$tag.NAME}</td>
|
||||
<td><input type="text" name="tag_name-{$tag.ID}" value="{$tag.NAME}" size="50"></td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<input type="submit" name="duplic_submit" value="{'Submit'|@translate}">
|
||||
<input type="submit" name="duplic_cancel" value="{'Cancel'|@translate}">
|
||||
</p>
|
||||
</fieldset>
|
||||
{/if}
|
||||
|
||||
{if isset($MERGE_TAGS_LIST)}
|
||||
<fieldset id="mergeTags">
|
||||
<legend>{'Merge tags'|@translate}</legend>
|
||||
{'Select the destination tag'|@translate}
|
||||
|
||||
<p>
|
||||
{foreach from=$tags item=tag name=tagloop}
|
||||
<label><input type="radio" name="destination_tag" value="{$tag.ID}"{if $smarty.foreach.tagloop.index == 0} checked="checked"{/if}> {$tag.NAME}<span class="warningDeletion"> {'(this tag will be deleted)'|@translate}</span></label><br>
|
||||
{/foreach}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="hidden" name="merge_list" value="{$MERGE_TAGS_LIST}">
|
||||
<input type="submit" name="merge_submit" value="{'Confirm merge'|@translate}">
|
||||
<input type="submit" name="merge_cancel" value="{'Cancel'|@translate}">
|
||||
</p>
|
||||
</fieldset>
|
||||
{/if}
|
||||
|
||||
{if !isset($EDIT_TAGS_LIST) and !isset($DUPLIC_TAGS_LIST) and !isset($MERGE_TAGS_LIST)}
|
||||
|
||||
<fieldset id="selectTags">
|
||||
<legend>{'Tags'|@translate}</legend>
|
||||
|
||||
{if count($all_tags)}
|
||||
<div><label><span class="icon-filter" style="visibility:hidden" id="filterIcon"></span>{'Search'|@translate} <input id="searchInput" type="text" size="12"></label></div>
|
||||
{/if}
|
||||
|
||||
<ul class="tagSelection">
|
||||
{foreach from=$all_tags item=tag}
|
||||
<li>
|
||||
{capture name='showInfo'}{strip}
|
||||
<b>{$tag.name}</b> ({$tag.counter|@translate_dec:'%d photo':'%d photos'})<br>
|
||||
<a href="{$tag.U_VIEW}">{'View in gallery'|@translate}</a> |
|
||||
<a href="{$tag.U_EDIT}">{'Manage photos'|@translate}</a>
|
||||
{if !empty($tag.alt_names)}<br>{$tag.alt_names}{/if}
|
||||
{/strip}{/capture}
|
||||
<a class="icon-info-circled-1 showInfo" title="{$smarty.capture.showInfo|@htmlspecialchars}"></a>
|
||||
<label class="font-checkbox no-bold">
|
||||
<span class="icon-check" style="display:none"></span>
|
||||
<input type="checkbox" name="tags[]" value="{$tag.id}">
|
||||
{$tag.name}
|
||||
</label>
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="action" style="display:none">
|
||||
<legend>{'Action'|@translate}</legend>
|
||||
<div id="forbidAction">{'No tag selected, no action possible.'|@translate}</div>
|
||||
<div id="permitAction" style="display:none">
|
||||
|
||||
<select name="selectAction">
|
||||
<option value="-1">{'Choose an action'|@translate}</option>
|
||||
<option disabled="disabled">------------------</option>
|
||||
<option value="edit">{'Edit selected tags'|@translate}</option>
|
||||
<option value="duplicate">{'Duplicate selected tags'|@translate}</option>
|
||||
<option value="merge">{'Merge selected tags'|@translate}</option>
|
||||
<option value="delete">{'Delete selected tags'|@translate}</option>
|
||||
{if !empty($tag_manager_plugin_actions)}
|
||||
{foreach from=$tag_manager_plugin_actions item=action}
|
||||
<option value="{$action.ID}">{$action.NAME}</option>
|
||||
{/foreach}
|
||||
{/if}
|
||||
<div id="MergeOptionsBlock">
|
||||
<p>{'Choose which tag to merge these tags into'|@translate}</p>
|
||||
<p class="ItalicTextInfo">{'The other tags will be removed'|@translate}</p>
|
||||
<div class="MergeOptionsContainer">
|
||||
<select id="MergeOptionsChoices">
|
||||
</select>
|
||||
</div>
|
||||
<button class="icon-ok ConfirmMergeButton">Confirm merge</button>
|
||||
<a id="CancelMerge">Cancel</a>
|
||||
</div>
|
||||
|
||||
<!-- delete -->
|
||||
<div id="action_delete" class="bulkAction">
|
||||
<p>
|
||||
<label class="font-checkbox">
|
||||
<span class="icon-check"></span>
|
||||
<input type="checkbox" name="confirm_deletion" value="1">
|
||||
{'Are you sure?'|@translate}
|
||||
</label>
|
||||
<span class="errors" style="display:none"><i class="icon-cancel"></i> we really need you to confirm</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* plugins *}
|
||||
{if !empty($tag_manage_plugin_actions)}
|
||||
{foreach from=$element_set_groupe_plugins_actions item=action}
|
||||
<div id="action_{$action.ID}" class="bulkAction">
|
||||
{if !empty($action.CONTENT)}{$action.CONTENT}{/if}
|
||||
</div>
|
||||
<div class='tag-header'>
|
||||
<div id='search-tag'>
|
||||
<span class='icon-filter'> </span>
|
||||
<input class='search-input' type='text' placeholder='{'Search'|@translate}'>
|
||||
</div>
|
||||
<form id='add-tag'>
|
||||
<span class='icon-cancel'></span>
|
||||
<span class='icon-plus-circled icon-validate'></span>
|
||||
<label class='add-tag-container'>
|
||||
<p>{'Add a tag'|@translate}</p>
|
||||
<input type='text' id='add-tag-input' placeholder="{'Add a tag'|@translate}">
|
||||
<input type='submit' hidden>
|
||||
</label>
|
||||
</form>
|
||||
{if $warning_tags != ""}
|
||||
<div class='tag-warning tag-info icon-attention'><p> {$warning_tags} </p></div>
|
||||
{/if}
|
||||
<div class='tag-message tag-info icon-ok' {if $message_tags != ""}style='display:flex'{/if}> <p> {$message_tags} </p> </div>
|
||||
<div class='tag-error tag-info icon-cancel'> <p> </p> </div>
|
||||
</div>
|
||||
|
||||
<div class='tag-container'>
|
||||
{foreach from=$all_tags item=tag}
|
||||
<div class='tag-box' data-id='{$tag.id}' data-selected='0'>
|
||||
{tagContent
|
||||
tag_name=$tag.name
|
||||
tag_U_VIEW=$tag.U_VIEW
|
||||
tag_U_EDIT=$tag.U_EDIT
|
||||
has_image=($tag.counter > 0)
|
||||
}
|
||||
</div>
|
||||
{/foreach}
|
||||
{/if}
|
||||
<span id="displayFormBlock" style="display:none">
|
||||
<button id="displayForm" class="buttonLike" type="submit" name="">{'Display form'|translate} <i class="icon-right"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="emptyResearch"> {'No tag found'|@translate} </div>
|
||||
|
||||
<p id="applyActionBlock" style="display:none" class="actionButtons">
|
||||
<button id="applyAction" name="submit" type="submit" class="buttonLike">
|
||||
<i class="icon-trash"></i> {'Apply action'|translate} {* icon-trash because the only action is deletion *}
|
||||
</button>
|
||||
<span id="applyOnDetails"></span>
|
||||
</p>
|
||||
</div> {* #permitAction *}
|
||||
</fieldset>
|
||||
{/if}
|
||||
|
||||
</form>
|
||||
<div class='tag-template' style='display:none'>
|
||||
{tagContent
|
||||
tag_name='%name%'
|
||||
tag_U_VIEW='%U_VIEW%'
|
||||
tag_U_EDIT='%U_EDIT%'
|
||||
has_image=false
|
||||
}
|
||||
</div>
|
||||
@@ -2194,7 +2194,7 @@ input[type="text"].dError {border-color:#ff7070; background-color:#FFe5e5;}
|
||||
.selection-mode-group-manager{
|
||||
position:absolute;
|
||||
right:15px;
|
||||
z-index:1;
|
||||
z-index:11;
|
||||
}
|
||||
|
||||
.switch {
|
||||
@@ -2257,9 +2257,9 @@ input:checked + .slider:before {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 223px;
|
||||
min-height: 584px;
|
||||
height:calc(100% - 171px);
|
||||
min-height:calc(100% - 171px);
|
||||
top: 169.5px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.Selection-mode-content{
|
||||
@@ -2304,7 +2304,7 @@ input:checked + .slider:before {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.SelectionModeGroup button{
|
||||
#selection-mode-block button{
|
||||
display:block;
|
||||
margin:20px auto;
|
||||
font-size: 12px;
|
||||
@@ -2314,11 +2314,11 @@ input:checked + .slider:before {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.SelectionModeGroup button:hover{
|
||||
#selection-mode-block button:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.SelectionModeGroup button.unavailable{
|
||||
#selection-mode-block button.unavailable{
|
||||
opacity: 0.3;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
@@ -2503,26 +2503,26 @@ input:checked + .slider:before {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.groupDeleteConfirm, .groupAlert {
|
||||
.jconfirmDeleteConfirm, .jconfirmAlert {
|
||||
padding-bottom: 0 !important;
|
||||
color: #3c3c3c !important;
|
||||
line-height: 28px !important;
|
||||
}
|
||||
|
||||
.groupAlert {
|
||||
.jconfirmAlert {
|
||||
margin-bottom: -2px !important;
|
||||
}
|
||||
|
||||
.groupDeleteConfirm ~ .jconfirm-content-pane, .groupAlert ~ .jconfirm-content-pane {
|
||||
.jconfirmDeleteConfirm ~ .jconfirm-content-pane, .jconfirmAlert ~ .jconfirm-content-pane {
|
||||
height: 0px !important;
|
||||
margin: 0px !important;
|
||||
}
|
||||
|
||||
.groupDeleteConfirm ~ .jconfirm-buttons button {
|
||||
.jconfirmDeleteConfirm ~ .jconfirm-buttons button {
|
||||
text-transform: none !important;
|
||||
}
|
||||
|
||||
.groupAlert .jconfirm-icon-c i {
|
||||
.jconfirmAlert .jconfirm-icon-c i {
|
||||
color: #0a0 !important;
|
||||
background-color:#c2f5c2 !important;
|
||||
border-radius: 20px;
|
||||
@@ -2532,11 +2532,11 @@ input:checked + .slider:before {
|
||||
font-size: 45px;
|
||||
}
|
||||
|
||||
.groupAlert .jconfirm-icon-c {
|
||||
.jconfirmAlert .jconfirm-icon-c {
|
||||
margin-bottom: 25px !important;
|
||||
}
|
||||
|
||||
.groupAlert .jconfirm-title {
|
||||
.jconfirmAlert .jconfirm-title {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
@@ -3223,4 +3223,344 @@ li.plupload_delete a:hover {background: url("images/cancelhover.svg")!important;
|
||||
}
|
||||
.selectedAlbum.cat-list-album-path span {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tag-header {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.tag-header #search-tag{
|
||||
position: relative;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.tag-header #search-tag .search-input{
|
||||
padding: 10px;
|
||||
box-shadow: 0px 2px #00000024;
|
||||
border: none;
|
||||
background-color: #fafafa;
|
||||
padding-left: 30px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.tag-header #search-tag span {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(4px, -50%);
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.tag-header #add-tag {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tag-header #add-tag .add-tag-container {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
background-color: #fafafa;
|
||||
padding-left: 30px;
|
||||
box-shadow: 0px 2px #00000024;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
display: inline-flex;
|
||||
transition: ease 0.2s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tag-header #add-tag .add-tag-container:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.tag-header #add-tag.input-mode .add-tag-container {
|
||||
width: 200px;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.tag-header #add-tag input[type=text] {
|
||||
position: absolute;
|
||||
left: 5%;
|
||||
background: none;
|
||||
width: calc(90% - 40px);
|
||||
border: none;
|
||||
opacity: 0;
|
||||
display: none;
|
||||
transition: ease 0.2s;
|
||||
}
|
||||
|
||||
.tag-header #add-tag span{
|
||||
z-index: 100;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tag-header #add-tag.input-mode input[type=text] {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tag-header #add-tag .icon-validate {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(5px, -50%);
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: auto;
|
||||
transition: transform ease 0.8s, color ease 0.2s;
|
||||
}
|
||||
|
||||
.tag-header #add-tag.input-mode .icon-validate{
|
||||
transform: translate(180px, -50%) rotate(360deg);
|
||||
color: #FFA646;
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tag-header #add-tag.input-mode span:hover{
|
||||
color: #ff7700;
|
||||
}
|
||||
|
||||
.tag-header #add-tag p {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tag-header #add-tag.input-mode p {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.tag-header #add-tag .icon-cancel {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(209px, -50%);
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
transition: ease 0.2s;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.tag-header #add-tag.input-mode .icon-cancel {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tag-info {
|
||||
height: 35px;
|
||||
overflow: hidden;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
padding: 0px 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tag-info p {
|
||||
margin: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tag-info::before {
|
||||
line-height: 35px;
|
||||
margin: 0px 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tag-info.tag-warning {
|
||||
color: #ee8800;
|
||||
background-color:#ffdd99;
|
||||
}
|
||||
|
||||
.tag-info.tag-message {
|
||||
color: #0a0;
|
||||
background-color:#c2f5c2;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tag-info.tag-error {
|
||||
color: #f22;
|
||||
background-color: #ffd5dc;
|
||||
display: none;
|
||||
animation-name: tag-error-appear ;
|
||||
animation-duration: 0.4s;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
@keyframes tag-error-appear {
|
||||
25% { transform: translateX(-10px)}
|
||||
50% { transform: translateX(10px)}
|
||||
75% { transform: translateX(-10px)}
|
||||
100% { transform: translateX(0px)}
|
||||
}
|
||||
|
||||
.tag-container {
|
||||
display: flex;
|
||||
padding: 25px;
|
||||
flex-flow: wrap;
|
||||
padding-right: 223px;
|
||||
}
|
||||
|
||||
.tag-container .tag-box{
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #fafafa;
|
||||
margin: 5px;
|
||||
box-shadow: 0px 2px 1px #00000024;
|
||||
border-radius: 18px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tag-container .tag-box.selection {
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tag-container .tag-box[data-selected='1'] {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tag-container .tag-box p {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tag-container .tag-box.edit-name p {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tag-container .tag-box.edit-name .showOptions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tag-container .tag-box .tag-dropdown-block {
|
||||
display:none;
|
||||
position:absolute;
|
||||
right: 0;
|
||||
top: 30px;
|
||||
background-color:white;
|
||||
z-index:2;
|
||||
padding:5px 0px;
|
||||
box-shadow: 0px 0px 5px #d7d7d7;
|
||||
border-radius: 10px;
|
||||
transform: translateX(85%);
|
||||
}
|
||||
|
||||
.tag-container .tag-box .tag-dropdown-block .tag-dropdown-action {
|
||||
white-space: nowrap;
|
||||
text-align: initial;
|
||||
padding: 5px 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tag-container .tag-box .tag-dropdown-block .tag-dropdown-action:hover {
|
||||
color: #3A3A3A;
|
||||
text-decoration: none;
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
|
||||
.tag-container .tag-box .select-checkbox {
|
||||
display: none;
|
||||
width: 18.4px;
|
||||
height: 19px;
|
||||
background-color: #e7e7e7;
|
||||
border-radius: 100%;
|
||||
margin: 2px 0px;
|
||||
margin-left: 0px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.tag-container .tag-box[data-selected='1'] .select-checkbox {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.tag-container .tag-box .select-checkbox i {
|
||||
display: none;
|
||||
font-size: 20px;
|
||||
transform: translate(-12px , -6px);
|
||||
position: absolute;
|
||||
animation-name: icon-check-animation;
|
||||
animation-duration: 0.4s;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
.tag-container .tag-box[data-selected='1'] .select-checkbox i {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@keyframes icon-check-animation {
|
||||
0% {
|
||||
transform: translate(-12px , -6px) scale(0);
|
||||
}
|
||||
75% {
|
||||
transform: translate(-12px , -6px) scale(1.3);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-12px , -6px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tag-container .tag-box .tag-rename {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tag-container .tag-box.edit-name .tag-rename {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tag-container .tag-box .tag-rename .tag-name-editable {
|
||||
text-align: left;
|
||||
width: 100px;
|
||||
color: #3c3c3c;
|
||||
font-family: "Open Sans", "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
|
||||
margin: 0px;
|
||||
background-color: white;
|
||||
border: 1px solid #d5d5d5;
|
||||
}
|
||||
|
||||
.tag-container .tag-box .tag-rename span:hover {
|
||||
color: #ffa744;
|
||||
}
|
||||
|
||||
|
||||
.tag-container .tag-box .tag-rename span {
|
||||
padding: 2px 3px;
|
||||
margin: auto;
|
||||
cursor: pointer;
|
||||
color: #3A3A3A;
|
||||
}
|
||||
|
||||
.tag-selection .tag-selection-content {
|
||||
margin-top: 90px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.tag-selection .tag-selection-content .selection-mode-tag{
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.selection-mode-tag .tag-list {
|
||||
margin: 10px;
|
||||
text-align: start;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.selection-mode-tag .tag-list p {
|
||||
width: 85%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
color: #a0a0a0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.selection-mode-tag .tag-list div {
|
||||
display: flex;
|
||||
margin: 10px;
|
||||
text-align: start;
|
||||
}
|
||||
@@ -558,13 +558,13 @@ input:focus + .slider {
|
||||
color:#c0c0c0;
|
||||
}
|
||||
|
||||
.SelectionModeGroup button{
|
||||
#selection-mode-block button{
|
||||
border: 1px solid #e7e7e7;
|
||||
color:#c0c0c0;
|
||||
}
|
||||
|
||||
|
||||
.SelectionModeGroup button:hover{
|
||||
#selection-mode-block button:hover{
|
||||
background-color: #ffa744;
|
||||
border: 1px solid #ffa744;
|
||||
color:#3c3c3c;
|
||||
@@ -862,7 +862,7 @@ li.plupload_delete a:hover {background: url("images/cancelhover.svg")!important;
|
||||
color: #777 !important;
|
||||
}
|
||||
|
||||
.groupAlert .jconfirm-icon-c i {
|
||||
.jconfirmAlert .jconfirm-icon-c i {
|
||||
color:#c2f5c2 !important;
|
||||
background-color:#0a0 !important;
|
||||
}
|
||||
|
||||
@@ -220,14 +220,281 @@ function ws_tags_add($params, &$service)
|
||||
{
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
|
||||
if (get_pwg_token() != $params['pwg_token'])
|
||||
{
|
||||
return new PwgError(403, 'Invalid security token');
|
||||
}
|
||||
|
||||
$creation_output = create_tag($params['name']);
|
||||
|
||||
if (isset($creation_output['error']))
|
||||
{
|
||||
return new PwgError(500, $creation_output['error']);
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, $creation_output['error']);
|
||||
}
|
||||
|
||||
pwg_activity('tag', $creation_output['id'], 'add');
|
||||
|
||||
return $creation_output;
|
||||
}
|
||||
|
||||
function ws_tags_delete($params, &$service)
|
||||
{
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
|
||||
if (get_pwg_token() != $params['pwg_token'])
|
||||
{
|
||||
return new PwgError(403, 'Invalid security token');
|
||||
}
|
||||
|
||||
$query = '
|
||||
SELECT COUNT(*)
|
||||
FROM `'. TAGS_TABLE .'`
|
||||
WHERE id in ('.implode(',', $params['tag_id']) .')
|
||||
;';
|
||||
list($count) = pwg_db_fetch_row(pwg_query($query));
|
||||
if ($count != count($params['tag_id']))
|
||||
{
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, 'All tags does not exist.');
|
||||
}
|
||||
|
||||
|
||||
$tag_ids = $params['tag_id'];
|
||||
|
||||
if (count($tag_ids) > 0)
|
||||
{
|
||||
delete_tags($params['tag_id']);
|
||||
return array('id' => $tag_ids);
|
||||
foreach ($tag_ids as $ids) {
|
||||
pwg_activity('tag', $creation_output['id'], 'delete');
|
||||
}
|
||||
} else {
|
||||
return array('id' => array());
|
||||
}
|
||||
}
|
||||
|
||||
function ws_tags_rename($params, &$service)
|
||||
{
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
|
||||
if (get_pwg_token() != $params['pwg_token'])
|
||||
{
|
||||
return new PwgError(403, 'Invalid security token');
|
||||
}
|
||||
|
||||
$tag_id = $params['tag_id'];
|
||||
$tag_name = $params['new_name'];
|
||||
|
||||
// does the tag exist ?
|
||||
$query = '
|
||||
SELECT COUNT(*)
|
||||
FROM `'. TAGS_TABLE .'`
|
||||
WHERE id = '. $tag_id .'
|
||||
;';
|
||||
list($count) = pwg_db_fetch_row(pwg_query($query));
|
||||
if ($count == 0)
|
||||
{
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, 'This tag does not exist.');
|
||||
}
|
||||
|
||||
$query = '
|
||||
SELECT name
|
||||
FROM '.TAGS_TABLE.'
|
||||
WHERE id != '.$tag_id.'
|
||||
;';
|
||||
$existing_names = array_from_query($query, 'name');
|
||||
|
||||
$update = array();
|
||||
|
||||
if (in_array($tag_name, $existing_names))
|
||||
{
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, 'This name is already token');
|
||||
}
|
||||
else if (!empty($tag_name))
|
||||
{
|
||||
$update = array(
|
||||
'name' => addslashes($tag_name),
|
||||
'url_name' => trigger_change('render_tag_url', $tag_name),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
pwg_activity('tag', $tag_id, 'edit');
|
||||
|
||||
single_update(
|
||||
TAGS_TABLE,
|
||||
$update,
|
||||
array('id' => $tag_id)
|
||||
);
|
||||
|
||||
return array(
|
||||
'id' => $tag_id,
|
||||
'name' => addslashes($tag_name),
|
||||
'url_name' => trigger_change('render_tag_url', $tag_name)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function ws_tags_duplicate($params, &$service) {
|
||||
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
|
||||
if (get_pwg_token() != $params['pwg_token'])
|
||||
{
|
||||
return new PwgError(403, 'Invalid security token');
|
||||
}
|
||||
|
||||
$tag_id = $params['tag_id'];
|
||||
$copy_name = $params['copy_name'];
|
||||
|
||||
// does the tag exist ?
|
||||
$query = '
|
||||
SELECT COUNT(*)
|
||||
FROM `'. TAGS_TABLE .'`
|
||||
WHERE id = '. $tag_id .'
|
||||
;';
|
||||
list($count) = pwg_db_fetch_row(pwg_query($query));
|
||||
if ($count == 0)
|
||||
{
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, 'This tag does not exist.');
|
||||
}
|
||||
|
||||
$query = '
|
||||
SELECT COUNT(*)
|
||||
FROM `'. TAGS_TABLE .'`
|
||||
WHERE name = "'. $copy_name .'"
|
||||
;';
|
||||
list($count) = pwg_db_fetch_row(pwg_query($query));
|
||||
if ($count != 0)
|
||||
{
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, 'This name is already taken.');
|
||||
}
|
||||
|
||||
|
||||
single_insert(
|
||||
TAGS_TABLE,
|
||||
array(
|
||||
'name' => $copy_name,
|
||||
'url_name' => trigger_change('render_tag_url', $copy_name),
|
||||
)
|
||||
);
|
||||
$destination_tag_id = pwg_db_insert_id(TAGS_TABLE);
|
||||
|
||||
pwg_activity('tag', $destination_tag_id, 'add', array('action'=>'duplicate', 'source_tag'=>$tag_id));
|
||||
|
||||
$query = '
|
||||
SELECT image_id
|
||||
FROM '.IMAGE_TAG_TABLE.'
|
||||
WHERE tag_id = '.$tag_id.'
|
||||
;';
|
||||
$destination_tag_image_ids = array_from_query($query, 'image_id');
|
||||
|
||||
$inserts = array();
|
||||
|
||||
foreach ($destination_tag_image_ids as $image_id)
|
||||
{
|
||||
$inserts[] = array(
|
||||
'tag_id' => $destination_tag_id,
|
||||
'image_id' => $image_id
|
||||
);
|
||||
pwg_activity('image', $image_id, 'edit', array("add-tag" => $destination_tag_id));
|
||||
}
|
||||
|
||||
if (count($inserts) > 0)
|
||||
{
|
||||
mass_inserts(
|
||||
IMAGE_TAG_TABLE,
|
||||
array_keys($inserts[0]),
|
||||
$inserts
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'id' => $destination_tag_id,
|
||||
'name' => $copy_name,
|
||||
'url_name' => trigger_change('render_tag_url', $copy_name),
|
||||
);
|
||||
}
|
||||
|
||||
function ws_tags_merge($params, &$service) {
|
||||
|
||||
if (get_pwg_token() != $params['pwg_token'])
|
||||
{
|
||||
return new PwgError(403, 'Invalid security token');
|
||||
}
|
||||
|
||||
$all_tags = $params['merge_tag_id'];
|
||||
array_push($all_tags, $params['destination_tag_id']);
|
||||
|
||||
$all_tags = array_unique($all_tags);
|
||||
$merge_tag = array_diff($params['merge_tag_id'], array($params['destination_tag_id']));
|
||||
|
||||
$query = '
|
||||
SELECT COUNT(*)
|
||||
FROM `'. TAGS_TABLE .'`
|
||||
WHERE id in ('.implode(',', $all_tags) .')
|
||||
;';
|
||||
list($count) = pwg_db_fetch_row(pwg_query($query));
|
||||
if ($count != count($all_tags))
|
||||
{
|
||||
return new PwgError(WS_ERR_INVALID_PARAM, 'All tags does not exist.');
|
||||
}
|
||||
|
||||
$image_in_merge_tags = array();
|
||||
$image_in_dest = array();
|
||||
$image_to_add = array();
|
||||
|
||||
$query = '
|
||||
SELECT DISTINCT(image_id)
|
||||
FROM `'. IMAGE_TAG_TABLE .'`
|
||||
WHERE
|
||||
tag_id IN ('.implode(',', $merge_tag) .')
|
||||
;';
|
||||
$image_in_merge_tags = query2array($query, null, 'image_id');
|
||||
|
||||
$query = '
|
||||
SELECT image_id
|
||||
FROM `'. IMAGE_TAG_TABLE .'`
|
||||
WHERE tag_id = '.$params['destination_tag_id'].'
|
||||
;';
|
||||
|
||||
$image_in_dest = query2array($query, null, 'image_id');;
|
||||
|
||||
|
||||
$image_to_add = array_diff($image_in_merge_tags, $image_in_dest);
|
||||
|
||||
$inserts = array();
|
||||
foreach ($image_to_add as $image)
|
||||
{
|
||||
$inserts[] = array(
|
||||
'tag_id' => $params['destination_tag_id'],
|
||||
'image_id' => $image,
|
||||
);
|
||||
}
|
||||
|
||||
mass_inserts(
|
||||
IMAGE_TAG_TABLE,
|
||||
array('tag_id', 'image_id'),
|
||||
$inserts,
|
||||
array('ignore'=>true)
|
||||
);
|
||||
|
||||
pwg_activity('tag', $params['destination_tag_id'], 'edit');
|
||||
foreach ($image_to_add as $image_id)
|
||||
{
|
||||
pwg_activity('image', $image_id, 'edit', array("tag-add" => $params['destination_tag_id']));
|
||||
}
|
||||
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
|
||||
delete_tags($merge_tag);
|
||||
|
||||
$image_in_merged = array_merge($image_in_dest, $image_to_add);
|
||||
|
||||
return array(
|
||||
"destination_tag" => $params['destination_tag_id'],
|
||||
"deleted_tag" => $params['merge_tag_id'],
|
||||
"images_in_merged_tag" => $image_in_merged
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
59
ws.php
59
ws.php
@@ -640,12 +640,69 @@ function ws_addDefaultMethods( $arr )
|
||||
$service->addMethod( // TODO: create multiple tags
|
||||
'pwg.tags.add',
|
||||
'ws_tags_add',
|
||||
array('name'),
|
||||
array(
|
||||
'name' => array(),
|
||||
'pwg_token' => array(),
|
||||
),
|
||||
'Adds a new tag.',
|
||||
$ws_functions_root . 'pwg.tags.php',
|
||||
array('admin_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.tags.delete',
|
||||
'ws_tags_delete',
|
||||
array(
|
||||
'tag_id' => array('type'=>WS_TYPE_ID,
|
||||
'flags'=>WS_PARAM_FORCE_ARRAY),
|
||||
'pwg_token' => array(),
|
||||
),
|
||||
'Delete tag(s) by ID.',
|
||||
$ws_functions_root . 'pwg.tags.php',
|
||||
array('admin_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.tags.rename',
|
||||
'ws_tags_rename',
|
||||
array(
|
||||
'tag_id' => array('type'=>WS_TYPE_ID),
|
||||
'new_name' => array(),
|
||||
'pwg_token' => array(),
|
||||
),
|
||||
'Rename tag',
|
||||
$ws_functions_root . 'pwg.tags.php',
|
||||
array('admin_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.tags.duplicate',
|
||||
'ws_tags_duplicate',
|
||||
array(
|
||||
'tag_id' => array('type'=>WS_TYPE_ID),
|
||||
'copy_name' => array(),
|
||||
'pwg_token' => array(),
|
||||
),
|
||||
'Create a copy of a tag',
|
||||
$ws_functions_root . 'pwg.tags.php',
|
||||
array('admin_only'=>true, 'post_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.tags.merge',
|
||||
'ws_tags_merge',
|
||||
array(
|
||||
'destination_tag_id' => array('type'=>WS_TYPE_ID,
|
||||
'info'=>'Is not necessarily part of groups to merge'),
|
||||
'merge_tag_id' => array('flags'=>WS_PARAM_FORCE_ARRAY,
|
||||
'type'=>WS_TYPE_ID),
|
||||
'pwg_token' => array(),
|
||||
),
|
||||
'Merge tags in one other group',
|
||||
$ws_functions_root . 'pwg.tags.php',
|
||||
array('admin_only'=>true, 'post_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.images.exist',
|
||||
'ws_images_exist',
|
||||
|
||||
Reference in New Issue
Block a user