diff --git a/admin/batch_manager_global.php b/admin/batch_manager_global.php
index a4786c9f9..441a1ce6f 100644
--- a/admin/batch_manager_global.php
+++ b/admin/batch_manager_global.php
@@ -36,6 +36,7 @@ check_input_parameter('del_tags', $_POST, true, PATTERN_ID);
check_input_parameter('associate', $_POST, true, PATTERN_ID);
check_input_parameter('move', $_POST, false, PATTERN_ID);
check_input_parameter('dissociate', $_POST, false, PATTERN_ID);
+check_input_parameter('mf_albums', $_POST, true, PATTERN_ID);
// +-----------------------------------------------------------------------+
// | current selection |
@@ -419,6 +420,186 @@ DELETE
}
}
+ else if ('multi_fields' == $action)
+ {
+ $enabled = isset($_POST['mf_enable']) ? $_POST['mf_enable'] : array();
+ $enabled = array_flip($enabled);
+
+ if (count($enabled) == 0)
+ {
+ $page['errors'][] = l10n('Select at least one field');
+ }
+ else
+ {
+ $base = array(
+ 'title' => array('col' => 'name', 'post' => 'mf_title', 'mode' => 'mf_title_mode'),
+ 'author' => array('col' => 'author', 'post' => 'mf_author', 'mode' => 'mf_author_mode'),
+ 'comment' => array('col' => 'comment', 'post' => 'mf_comment', 'mode' => 'mf_comment_mode'),
+ );
+
+ $update_cols = array();
+ foreach ($base as $key => $def)
+ {
+ if (isset($enabled[$key]))
+ {
+ $update_cols[] = $def['col'];
+ }
+ }
+
+ if (count($update_cols) > 0)
+ {
+ $datas = array();
+ foreach ($collection as $image_id)
+ {
+ $row = array('id' => $image_id);
+ foreach ($base as $key => $def)
+ {
+ if (isset($enabled[$key]))
+ {
+ $mode = $_POST[$def['mode']];
+ if ('empty' == $mode)
+ {
+ $row[$def['col']] = null;
+ }
+ else
+ {
+ $value = $_POST[$def['post']];
+ $row[$def['col']] = ($value === '') ? null : $value;
+ }
+ }
+ }
+ $datas[] = $row;
+ }
+
+ mass_updates(
+ IMAGES_TABLE,
+ array('primary' => array('id'), 'update' => $update_cols),
+ $datas
+ );
+ }
+
+ if (isset($enabled['albums']))
+ {
+ check_input_parameter('mf_albums_mode', $_POST, false, '/^(associate|dissociate)$/');
+ $mode = $_POST['mf_albums_mode'];
+
+ if (empty($_POST['mf_albums']))
+ {
+ $page['errors'][] = l10n('Select at least one album');
+ }
+ else
+ {
+ $album_ids = $_POST['mf_albums'];
+
+ if ('dissociate' == $mode)
+ {
+ foreach ($album_ids as $album_id)
+ {
+ dissociate_images_from_category($collection, $album_id);
+ }
+ $redirect = true;
+ }
+ else if ('associate' == $mode)
+ {
+ associate_images_to_categories($collection, $album_ids);
+ }
+ }
+ }
+
+ if (isset($enabled['tags']))
+ {
+ check_input_parameter('mf_tags_mode', $_POST, false, '/^(replace|add|empty|remove)$/');
+ $mode = $_POST['mf_tags_mode'];
+
+ if ('empty' == $mode)
+ {
+ $tags_of = array();
+ foreach ($collection as $image_id)
+ {
+ $tags_of[$image_id] = array();
+ }
+ set_tags_of($tags_of);
+ }
+ else if (empty($_POST['mf_tags']))
+ {
+ $page['errors'][] = l10n('Select at least one tag');
+ }
+ else
+ {
+ if ('remove' == $mode)
+ {
+ check_input_parameter('mf_tags', $_POST, true, PATTERN_ID);
+ $tag_ids = $_POST['mf_tags'];
+ }
+ else
+ {
+ $tag_ids = get_tag_ids($_POST['mf_tags']);
+ }
+ if ('replace' == $mode)
+ {
+ $tags_of = array();
+ foreach ($collection as $image_id)
+ {
+ $tags_of[$image_id] = $tag_ids;
+ }
+ set_tags_of($tags_of);
+ }
+ else if ('remove' == $mode)
+ {
+ $taglist_before = get_image_tag_ids($collection);
+
+ $query = '
+DELETE
+ FROM '.IMAGE_TAG_TABLE.'
+ WHERE image_id IN ('.implode(',', $collection).')
+ AND tag_id IN ('.implode(',', $tag_ids).')
+;';
+ pwg_query($query);
+
+ $taglist_after = get_image_tag_ids($collection);
+ $images_to_update = compare_image_tag_lists($taglist_before, $taglist_after);
+ update_images_lastmodified($images_to_update);
+
+ if (isset($_SESSION['bulk_manager_filter']['tags'])
+ && count(array_intersect($_SESSION['bulk_manager_filter']['tags'], $tag_ids)))
+ {
+ $redirect = true;
+ }
+ }
+ else if ('add' == $mode)
+ {
+ add_tags($tag_ids, $collection);
+ }
+ }
+ }
+
+ $mode_rules = array(
+ 'title' => array('post' => 'mf_title_mode', 'allowed' => array('replace', 'empty'), 'default' => 'replace'),
+ 'author' => array('post' => 'mf_author_mode', 'allowed' => array('replace', 'empty'), 'default' => 'replace'),
+ 'comment' => array('post' => 'mf_comment_mode', 'allowed' => array('replace', 'empty'), 'default' => 'replace'),
+ 'albums' => array('post' => 'mf_albums_mode', 'allowed' => array('associate', 'dissociate'), 'default' => 'associate'),
+ 'tags' => array('post' => 'mf_tags_mode', 'allowed' => array('add', 'replace', 'empty', 'remove'), 'default' => 'add'),
+ );
+
+ $activity_fields = array();
+ foreach ($mode_rules as $field => $rule)
+ {
+ if (isset($enabled[$field]))
+ {
+ $mode = isset($_POST[$rule['post']]) ? $_POST[$rule['post']] : $rule['default'];
+ $activity_fields[$field] = in_array($mode, $rule['allowed'], true) ? $mode : $rule['default'];
+ }
+ }
+
+ pwg_activity('photo', $collection, 'edit', array('action' => 'multi_fields', 'fields' => $activity_fields));
+
+ if (empty($page['errors']))
+ {
+ $page['infos'][] = l10n('Information data registered in database');
+ }
+ }
+ }
+
if (!in_array($action, array('remove_from_caddie','add_to_caddie','delete_derivatives','generate_derivatives')))
{
invalidate_user_cache();
diff --git a/admin/themes/clear/theme.css b/admin/themes/clear/theme.css
index a4a89264c..4915230b1 100644
--- a/admin/themes/clear/theme.css
+++ b/admin/themes/clear/theme.css
@@ -834,7 +834,9 @@ li.plupload_delete a.remove-format:hover{color: #474747;}
background-color: #fafafa;
box-shadow: 0px 2px #00000024;
}
-.breadcrumb-item:hover {
+.breadcrumb-item:hover,
+#batchManagerGlobal .head-button-2:hover,
+#batchManagerGlobal .head-button-2:hover p {
background: #ffd7ad;
}
.breadcrumb-item .icon-cancel-circled:hover {
diff --git a/admin/themes/default/css/components/general.css b/admin/themes/default/css/components/general.css
index f86b0e027..962c007b4 100644
--- a/admin/themes/default/css/components/general.css
+++ b/admin/themes/default/css/components/general.css
@@ -19,6 +19,10 @@ or
align-items: baseline;
cursor: pointer;
margin-right: 10px;
+ transition: all 125ms ease-out;
+}
+.head-button-2 p {
+ transition: all 125ms ease-out;
}
.head-button-1:active, .head-button-2:active {
diff --git a/admin/themes/default/js/batchManagerGlobal.js b/admin/themes/default/js/batchManagerGlobal.js
index 2e15e6ea5..5340d1117 100644
--- a/admin/themes/default/js/batchManagerGlobal.js
+++ b/admin/themes/default/js/batchManagerGlobal.js
@@ -59,6 +59,22 @@ jQuery(document).ready(function() {
}
});
+ const ab_multi_fields = new AlbumSelector({
+ adminMode: true,
+ selectAlbum: select_multi_fields_album,
+ removeSelectedAlbum: remove_multi_fields_album,
+ });
+
+ $('#multi_fields_select_album').on('click', function () {
+ ab_multi_fields.open();
+ });
+
+ $('.multi-fields-selected-albums').on('click', (e) => {
+ if (e.target.classList.contains("remove-associate")) {
+ ab_multi_fields.remove_selected_album($(e.target).attr('id'));
+ }
+ });
+
});
/* ********** Album Selector */
@@ -81,6 +97,47 @@ function remove_album_action({ id_album, getSelectedAlbum }) {
}
}
+function select_multi_fields_album({ album, addSelectedAlbum }) {
+ $('#multi_fields_select_album p').html(str_add_alb_associate);
+ $('.multi-fields-selected-albums').append(
+ `
+ ${album.name}
+
+
`
+ );
+ hideError("form");
+ update_multi_fields_album_button();
+ addSelectedAlbum();
+}
+
+function remove_multi_fields_album({ id_album, getSelectedAlbum }) {
+ $('.multi-fields-selected-albums').find(`#${id_album}`).parent().remove();
+ const selected = getSelectedAlbum();
+ if (!selected.length) {
+ $('#multi_fields_select_album p').html(str_select_alb_associate);
+ }
+ if (selected.length) {
+ hideError("form");
+ }
+ update_multi_fields_album_button();
+}
+
+function update_multi_fields_album_button() {
+ const hasSelectedAlbums = $('.multi-fields-selected-albums').children().length > 0;
+ $('#multi_fields_select_album')
+ .toggleClass('head-button-2', !hasSelectedAlbums)
+ .toggleClass('head-button-1', hasSelectedAlbums);
+}
+
+function displayError(error, text) {
+ var $error = $("[data-error='" + error + "']");
+ $error.text(text).css("visibility", "visible");
+}
+
+function hideError(error) {
+ $("[data-error='" + error + "']").css("visibility", "hidden");
+}
+
jQuery("a.preview-box").colorbox( {photo: true} );
@@ -102,6 +159,112 @@ jQuery(function() {
jQuery('[data-add-album]').pwgAddAlbum();
});
+jQuery(function() {
+ $("#action_multi_fields .mf-row").each(function() {
+ var $row = $(this);
+ var $toggle = $row.find(".switch input");
+ var $mode = $row.find(".mf-modes input[type=radio]");
+ var $content = $row.find(".mf-content");
+ var $tagSelect = $content.find("select[name='mf_tags[]']");
+ var tagsMode = null;
+ var selectizeCreate;
+
+ function switchTagsList(mode) {
+ var selectize = $tagSelect[0] && $tagSelect[0].selectize;
+ if (!selectize) return;
+
+ if (selectizeCreate === undefined) {
+ selectizeCreate = selectize.settings.create;
+ }
+
+ var isRemove = (mode === "remove");
+ if (tagsMode === isRemove) return;
+ tagsMode = isRemove;
+
+ selectize.clear(true);
+
+ if (isRemove) {
+ if (!selectize._allOptions) {
+ selectize._allOptions = $.extend(true, {}, selectize.options);
+ }
+ selectize.clearOptions();
+ selectize.settings.create = false;
+ var delTagsSelectize = $("select[name='del_tags[]']")[0];
+ var removeOptions = delTagsSelectize && delTagsSelectize.selectize
+ ? delTagsSelectize.selectize.options
+ : {};
+ $.each(removeOptions, function (id, tag) {
+ selectize.addOption(tag);
+ });
+ } else {
+ if (selectize._allOptions) {
+ selectize.clearOptions();
+ $.each(selectize._allOptions, function (id, opt) {
+ selectize.addOption(opt);
+ });
+ }
+ selectize.settings.create = selectizeCreate;
+ }
+ selectize.refreshOptions(false);
+ }
+
+ function resetRow() {
+ $content.find("input[type=text], textarea").val("");
+ $row.find(".multi-fields-selected-albums").empty();
+ update_multi_fields_album_button();
+
+ $content.find("select").each(function() {
+ if (this.selectize) {
+ this.selectize.clear();
+ } else {
+ $(this).val(null);
+ }
+ });
+
+ $mode.each(function() {
+ this.checked = this.defaultChecked;
+ });
+ tagsMode = null;
+ switchTagsList($mode.filter(":checked").val());
+ }
+
+ function refresh() {
+ var on = $toggle.is(":checked");
+ var mode = $mode.filter(":checked").val();
+ $row.toggleClass("mf-active", on);
+ $row.find(".mf-modes").toggle(on);
+ $content.toggle(on && mode !== "empty");
+ if ($row.data("field") === "tags") {
+ switchTagsList(mode);
+ }
+ }
+
+ $toggle.on("change", function() {
+ hideError("form");
+ if (!this.checked) {
+ resetRow();
+ }
+ refresh();
+ });
+
+ $mode.on("change", function() {
+ if ($row.data("field") === "tags" && $(this).val() === "empty") {
+ hideError("form");
+ }
+ refresh();
+ });
+
+ $tagSelect.on("change", function() {
+ var selectedTags = $(this).val();
+ if (selectedTags && selectedTags.length) {
+ hideError("form");
+ }
+ });
+
+ refresh();
+ });
+});
+
$("input[name=remove_author]").click(function () {
if ($(this).is(':checked')) {
$("input[name=author]").hide();
@@ -244,7 +407,35 @@ jQuery('#applyAction').click(function(e) {
return true;
}
- if (jQuery('[name="selectAction"]').val() == 'metadata') {
+ var action = jQuery('[name="selectAction"]').val();
+ if (action == 'multi_fields') {
+ var $enabledFields = jQuery('input[name="mf_enable[]"]:checked');
+ var $tagsField = jQuery('input[name="mf_enable[]"][value="tags"]');
+ var tagsMode = jQuery('input[name="mf_tags_mode"]:checked').val();
+
+ if (!$enabledFields.length) {
+ displayError("form", lang.selectField);
+ e.preventDefault();
+ return false;
+ }
+ if (jQuery('input[name="mf_enable[]"][value="albums"]').is(':checked')
+ && !jQuery('input[name="mf_albums[]"]').length) {
+ displayError("form", str_select_album);
+ e.preventDefault();
+ return false;
+ }
+ var selectedTags = jQuery('select[name="mf_tags[]"]').val();
+ if ($tagsField.is(':checked')
+ && tagsMode !== 'empty'
+ && (!selectedTags || !selectedTags.length)) {
+ displayError("form", str_select_tag);
+ e.preventDefault();
+ return false;
+ }
+ }
+ hideError("form");
+
+ if (action == 'metadata') {
e.preventDefault();
e.stopPropagation();
jQuery('.bulkAction').hide();
@@ -318,7 +509,10 @@ jQuery('#applyAction').click(function(e) {
if (jQuery('[name="selectAction"]').val() == 'delete') {
if (!jQuery("#confirmDel input[name=confirm_deletion]").is(':checked')) {
- jQuery("#confirmDel span.errors").css("visibility", "visible");
+ displayError(
+ "form",
+ lang.confirmDeletion
+ );
return false;
}
e.stopPropagation();
@@ -422,7 +616,7 @@ function progress_bar(val, max, success) {
}
jQuery("#confirmDel input[name=confirm_deletion]").change(function() {
- jQuery("#confirmDel span.errors").css("visibility", "hidden");
+ hideError("form");
});
jQuery('#sync_md5sum').click(function(e) {
@@ -524,4 +718,3 @@ function delete_orphans_block(blockSize) {
}
});
}
-
diff --git a/admin/themes/default/template/batch_manager_global.tpl b/admin/themes/default/template/batch_manager_global.tpl
index 38bec6c9c..c84c70053 100644
--- a/admin/themes/default/template/batch_manager_global.tpl
+++ b/admin/themes/default/template/batch_manager_global.tpl
@@ -15,6 +15,8 @@ var lang = {
deleteProgressMessage: "{'Deletion in progress'|translate|escape:'javascript'}",
syncProgressMessage: "{'Synchronization in progress'|translate|escape:'javascript'}",
AreYouSure: "{'Are you sure?'|translate|escape:'javascript'}",
+ confirmDeletion: "{'You need to confirm deletion'|translate|escape:'javascript'}",
+ selectField: "{'Select at least one field'|translate|escape:'javascript'}",
generateMsg: "{'Generate multiple size images'|@translate}"
};
@@ -242,7 +244,7 @@ $(document).ready(function() {
}
jQuery("input[name=confirm_deletion]").change(function() {
- jQuery("#confirmDel span.errors").css("visibility", "hidden");
+ hideError("form");
});
jQuery('#applyAction').click(function() {
@@ -251,7 +253,10 @@ $(document).ready(function() {
let d_count = $('#confirmDel input[type=checkbox]').filter(':checked').length
let e_count = $('input[name="setSelected"]').is(':checked') ? nb_thumbs_set : $('.thumbnails input[type=checkbox]').filter(':checked').length;
if (!jQuery("#confirmDel input[name=confirm_deletion]").is(':checked')) {
- jQuery("#confirmDel span.errors").css("visibility", "visible");
+ displayError(
+ "form",
+ lang.confirmDeletion
+ );
return false;
} else {
return true;
@@ -420,6 +425,7 @@ UL.thumbnails SPAN.wrap2 {ldelim}
{/if}
+
{if !empty($element_set_global_plugins_actions)}
{foreach from=$element_set_global_plugins_actions item=action}
@@ -432,7 +438,7 @@ UL.thumbnails SPAN.wrap2 {ldelim}
{'Are you sure?'|@translate}
- {"You need to confirm deletion"|translate}
+