diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/template/TemplateResource.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/template/TemplateResource.java index c7206a9d5659..e85e380bd77f 100644 --- a/dotCMS/src/main/java/com/dotcms/rest/api/v1/template/TemplateResource.java +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/template/TemplateResource.java @@ -8,7 +8,6 @@ import com.dotcms.rest.api.BulkResultView; import com.dotcms.rest.api.FailedResultView; import com.dotcms.util.PaginationUtil; -import com.dotcms.util.pagination.ContainerPaginator; import com.dotcms.util.pagination.OrderDirection; import com.dotcms.util.pagination.TemplatePaginator; import com.dotmarketing.beans.Host; @@ -26,7 +25,6 @@ import com.dotmarketing.portlets.templates.business.TemplateSaveParameters; import com.dotmarketing.portlets.templates.design.bean.TemplateLayout; import com.dotmarketing.portlets.templates.design.util.DesignTemplateUtil; -import com.dotmarketing.portlets.templates.factories.TemplateFactory; import com.dotmarketing.portlets.templates.model.Template; import com.dotmarketing.util.ActivityLogger; import com.dotmarketing.util.InodeUtils; @@ -136,15 +134,26 @@ public final Response list(@Context final HttpServletRequest httpRequest, final InitDataObject initData = new WebResource.InitBuilder(webResource) .requestAndResponse(httpRequest, httpResponse).rejectWhenNoUser(true).init(); final User user = initData.getUser(); - final Lazy lazyCurrentHost = Lazy.of(() -> Try.of(() -> Host.class.cast(httpRequest.getSession().getAttribute(WebKeys.CURRENT_HOST)).getIdentifier()).getOrNull()); - final Optional checkedHostId = Optional.ofNullable(Try.of(()-> APILocator.getHostAPI() - .find(hostId, user, false).getIdentifier()).getOrElse(lazyCurrentHost.get())); + Logger.debug(this, ()-> "Getting the List of templates"); final Map extraParams = new HashMap<>(); extraParams.put(ARCHIVE_PARAM, archive); - checkedHostId.ifPresent(checkedHostIdentifier -> extraParams.put(ContainerPaginator.HOST_PARAMETER_ID, checkedHostIdentifier)); + + //In case we need to get the list of templates across multiple sites, we don't set the TemplatePaginator.HOST_PARAMETER_ID + if (null == hostId || !StringPool.STAR.equals(hostId)) { + final Lazy lazyCurrentHost = Lazy.of(() -> Try.of(() -> Host.class.cast( + httpRequest.getSession().getAttribute(WebKeys.CURRENT_HOST)).getIdentifier()) + .getOrNull()); + final Optional checkedHostId = Optional.ofNullable( + Try.of(() -> APILocator.getHostAPI() + .find(hostId, user, false).getIdentifier()) + .getOrElse(lazyCurrentHost.get())); + checkedHostId.ifPresent( + checkedHostIdentifier -> extraParams.put(TemplatePaginator.HOST_PARAMETER_ID, + checkedHostIdentifier)); + } return this.paginationUtil.getPage(httpRequest, user, filter, page, perPage, orderBy, OrderDirection.valueOf(direction), extraParams); } diff --git a/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl b/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl index e906b927dca2..c89aca255ee7 100644 --- a/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl +++ b/dotCMS/src/main/webapp/WEB-INF/velocity/static/htmlpage_assets/template_custom_field.vtl @@ -74,12 +74,10 @@ function fetchTemplateImage(templateId) { * Callback function to handle the template fetch * */ -const onTemplateFetchComplete = function(templates, currentRequest){ +const onTemplateFetchComplete = function(templates, currentRequest) { const templateId = dojo.byId("template").value; const isTemplateValid = templateId && templateId != "0"; - console.log("templateId", templateId); - if(!templates || templates.length === 0){ return; } @@ -93,29 +91,35 @@ const onTemplateFetchComplete = function(templates, currentRequest){ } const { identifier, fullTitle } = template; - // We set the values directly into the components because setting it direcrtly into`templateSel` fires another load operation. + + // We set the values directly into the components because setting it directly into`templateSelect` fires another load operation. dojo.byId("currentTemplateId").value = identifier; dojo.byId("template").value = identifier; dijit.byId('templateSel').set("displayedValue", fullTitle); fetchTemplateImage(identifier); }; +function resetTemplateSelection() { + const templateSel = dijit.byId("templateSel"); + templateSel.set("value",""); + templateSel.filter(); + dojo.byId("template").value= ''; + dojo.byId("templateSel").value = ""; + dojo.byId("currentTemplateId").value = ""; + dojo.byId("templateThumbnailHolder").src = "/html/images/shim.gif"; + dojo.byId("templateThumbnailHolder").style.border = '0px'; +} + /** * Handles the template change event * */ function templateChanged() { - const templateSel=dijit.byId("templateSel"); - const value=templateSel.get('value'); - - if(!value) { - return; - } - - if(value == "0") { - templateSel.set("value",""); - templateSel.filter(); + const templateSel = dijit.byId("templateSel"); + const value = templateSel?.get('value'); + if(!value || value == "0") { + resetTemplateSelection(); return; } @@ -151,11 +155,11 @@ dojo.ready(function(){ currentTemplateIdElement.value = templateId; const templateStore = new dotcms.dojo.data.TemplateReadStore({ - hostId: hostId, + hostId: '*', templateSelected: templateId }); - const templateSelect=new dijit.form.FilteringSelect({ + const templateSelect = new dijit.form.FilteringSelect({ id:"templateSel", name:"templateSel", style:"width:350px;", @@ -170,7 +174,7 @@ dojo.ready(function(){ labelAttr: "htmlTitle", searchAttr: "fullTitle", value: templateId, - invalidMessage: '$text.get("Invalid-option-selected")' + invalidMessage: '$text.get("Invalid-option-selected")', },"templateHolder"); if (isTemplateValid){ @@ -182,8 +186,7 @@ dojo.ready(function(){ const templateFetchParams = { query: { - fullTitle: '*', - hostId: hostId + fullTitle: '*' }, queryOptions: {}, start: 0, diff --git a/dotCMS/src/main/webapp/html/js/dotcms/dojo/data/TemplateReadStore.js b/dotCMS/src/main/webapp/html/js/dotcms/dojo/data/TemplateReadStore.js index 4e7dbe29fbbd..fb449474b813 100644 --- a/dotCMS/src/main/webapp/html/js/dotcms/dojo/data/TemplateReadStore.js +++ b/dotCMS/src/main/webapp/html/js/dotcms/dojo/data/TemplateReadStore.js @@ -11,10 +11,23 @@ dojo.declare("dotcms.dojo.data.TemplateReadStore", null, { includeTemplate: null, templateSelected: '', + /** + * To Emulate this old Backend Behavion + * https://github.com/dotCMS/core/blob/7bc05d335b98ffb30d909de9ec82dd4557b37078/dotCMS/src/main/java/com/dotmarketing/portlets/templates/ajax/TemplateAjax.java#L72-L76 + * + * @type {*} + * */ + ALL_SITE_TEMPLATE: { + title: "All Sites", + fullTitle: "All Sites", + htmlTitle: '
-- All Sites ---
', + identifier: "0", + inode: "0" + }, + constructor: function (options) { this.hostId = options.hostId; this.templateSelected = options.templateSelected; - window.top._dotTemplateStore = this; }, getValue: function (item, attribute, defaultValue) { @@ -95,20 +108,26 @@ dojo.declare("dotcms.dojo.data.TemplateReadStore", null, { } else { + const hostId = keywordArgs.query.hostId; + let url = "/api/v1/templates/?filter=" + keywordArgs.query.fullTitle.replace('*','') + "&page=" + keywordArgs.start + "&per_page=" + keywordArgs.count + (keywordArgs.sort == undefined || keywordArgs.sort != ""? "": "&orderby=" + keywordArgs.sort); - if (keywordArgs.query.hostId != undefined && keywordArgs.query.hostId != "") { - url += "&host=" + keywordArgs.query.hostId; + if (hostId != undefined && hostId != "") { + url += "&host=" + hostId; } fetch(url) .then((fetchResp) => fetchResp.json()) .then(responseEntity => { - this.fetchTemplatesCallback(keywordArgs, responseEntity); + if( hostId === '*') { + responseEntity.entity.unshift(this.ALL_SITE_TEMPLATE); } - ); + + + this.fetchTemplatesCallback(keywordArgs, responseEntity); + }); this.currentRequest = keywordArgs; this.currentRequest.abort = function () { }; @@ -117,7 +136,6 @@ dojo.declare("dotcms.dojo.data.TemplateReadStore", null, { }, fetchTemplatesCallback: function (keywordArgs, templatesEntity) { - var scope = keywordArgs.scope; if(keywordArgs.onBegin) { diff --git a/dotcms-integration/src/test/java/com/dotcms/rest/api/v1/template/TemplateResourceTest.java b/dotcms-integration/src/test/java/com/dotcms/rest/api/v1/template/TemplateResourceTest.java index 9af89f0e24bf..71a7a182a0bd 100644 --- a/dotcms-integration/src/test/java/com/dotcms/rest/api/v1/template/TemplateResourceTest.java +++ b/dotcms-integration/src/test/java/com/dotcms/rest/api/v1/template/TemplateResourceTest.java @@ -1,6 +1,5 @@ package com.dotcms.rest.api.v1.template; -import static com.dotcms.rendering.velocity.directive.ParseContainer.PARSE_CONTAINER_UUID_PREFIX; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -32,7 +31,6 @@ import com.dotmarketing.beans.MultiTree; import com.dotmarketing.beans.Permission; import com.dotmarketing.business.APILocator; -import com.dotmarketing.business.ApiProvider; import com.dotmarketing.business.PermissionAPI; import com.dotmarketing.exception.DoesNotExistException; import com.dotmarketing.exception.DotDataException; @@ -46,17 +44,18 @@ import com.dotmarketing.portlets.templates.model.Template; import com.dotmarketing.util.PageMode; import com.dotmarketing.util.PaginatedArrayList; +import com.dotmarketing.util.StringUtils; import com.dotmarketing.util.UUIDGenerator; import com.dotmarketing.util.WebKeys; import com.liferay.portal.model.User; import com.liferay.util.Base64; +import com.liferay.util.StringPool; import java.util.ArrayList; import java.util.Arrays; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.junit.Assert; @@ -1070,6 +1069,49 @@ public void test_listTemplate_filterByHost_usingCurrentHost() APILocator.getIdentifierAPI().find(((TemplateView) paginatedArrayListWihoutSystemTemplate.get(0)).getIdentifier()).getHostId()); } + /** + * Method to test: list in the TemplateResource + * Given Scenario: Create a template on hostA, and a template on hostB. List templates using the + * wildcard host as the query param. + * ExpectedResult: The endpoint should return 200, and templateA and templateB should be returned + */ + @Test + public void test_listTemplate_filterByHost_usingWildcardHost() + throws DotSecurityException, DotDataException { + final String title = "Template" + System.currentTimeMillis(); + final Host newHostA = new SiteDataGen().nextPersisted(); + final Host newHostB = new SiteDataGen().nextPersisted(); + + //Create templates in two different sites + final Template templateA = APILocator.getTemplateAPI() + .saveTemplate(new TemplateDataGen().title(title).next(), newHostA, adminUser, + false); + final Template templateB = APILocator.getTemplateAPI() + .saveTemplate(new TemplateDataGen().title(title).next(), newHostB, adminUser, + false); + + //Call Resource + final Response responseResource = resource.list( + getHttpRequest(adminUser.getEmailAddress(), "admin"), response, title, 0, 40, + "mod_date", "DESC", + StringPool.STAR, false); + //Check that the response is 200, OK + Assert.assertEquals(Status.OK.getStatusCode(), responseResource.getStatus()); + final ResponseEntityView responseEntityView = ResponseEntityView.class.cast( + responseResource.getEntity()); + final PaginatedArrayList paginatedArrayList = PaginatedArrayList.class.cast( + responseEntityView.getEntity()); + final PaginatedArrayList paginatedArrayListWihoutSystemTemplate = removeSystemTemplate( + paginatedArrayList); + Assert.assertEquals(2, paginatedArrayListWihoutSystemTemplate.size()); + paginatedArrayListWihoutSystemTemplate.stream().anyMatch( + templateView -> ((TemplateView) templateView).getIdentifier() + .equals(templateA.getIdentifier())); + paginatedArrayListWihoutSystemTemplate.stream().anyMatch( + templateView -> ((TemplateView) templateView).getIdentifier() + .equals(templateB.getIdentifier())); + } + /** * Method to test: list in the TemplateResource * Given Scenario: Create 2 templates, and a limited user. Give READ Permissions to one template to