diff --git a/ci/mvn-release.sh b/ci/mvn-release.sh old mode 100644 new mode 100755 diff --git a/ci/setup-git.sh b/ci/setup-git.sh old mode 100644 new mode 100755 diff --git a/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/css/genericmultifield.css b/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/css/genericmultifield.css index 5ee1264..c9c824a 100644 --- a/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/css/genericmultifield.css +++ b/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/css/genericmultifield.css @@ -28,7 +28,8 @@ .coral-SpectrumMultiField-edit, .coral-SpectrumMultiField-remove, -.coral-SpectrumMultiField-move { +.coral-SpectrumMultiField-move, +.coral-SpectrumMultiField-copy { width: 41px; height: 41px; } @@ -65,6 +66,12 @@ right: 0; } +.coral-SpectrumMultiField-copy { + position: absolute; + top: 0; + right: 6.3rem; +} + .coral-GenericMultiField .coral-GenericMultiField-listEntry { border: .0625rem solid rgba(0, 0, 0, 0.15); position: relative; diff --git a/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/js/CUI.GenericMultiField.js b/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/js/CUI.GenericMultiField.js index 8c0a3eb..1c020c4 100644 --- a/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/js/CUI.GenericMultiField.js +++ b/src/main/resources/SLING-INF/apps/merkle/genericmultifield/clientlibs/js/CUI.GenericMultiField.js @@ -8,6 +8,7 @@ var removeButton = ""; var editButton = ""; var moveButton = ""; + var copyButton = ""; /** * The Merkle.GenericMultiField class represents an editable list @@ -164,10 +165,12 @@ li.append($(removeButton)); li.append(editButton); li.append(moveButton); + li.append(copyButton); if (this.readOnly) { $(".coral-SpectrumMultiField-remove", li).attr("disabled", "disabled"); $(".coral-SpectrumMultiField-edit", li).attr("disabled", "disabled"); $(".coral-SpectrumMultiField-move", li).attr("disabled", "disabled"); + $(".coral-SpectrumMultiField-copy", li).attr("disabled", "disabled"); } return li; }, @@ -196,6 +199,11 @@ that._editItem(currentItem); }); + this.$element.on("click", ".js-coral-SpectrumMultiField-copy", function (e) { + var currentItem = $(this).closest("li"); + that._copyItem(currentItem); + }); + this.$element .fipo("taphold", "mousedown", ".js-coral-SpectrumMultiField-move", function (e) { @@ -355,6 +363,37 @@ } }, + /** + * Copies an item by creating a duplicate. + * + * @param {Object} item List item to be copied. + * @private + */ + _copyItem: function (item) { + var that = this; + var currentElements = this.$element.find("li").length; + + if (!this.maxElements || (currentElements < this.maxElements)) { + + this.ui.prompt(Granite.I18n.get("Copy Item"), Granite.I18n.get("Are you sure you want to copy this item?", this.minElements), "info", + [{text: Granite.I18n.get("Cancel")}, + { + text: Granite.I18n.get("Copy"), + primary: true, + handler: function () { + var sourcePath = that.crxPath + "/" + that.itemStorageNode + "/" + item.attr("id"); + that._copyNode(sourcePath, function (copiedPath) { + console.log("Item copied successfully to:", copiedPath); + // Refresh the list to show the newly copied item + that._updateList(true); + }); + } + }]); + } else { + this.ui.alert(Granite.I18n.get("Maximum reached"), Granite.I18n.get("Maximum number of {0} item(s) reached, you cannot add any additional items.", this.maxElements), "warning"); + } + }, + /** * Performs drag and drop reordering and * executes a sling reordering request on crx items. @@ -467,6 +506,33 @@ }); }, + /** + * Copies the node at given path. + * + * @param {String} path of node to be copied. + * @param {Function} callback node that has been copied. + * @private + */ + _copyNode: function (path, callback) { + var that = this; + // Create a unique destination path for the copy + var timestamp = Date.now(); + var destinationPath = that.crxPath + "/" + that.itemStorageNode + "/copy_" + timestamp; + + $.ajax({ + type: "POST", + data: ":operation=copy&:dest=" + destinationPath, + url: path + }).done(function (data) { + if ($.isFunction(callback)) { + callback(destinationPath); + } + }).fail(function(xhr, status, error) { + console.error("Copy operation failed:", error); + that.ui.alert(Granite.I18n.get("Copy Error"), Granite.I18n.get("Failed to copy the item. Please try again."), "error"); + }); + }, + /** * Triggers the change event with the DOM element as the source. *