diff --git a/all/pom.xml b/all/pom.xml index 8bc6cf7..8e45c9a 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -22,7 +22,7 @@ com.exadel.etoolbox etoolbox-rollout-manager - 1.2.0 + 1.3.0-SNAPSHOT ../pom.xml diff --git a/core/pom.xml b/core/pom.xml index a096f5a..68fe69d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -18,7 +18,7 @@ com.exadel.etoolbox etoolbox-rollout-manager - 1.2.0 + 1.3.0-SNAPSHOT ../pom.xml etoolbox-rollout-manager.core diff --git a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/models/RolloutItem.java b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/models/RolloutItem.java new file mode 100644 index 0000000..1dbe0e9 --- /dev/null +++ b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/models/RolloutItem.java @@ -0,0 +1,38 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.exadel.etoolbox.rolloutmanager.core.models; + +public class RolloutItem { + private String master; + private String target; + private int depth; + boolean autoRolloutTrigger; + + public String getMaster() { + return master; + } + + public String getTarget() { + return target; + } + + public int getDepth() { + return depth; + } + + public boolean isAutoRolloutTrigger() { + return autoRolloutTrigger; + } +} diff --git a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/models/RolloutStatus.java b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/models/RolloutStatus.java new file mode 100644 index 0000000..9b0fe1b --- /dev/null +++ b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/models/RolloutStatus.java @@ -0,0 +1,36 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.exadel.etoolbox.rolloutmanager.core.models; + +public class RolloutStatus { + private boolean isSuccess; + private final String target; + + public RolloutStatus(String target) { + this.target = target; + } + + public boolean isSuccess() { + return isSuccess; + } + + public void setSuccess(boolean success) { + isSuccess = success; + } + + public String getTarget() { + return target; + } +} diff --git a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/services/PageReplicationService.java b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/services/PageReplicationService.java new file mode 100644 index 0000000..2c210c5 --- /dev/null +++ b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/services/PageReplicationService.java @@ -0,0 +1,30 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.exadel.etoolbox.rolloutmanager.core.services; + +import com.day.cq.wcm.api.PageManager; +import com.exadel.etoolbox.rolloutmanager.core.models.RolloutItem; +import com.exadel.etoolbox.rolloutmanager.core.models.RolloutStatus; +import org.apache.sling.api.resource.ResourceResolver; + +import java.util.List; + +/** + * Provides methods for checking if a live relationship can be synchronized with a blueprint in scope of usage + * the rollout manager tool. + */ +public interface PageReplicationService { + List replicateItems(ResourceResolver resourceResolver, RolloutItem[] items, PageManager pageManager); +} \ No newline at end of file diff --git a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/services/impl/PageReplicationServiceImpl.java b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/services/impl/PageReplicationServiceImpl.java new file mode 100644 index 0000000..3fe67a4 --- /dev/null +++ b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/services/impl/PageReplicationServiceImpl.java @@ -0,0 +1,134 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.exadel.etoolbox.rolloutmanager.core.services.impl; + +import com.day.cq.replication.ReplicationActionType; +import com.day.cq.replication.ReplicationException; +import com.day.cq.replication.Replicator; +import com.day.cq.wcm.api.Page; +import com.day.cq.wcm.api.PageManager; +import com.day.cq.wcm.api.WCMException; +import com.day.cq.wcm.msm.api.LiveRelationshipManager; +import com.exadel.etoolbox.rolloutmanager.core.models.RolloutItem; +import com.exadel.etoolbox.rolloutmanager.core.models.RolloutStatus; +import com.exadel.etoolbox.rolloutmanager.core.services.PageReplicationService; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.event.jobs.JobManager; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.Designate; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Session; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Component(service = PageReplicationService.class) +@Designate(ocd = PageReplicationServiceImpl.Configuration.class) +public class PageReplicationServiceImpl implements PageReplicationService { + private static final Logger LOG = LoggerFactory.getLogger(PageReplicationServiceImpl.class); + + @ObjectClassDefinition(name = "EToolbox Page Replication Service Configuration") + @interface Configuration { + + @AttributeDefinition( + name = "Pool size", + description = "The number of Threads in the pool") + int poolSize() default 5; + } + + @Activate + private PageReplicationServiceImpl.Configuration config; + + @Reference + private LiveRelationshipManager liveRelationshipManager; + + @Reference + private JobManager jobManager; + + @Reference + private Replicator replicator; + + public List replicateItems(ResourceResolver resourceResolver, RolloutItem[] items, PageManager pageManager) { + return Arrays.stream(items) + .collect(Collectors.groupingBy(RolloutItem::getDepth)) + .entrySet() + .stream() + .sorted(Map.Entry.comparingByKey()) + .map(Map.Entry::getValue) + .flatMap(sortedByDepthItems -> replicateSortedByDepthItems(resourceResolver, sortedByDepthItems, pageManager)) + .collect(Collectors.toList()); + } + + private Stream replicateSortedByDepthItems(ResourceResolver resourceResolver, List items, PageManager pageManager) { + ExecutorService executorService = Executors.newFixedThreadPool(config.poolSize()); + return items.stream() + .filter(item -> StringUtils.isNotBlank(item.getTarget())) + .filter(item -> !isBluePrintPage(item, resourceResolver)) + .map(item -> CompletableFuture.supplyAsync(() -> replicate(resourceResolver, item, pageManager), executorService)) + .collect(Collectors.toList()) + .stream() + .map(CompletableFuture::join); + } + + private boolean isBluePrintPage(RolloutItem item, ResourceResolver resourceResolver) { + boolean hasRelationships = true; + try { + hasRelationships = liveRelationshipManager + .getLiveRelationships(resourceResolver.getResource(item.getTarget()), null, null).hasNext(); + } catch (WCMException e) { + LOG.debug("Item replication skipped due to error while Live Copy initialization, master: {}, target: {}", item.getMaster(), item.getTarget()); + } + if (hasRelationships) { + LOG.debug("Item replication skipped, master: {}, target: {}", item.getMaster(), item.getTarget()); + } + return hasRelationships; + } + + private RolloutStatus replicate(ResourceResolver resourceResolver, RolloutItem targetItem, PageManager pageManager) { + + String targetPath = targetItem.getTarget(); + RolloutStatus status = new RolloutStatus(targetPath); + + Optional targetPage = Optional.ofNullable(pageManager.getPage(targetPath)); + Session session = resourceResolver.adaptTo(Session.class); + if (!targetPage.isPresent() || ObjectUtils.isEmpty(session)) { + status.setSuccess(false); + LOG.warn("Replication failed - target page is null, page path: {}", targetPath); + return status; + } + try { + replicator.replicate(session, ReplicationActionType.ACTIVATE, targetPath); + status.setSuccess(true); + } catch (ReplicationException ex) { + status.setSuccess(false); + LOG.error("Exception during page replication", ex); + } + return status; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServlet.java b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServlet.java index 005d6fb..17b8835 100644 --- a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServlet.java +++ b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServlet.java @@ -75,6 +75,7 @@ public class CollectLiveCopiesServlet extends SlingAllMethodsServlet { private static final String IS_NEW_JSON_FIELD = "isNew"; private static final String HAS_ROLLOUT_TRIGGER_JSON_FIELD = "autoRolloutTrigger"; private static final String LAST_ROLLED_OUT_JSON_FIELD = "lastRolledOut"; + private static final String IS_DISABLED_JSON_FIELD = "disabled"; @Reference private transient LiveRelationshipManager liveRelationshipManager; @@ -137,11 +138,10 @@ private JsonObject relationshipToJson(LiveRelationship relationship, String targetPath = buildTargetPath(relationship, syncPath); LiveCopy liveCopy = relationship.getLiveCopy(); - if (liveCopy == null - || (StringUtils.isNotBlank(syncPath) && !liveCopy.isDeep()) - || !relationshipCheckerService.isAvailableForSync(syncPath, targetPath, liveCopy.getExclusions(), resourceResolver)) { + if (liveCopy == null || (StringUtils.isNotBlank(syncPath) && !liveCopy.isDeep())) { return JsonValue.EMPTY_JSON_OBJECT; } + boolean isDisabled = !relationshipCheckerService.isAvailableForSync(syncPath, targetPath, liveCopy.getExclusions(), resourceResolver); String liveCopyPath = liveCopy.getPath(); boolean isNew = !resourceExists(resourceResolver, liveCopyPath + syncPath); @@ -154,13 +154,14 @@ private JsonObject relationshipToJson(LiveRelationship relationship, .add(IS_NEW_JSON_FIELD, isNew) .add(HAS_ROLLOUT_TRIGGER_JSON_FIELD, !isNew && hasAutoTrigger(liveCopy)) .add(LAST_ROLLED_OUT_JSON_FIELD, getStringDate(resourceResolver, liveCopyPath + syncPath)) + .add(IS_DISABLED_JSON_FIELD, isDisabled) .build(); } private boolean hasAutoTrigger(LiveCopy liveCopy) { return liveCopy.getRolloutConfigs().stream() .map(RolloutConfig::getTrigger) - .anyMatch(trigger -> trigger == RolloutManager.Trigger.MODIFICATION || trigger == RolloutManager.Trigger.ROLLOUT); + .anyMatch(trigger -> trigger == RolloutManager.Trigger.MODIFICATION); } private String buildSyncPath(LiveRelationship relationship, String sourceSyncPath) { diff --git a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/RolloutServlet.java b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/RolloutServlet.java index 547790c..bae4a86 100644 --- a/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/RolloutServlet.java +++ b/core/src/main/java/com/exadel/etoolbox/rolloutmanager/core/servlets/RolloutServlet.java @@ -18,6 +18,9 @@ import com.day.cq.wcm.api.PageManager; import com.day.cq.wcm.api.WCMException; import com.day.cq.wcm.msm.api.RolloutManager; +import com.exadel.etoolbox.rolloutmanager.core.models.RolloutItem; +import com.exadel.etoolbox.rolloutmanager.core.models.RolloutStatus; +import com.exadel.etoolbox.rolloutmanager.core.services.PageReplicationService; import com.exadel.etoolbox.rolloutmanager.core.servlets.util.ServletUtil; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.collections.CollectionUtils; @@ -39,6 +42,7 @@ import javax.json.Json; import javax.servlet.Servlet; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -67,11 +71,15 @@ public class RolloutServlet extends SlingAllMethodsServlet { private static final String SELECTION_JSON_ARRAY_PARAM = "selectionJsonArray"; private static final String IS_DEEP_ROLLOUT_PARAM = "isDeepRollout"; + private static final String SHOULD_ACTIVATE_PARAM = "shouldActivate"; private static final String FAILED_TARGETS_RESPONSE_PARAM = "failedTargets"; @Reference private transient RolloutManager rolloutManager; + @Reference + private transient PageReplicationService pageReplicationService; + @Override protected void doPost(final SlingHttpServletRequest request, final SlingHttpServletResponse response) { StopWatch sw = StopWatch.createStarted(); @@ -103,7 +111,16 @@ protected void doPost(final SlingHttpServletRequest request, final SlingHttpServ LOG.debug("Is deep rollout (include subpages): {}", isDeepRollout); List rolloutStatuses = doItemsRollout(rolloutItems, pageManager, isDeepRollout); - writeStatusesIfFailed(rolloutStatuses, response); + + boolean shouldActivate = ServletUtil.getRequestParamBoolean(request, SHOULD_ACTIVATE_PARAM); + LOG.debug("Should activate pages: {}", shouldActivate); + List activationStatuses = new ArrayList<>(); + if (shouldActivate) { + activationStatuses = pageReplicationService.replicateItems(request.getResourceResolver(), rolloutItems, request.getResourceResolver().adaptTo(PageManager.class)); + } + + writeStatusesIfFailed(Stream.concat(rolloutStatuses.stream(), activationStatuses.stream()) + .collect(Collectors.toList()), response); LOG.debug("Rollout of selected items is completed in {} ms", sw.getTime(TimeUnit.MILLISECONDS)); } @@ -192,48 +209,4 @@ private RolloutItem[] jsonArrayToRolloutItems(String jsonArray) { } return new RolloutItem[0]; } - - private static class RolloutItem { - private String master; - private String target; - private int depth; - boolean autoRolloutTrigger; - - public String getMaster() { - return master; - } - - public String getTarget() { - return target; - } - - public int getDepth() { - return depth; - } - - public boolean isAutoRolloutTrigger() { - return autoRolloutTrigger; - } - } - - private static class RolloutStatus { - private boolean isSuccess; - private final String target; - - public RolloutStatus(String target) { - this.target = target; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } - - public String getTarget() { - return target; - } - } } \ No newline at end of file diff --git a/core/src/test/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServletTest.java b/core/src/test/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServletTest.java index 631dbbd..078d4d7 100644 --- a/core/src/test/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServletTest.java +++ b/core/src/test/java/com/exadel/etoolbox/rolloutmanager/core/servlets/CollectLiveCopiesServletTest.java @@ -63,6 +63,9 @@ class CollectLiveCopiesServletTest { private static final String EXPECTED_RESPONSE_JSON = "src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items.json"; + private static final String EXPECTED_EMPTY_RESPONSE_JSON = + "src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items-with-no-valid-live-copy.json"; + private final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK); @Mock @@ -142,12 +145,13 @@ void doPost_RelationshipExcludeChildren_EmptyArrayResponse() throws WCMException } @Test - void doPost_NotAvailableForRollout_EmptyArrayResponse() throws WCMException { + void doPost_NotAvailableForRollout_EmptyResponse() throws WCMException, IOException { createSourceResource(); LiveRelationship relationship = mockSingleLiveRelationship(TEST_SOURCE_PATH); LiveCopy liveCopy = mock(LiveCopy.class); + when(liveCopy.getPath()).thenReturn(TEST_LIVE_COPY_PATH); when(relationship.getLiveCopy()).thenReturn(liveCopy); when(relationship.getSyncPath()).thenReturn(TEST_SYNC_PATH); @@ -156,7 +160,10 @@ void doPost_NotAvailableForRollout_EmptyArrayResponse() throws WCMException { .thenReturn(false); fixture.doPost(request, response); - assertEquals(JsonValue.EMPTY_JSON_ARRAY.toString(), response.getOutputAsString()); + + String expected = new String(Files.readAllBytes(Paths.get(EXPECTED_EMPTY_RESPONSE_JSON))) + .replaceAll("(\\r|\\n|\\t|\\s)", StringUtils.EMPTY); + assertEquals(expected, response.getOutputAsString()); } @Test diff --git a/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items-with-no-valid-live-copy.json b/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items-with-no-valid-live-copy.json new file mode 100644 index 0000000..18a15b0 --- /dev/null +++ b/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items-with-no-valid-live-copy.json @@ -0,0 +1,12 @@ +[ + { + "master": "/content/my-site/language-masters/en/testResource", + "path": "/content/my-site/fr/en/testResource", + "depth": 0, + "liveCopies": [], + "isNew": true, + "autoRolloutTrigger": false, + "lastRolledOut": "", + "disabled": true + } +] \ No newline at end of file diff --git a/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items.json b/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items.json index e287e59..7eba55f 100644 --- a/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items.json +++ b/core/src/test/resources/com/exadel/etoolbox/rolloutmanager/core/servlets/collect-expected-items.json @@ -11,11 +11,13 @@ "liveCopies": [], "isNew": true, "autoRolloutTrigger": false, - "lastRolledOut":"" + "lastRolledOut": "", + "disabled": false } ], "isNew": false, "autoRolloutTrigger": false, - "lastRolledOut":"" + "lastRolledOut": "", + "disabled": false } ] \ No newline at end of file diff --git a/pom.xml b/pom.xml index ea4cff8..45e4f09 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ com.exadel.etoolbox etoolbox-rollout-manager pom - 1.2.0 + 1.3.0-SNAPSHOT EToolbox Rollout Manager EToolbox Rollout Manager diff --git a/ui.apps.structure/pom.xml b/ui.apps.structure/pom.xml index 1cebc2e..73092b9 100644 --- a/ui.apps.structure/pom.xml +++ b/ui.apps.structure/pom.xml @@ -21,7 +21,7 @@ com.exadel.etoolbox etoolbox-rollout-manager - 1.2.0 + 1.3.0-SNAPSHOT ../pom.xml diff --git a/ui.apps/pom.xml b/ui.apps/pom.xml index 192c9ab..ff4ba79 100644 --- a/ui.apps/pom.xml +++ b/ui.apps/pom.xml @@ -21,7 +21,7 @@ com.exadel.etoolbox etoolbox-rollout-manager - 1.2.0 + 1.3.0-SNAPSHOT ../pom.xml diff --git a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/css/console-ui.checkboxlist.css b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/css/console-ui.checkboxlist.css index 7993e92..54e50d9 100644 --- a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/css/console-ui.checkboxlist.css +++ b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/css/console-ui.checkboxlist.css @@ -32,7 +32,6 @@ } .rollout-manager-select-all { - float: right; font-size: small; min-width: 86px; } @@ -58,7 +57,7 @@ .rollout-manager-dialog .coral3-Dialog-wrapper { width: 800px; - height: 526px; + height: 566px; } .rollout-manager-dialog .coral3-Checkbox { @@ -86,7 +85,7 @@ .rollout-manager-nestedcheckboxlist-container { overflow-y: auto; - height: 246px; + height: 206px; } .rollout-manager-logger-dialog .coral3-Dialog-wrapper { @@ -97,3 +96,11 @@ .rollout-manager-dialog .rollout-manager-last-rollout-date { z-index: 2; } + +#rolloutButton:not([disabled]) { + filter: brightness(1.3); +} + +/*.coral3-Accordion-label {*/ +/* font-weight: normal;*/ +/*}*/ diff --git a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.actions.js b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.actions.js index b9a421e..cb45ca3 100644 --- a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.actions.js +++ b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.actions.js @@ -16,7 +16,7 @@ * EToolbox Rollout Manager clientlib. * 'Rollout' button and dialog actions definition. */ -(function (window, document, $, ERM, Granite) { +(function (window, document, $, ns, Granite) { 'use strict'; const COLLECT_LIVE_COPIES_COMMAND = '/content/etoolbox-rollout-manager/servlet/collect-live-copies'; @@ -73,7 +73,7 @@ * @returns {*} */ function doItemsRollout(data, rolloutRequest) { - const logger = ERM.createLoggerDialog(PROCESSING_LABEL, ROLLOUT_IN_PROGRESS_LABEL, data.path); + const logger = ns.createLoggerDialog(PROCESSING_LABEL, ROLLOUT_IN_PROGRESS_LABEL, data.path); return $.Deferred() .resolve() .then(rolloutRequest(data, logger)) @@ -85,7 +85,7 @@ const ROLLOUT_COMMAND = '/content/etoolbox-rollout-manager/servlet/rollout'; const PROCESSING_ERROR_MSG = Granite.I18n.get('Rollout failed'); const PROCESSING_ERROR_FAILED_PATHS_MSG = Granite.I18n.get('Rollout failed for the following paths:'); - const SUCCESS_MSG = Granite.I18n.get('Selected live copies successfully synchronized'); + const SUCCESS_MSG = Granite.I18n.get('Completed'); function getProcessingErrorMsg(xhr) { if (xhr.status === 400 && xhr.responseJSON && xhr.responseJSON.failedTargets) { @@ -108,7 +108,8 @@ data: { _charset_: 'UTF-8', selectionJsonArray: JSON.stringify(data.selectionJsonArray), - isDeepRollout: data.isDeepRollout + isDeepRollout: data.isDeepRollout, + shouldActivate: data.shouldActivate } }).fail((xhr) => { logger.log(getProcessingErrorMsg(xhr), false); @@ -128,7 +129,7 @@ .then((liveCopiesJsonArray) => { // Clears the wait mask once the dialog is loaded foundationUi.clearWait(); - ERM.showRolloutDialog(liveCopiesJsonArray, selectedPath) + ns.showRolloutDialog(liveCopiesJsonArray, selectedPath) .then((data) => { doItemsRollout(data, buildRolloutRequest); }); @@ -153,4 +154,4 @@ name: 'etoolbox.rollout-manager.rollout-active-condition', handler: onRolloutActiveCondition }); -})(window, document, Granite.$, Granite.ERM, Granite); +})(window, document, Granite.$, window.erm = (window.erm || {}), Granite); diff --git a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.checkboxlist.js b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.checkboxlist.js index f021558..8d14bb7 100644 --- a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.checkboxlist.js +++ b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.checkboxlist.js @@ -28,7 +28,7 @@ 'use strict'; const INTERMEDIATE_ATTR = 'intermediate'; - const CORAL_CHECKBOX_ITEM = 'coral-checkbox[name="liveCopyProperties[]"]'; + const CORAL_CHECKBOX_ITEM = 'coral-checkbox[name="liveCopyProperties[]"]:not([disabled])'; function parentIntermediateStateOn(parentCheckbox) { parentCheckbox.attr(INTERMEDIATE_ATTR, true); @@ -79,6 +79,7 @@ childCheckboxes.removeAttr(INTERMEDIATE_ATTR); } } + childCheckboxes.filter(':not([disabled])').prop('checked', isChecked); childCheckboxes.prop('checked', isChecked); } diff --git a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.dialog.js b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.dialog.js index e6d1483..2216e78 100644 --- a/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.dialog.js +++ b/ui.apps/src/main/content/jcr_root/apps/etoolbox-rollout-manager/clientlibs/rollout-manager-ui/js/console-ui.dialog.js @@ -16,11 +16,9 @@ * EToolbox Rollout Manager clientlib. * Contains helper functions to showing the rollout process dialogs. */ -(function (window, document, $, Granite) { +(function (document, $, Granite, ns) { 'use strict'; - const Utils = Granite.ERM = (Granite.ERM || {}); - const LOGGER_DIALOG_CLASS = 'rollout-manager-logger-dialog'; const BASE_DIALOG_CLASS = 'rollout-manager-dialog'; @@ -103,11 +101,12 @@ } }; } - Utils.createLoggerDialog = createLoggerDialog; + ns.createLoggerDialog = createLoggerDialog; // Rollout dialog related constants const CANCEL_LABEL = Granite.I18n.get('Cancel'); const DIALOG_LABEL = Granite.I18n.get('Rollout'); + const ROLLOUT_AND_PUBLISH_LABEL = Granite.I18n.get('Rollout and Publish'); const SELECT_ALL_LABEL = Granite.I18n.get('Select all'); const UNSELECT_ALL_LABEL = Granite.I18n.get('Unselect all'); const TARGET_PATHS_LABEL = Granite.I18n.get('Target paths'); @@ -134,14 +133,14 @@ function appendTargetsHeader(sourceElement) { const span = $(''); - const selectAll = $('') - .text(SELECT_ALL_LABEL); - selectAll.appendTo(span); - const label = $('

') .text(TARGET_PATHS_LABEL); label.appendTo(span); + const selectAll = $('') + .text(SELECT_ALL_LABEL); + selectAll.appendTo(span); + span.appendTo(sourceElement); } @@ -181,12 +180,12 @@ data-depth="${liveCopyJson.depth}" data-auto-rollout="${liveCopyJson.autoRolloutTrigger}" value="${liveCopyJson.path}">` - ).text(liveCopyJson.path); + ).text(liveCopyJson.path).attr('disabled', !!liveCopyJson.disabled); const lastRolledOutTimeAgo = $(`` - ).text(TimeUtil.timeSince(liveCopyJson.lastRolledOut)); + ).text(ns.TimeUtil.timeSince(liveCopyJson.lastRolledOut)); liveCopyCheckbox.append(lastRolledOutTimeAgo); if (liveCopyJson.liveCopies && liveCopyJson.liveCopies.length > 0) { const accordion = initNestedAccordion(liveCopyCheckbox, liveCopyJson.liveCopies); @@ -228,7 +227,7 @@ } function selectUnselectAll() { - $(CORAL_CHECKBOX_ITEM).prop('checked', !hasSelection()); + $(CORAL_CHECKBOX_ITEM).filter(':not([disabled])').prop('checked', !hasSelection()); } function validateSelection(hasSelection, submitBtn) { @@ -246,8 +245,9 @@ onCheckboxChange(submitBtn); } - function onResolve(path, deferred) { - const isDeepRollout = $('coral-checkbox[name="isDeepRollout"]').prop('checked'); + function onResolve($btn, path, deferred) { + const shouldActivate = $btn.closest('[data-dialog-action]').data('dialogAction') === 'rolloutPublish'; + const isDeepRollout = $('coral-checkbox[name="isDeepRollout"]').filter(':not([disabled])').prop('checked'); const selectionJsonArray = []; $(CORAL_CHECKBOX_ITEM).each(function () { const checkbox = $(this); @@ -258,7 +258,8 @@ const data = { path, isDeepRollout, - selectionJsonArray + selectionJsonArray, + shouldActivate }; deferred.resolve(data); } @@ -285,8 +286,11 @@ const deferred = $.Deferred(); const dialog = initRolloutDialog(selectedPath); - const $submitBtn = $('