This is an automated email from the ASF dual-hosted git repository. dklco pushed a commit to branch SLING-8913-multiple-instance-types in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git
commit 3a3a691ee4f018b6396408955ec4c01287ce6044 Author: Dan Klco <[email protected]> AuthorDate: Thu Aug 27 17:03:07 2020 -0400 Adding the new publication UI --- .../cms/core/publication/PublishPostOperation.java | 68 ++++++++ .../core/publication/UnpublishPostOperation.java | 68 ++++++++ .../core/publication/PublishPostOperationTest.java | 74 +++++++++ .../publication/UnpublishPostOperationTest.java | 74 +++++++++ core/src/test/resources/content.json | 10 ++ .../apps/reference/components/pages/base/edit.json | 173 +++++++++---------- .../apps/reference/components/pages/post/edit.json | 185 +++++++++------------ ui/src/main/frontend/scss/cms.scss | 13 ++ ui/src/main/resources/jcr_root/conf/global.json | 9 +- .../components/cms/columns/publish/publish.jsp | 5 +- .../components/cms/contentgrid/contentgrid.jsp | 78 ++++----- .../cms/publicationstatus/publicationstatus.jsp | 53 ++++++ .../components/editor/fields/publication.json | 5 + .../components/editor/fields/publication/field.jsp | 73 ++++++++ .../libs/sling-cms/content/shared/publish.json | 18 +- .../libs/sling-cms/content/shared/unpublish.json | 18 +- .../resources/jcr_root/libs/sling-cms/i18n.json | 25 +++ 17 files changed, 683 insertions(+), 266 deletions(-) diff --git a/core/src/main/java/org/apache/sling/cms/core/publication/PublishPostOperation.java b/core/src/main/java/org/apache/sling/cms/core/publication/PublishPostOperation.java new file mode 100644 index 0000000..ad1672b --- /dev/null +++ b/core/src/main/java/org/apache/sling/cms/core/publication/PublishPostOperation.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.sling.cms.core.publication; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.cms.PublishableResource; +import org.apache.sling.cms.publication.PublicationManagerFactory; +import org.apache.sling.servlets.post.Modification; +import org.apache.sling.servlets.post.PostOperation; +import org.apache.sling.servlets.post.PostResponse; +import org.apache.sling.servlets.post.SlingPostProcessor; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A Sling Post Operation to publish content + */ +@Component(immediate = true, service = { PostOperation.class }, property = PostOperation.PROP_OPERATION_NAME + + "=publish") +public class PublishPostOperation implements PostOperation { + + private static final Logger log = LoggerFactory.getLogger(PublishPostOperation.class); + + @Reference + private PublicationManagerFactory publicationManagerFactory; + + @Override + public void run(SlingHttpServletRequest request, PostResponse response, SlingPostProcessor[] processors) { + final List<Modification> changes = new ArrayList<>(); + try { + publicationManagerFactory.getPublicationManager() + .publish(request.getResource().adaptTo(PublishableResource.class)); + + if (processors != null) { + for (SlingPostProcessor processor : processors) { + processor.process(request, changes); + } + } + + request.getResourceResolver().commit(); + + response.setPath(request.getResource().getPath()); + response.onModified(request.getResource().getPath()); + } catch (Exception e) { + log.error("Failed to publish", e); + response.setError(e); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/org/apache/sling/cms/core/publication/UnpublishPostOperation.java b/core/src/main/java/org/apache/sling/cms/core/publication/UnpublishPostOperation.java new file mode 100644 index 0000000..1dff941 --- /dev/null +++ b/core/src/main/java/org/apache/sling/cms/core/publication/UnpublishPostOperation.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.sling.cms.core.publication; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.cms.PublishableResource; +import org.apache.sling.cms.publication.PublicationManagerFactory; +import org.apache.sling.servlets.post.Modification; +import org.apache.sling.servlets.post.PostOperation; +import org.apache.sling.servlets.post.PostResponse; +import org.apache.sling.servlets.post.SlingPostProcessor; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A Sling Post Operation to unpublish content + */ +@Component(immediate = true, service = { PostOperation.class }, property = PostOperation.PROP_OPERATION_NAME + + "=unpublish") +public class UnpublishPostOperation implements PostOperation { + + private static final Logger log = LoggerFactory.getLogger(UnpublishPostOperation.class); + + @Reference + private PublicationManagerFactory publicationManagerFactory; + + @Override + public void run(SlingHttpServletRequest request, PostResponse response, SlingPostProcessor[] processors) { + final List<Modification> changes = new ArrayList<>(); + try { + publicationManagerFactory.getPublicationManager() + .unpublish(request.getResource().adaptTo(PublishableResource.class)); + + if (processors != null) { + for (SlingPostProcessor processor : processors) { + processor.process(request, changes); + } + } + + request.getResourceResolver().commit(); + + response.setPath(request.getResource().getPath()); + response.onModified(request.getResource().getPath()); + } catch (Exception e) { + log.error("Failed to publish", e); + response.setError(e); + } + } +} \ No newline at end of file diff --git a/core/src/test/java/org/apache/sling/cms/core/publication/PublishPostOperationTest.java b/core/src/test/java/org/apache/sling/cms/core/publication/PublishPostOperationTest.java new file mode 100644 index 0000000..38b4d2d --- /dev/null +++ b/core/src/test/java/org/apache/sling/cms/core/publication/PublishPostOperationTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.sling.cms.core.publication; + +import org.apache.sling.cms.core.helpers.SlingCMSTestHelper; +import org.apache.sling.cms.publication.PublicationException; +import org.apache.sling.cms.publication.PublicationManager; +import org.apache.sling.cms.publication.PublicationManagerFactory; +import org.apache.sling.servlets.post.PostResponse; +import org.apache.sling.testing.mock.sling.junit.SlingContext; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +public class PublishPostOperationTest { + + @Rule + public final SlingContext context = new SlingContext(); + + @Before + public void init() { + SlingCMSTestHelper.initContext(context); + context.currentResource("/content/apache/sling-apache-org/index"); + } + + @Test + public void testPublish() throws PublicationException { + PublicationManagerFactory publicationManagerFactory = Mockito.mock(PublicationManagerFactory.class); + PublicationManager publicationManager = Mockito.mock(PublicationManager.class); + Mockito.when(publicationManagerFactory.getPublicationManager()).thenReturn(publicationManager); + context.registerService(PublicationManagerFactory.class, publicationManagerFactory); + PublishPostOperation publishPostOperation = context.registerInjectActivateService(new PublishPostOperation()); + PostResponse response = Mockito.mock(PostResponse.class); + + publishPostOperation.run(context.request(), response, null); + + Mockito.verify(publicationManager).publish(Mockito.any()); + + Mockito.verify(response, Mockito.never()).setError(Mockito.any()); + Mockito.verify(response).setPath(context.currentResource().getPath()); + } + + @Test + public void testPublishFailure() throws PublicationException { + PublicationManagerFactory publicationManagerFactory = Mockito.mock(PublicationManagerFactory.class); + PublicationManager publicationManager = Mockito.mock(PublicationManager.class); + PublicationException ex = new PublicationException("OH NO MR BILL"); + Mockito.doThrow(ex).when(publicationManager).publish(Mockito.any()); + Mockito.when(publicationManagerFactory.getPublicationManager()).thenReturn(publicationManager); + context.registerService(PublicationManagerFactory.class, publicationManagerFactory); + PublishPostOperation publishPostOperation = context.registerInjectActivateService(new PublishPostOperation()); + PostResponse response = Mockito.mock(PostResponse.class); + + publishPostOperation.run(context.request(), response, null); + + Mockito.verify(response).setError(ex); + } + +} \ No newline at end of file diff --git a/core/src/test/java/org/apache/sling/cms/core/publication/UnpublishPostOperationTest.java b/core/src/test/java/org/apache/sling/cms/core/publication/UnpublishPostOperationTest.java new file mode 100644 index 0000000..28b87e3 --- /dev/null +++ b/core/src/test/java/org/apache/sling/cms/core/publication/UnpublishPostOperationTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.sling.cms.core.publication; + +import org.apache.sling.cms.core.helpers.SlingCMSTestHelper; +import org.apache.sling.cms.publication.PublicationException; +import org.apache.sling.cms.publication.PublicationManager; +import org.apache.sling.cms.publication.PublicationManagerFactory; +import org.apache.sling.servlets.post.PostResponse; +import org.apache.sling.testing.mock.sling.junit.SlingContext; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +public class UnpublishPostOperationTest { + + @Rule + public final SlingContext context = new SlingContext(); + + @Before + public void init() { + SlingCMSTestHelper.initContext(context); + context.currentResource("/content/apache/sling-apache-org/index"); + } + + @Test + public void testUnpublish() throws PublicationException { + PublicationManagerFactory publicationManagerFactory = Mockito.mock(PublicationManagerFactory.class); + PublicationManager publicationManager = Mockito.mock(PublicationManager.class); + Mockito.when(publicationManagerFactory.getPublicationManager()).thenReturn(publicationManager); + context.registerService(PublicationManagerFactory.class, publicationManagerFactory); + UnpublishPostOperation unpublishPostOperation = context.registerInjectActivateService(new UnpublishPostOperation()); + PostResponse response = Mockito.mock(PostResponse.class); + + unpublishPostOperation.run(context.request(), response, null); + + Mockito.verify(publicationManager).unpublish(Mockito.any()); + + Mockito.verify(response, Mockito.never()).setError(Mockito.any()); + Mockito.verify(response).setPath(context.currentResource().getPath()); + } + + @Test + public void testUnpublishFailure() throws PublicationException { + PublicationManagerFactory publicationManagerFactory = Mockito.mock(PublicationManagerFactory.class); + PublicationManager publicationManager = Mockito.mock(PublicationManager.class); + PublicationException ex = new PublicationException("OH NO MR BILL"); + Mockito.doThrow(ex).when(publicationManager).unpublish(Mockito.any()); + Mockito.when(publicationManagerFactory.getPublicationManager()).thenReturn(publicationManager); + context.registerService(PublicationManagerFactory.class, publicationManagerFactory); + UnpublishPostOperation unpublishPostOperation = context.registerInjectActivateService(new UnpublishPostOperation()); + PostResponse response = Mockito.mock(PostResponse.class); + + unpublishPostOperation.run(context.request(), response, null); + + Mockito.verify(response).setError(ex); + } + +} \ No newline at end of file diff --git a/core/src/test/resources/content.json b/core/src/test/resources/content.json index 7acf199..7622552 100644 --- a/core/src/test/resources/content.json +++ b/core/src/test/resources/content.json @@ -55,6 +55,16 @@ "jcr:language": "en", "sling:url": "https://sling.apache.org", "jcr:created": "Wed May 15 2019 12:40:00 GMT-0400", + "unpublished": { + "jcr:primaryType": "sling:Page", + "jcr:content": { + "jcr:primaryType": "nt:unstructured", + "jcr:title": "Not Published", + "sling:template": "/conf/global/site/templates/base-page", + "sling:resourceType": "reference/components/pages/base", + "sling:published": false + } + }, "index": { "jcr:primaryType": "sling:Page", "jcr:mixinTypes": [ diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/pages/base/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/pages/base/edit.json index 19d4ae2..65a4295 100644 --- a/reference/src/main/resources/jcr_root/apps/reference/components/pages/base/edit.json +++ b/reference/src/main/resources/jcr_root/apps/reference/components/pages/base/edit.json @@ -1,97 +1,78 @@ - { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/slingform", - "button": "Save Page", - "fields": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/general/container", - "title": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/text", - "label": "Title", - "name": "jcr:title", - "required": true - }, - "description": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/textarea", - "label": "Description", - "name": "jcr:description" - }, - "taxonomy": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/taxonomy", - "label": "Keywords", - "name": "sling:taxonomy" - }, - "taxonomyTypeHint": { - "jcr:primaryType": "nt:unstructured", - "name": "jcr:content/sling:taxonomy@TypeHint", - "value": "String[]", - "sling:resourceType": "sling-cms/components/editor/fields/hidden" - }, - "canonical": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/path", - "basePath": "/content", - "type": "page", - "label": "Canonical", - "name": "canonical" - }, - "published": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/select", - "label": "Published", - "name": "published", - "options": { - "yes": { - "jcr:primaryType": "nt:unstructured", - "label": "Yes", - "value": "true" - }, - "no": { - "jcr:primaryType": "nt:unstructured", - "label": "No", - "value": "false" - } - } - }, - "publishedTypeHint": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "published@TypeHint", - "value": "Boolean" - }, - "hideInSitemap": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/select", - "label": "Hide in Sitemap", - "name": "hideInSitemap", - "options": { - "no": { - "jcr:primaryType": "nt:unstructured", - "label": "No", - "value": "false" - }, - "yes": { - "jcr:primaryType": "nt:unstructured", - "label": "Yes", - "value": "true" - } - } - }, - "hideInSitemapTypeHint": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "hideInSitemap@TypeHint", - "value": "Boolean" - }, - "template": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/text", - "label": "Template", - "name": "sling:template", - "disabled": true - } - } +{ + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/slingform", + "button": "Save Page", + "fields": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/general/container", + "title": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/text", + "label": "Title", + "name": "jcr:title", + "required": true + }, + "description": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/textarea", + "label": "Description", + "name": "jcr:description" + }, + "taxonomy": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/taxonomy", + "label": "Keywords", + "name": "sling:taxonomy" + }, + "taxonomyTypeHint": { + "jcr:primaryType": "nt:unstructured", + "name": "jcr:content/sling:taxonomy@TypeHint", + "value": "String[]", + "sling:resourceType": "sling-cms/components/editor/fields/hidden" + }, + "canonical": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/path", + "basePath": "/content", + "type": "page", + "label": "Canonical", + "name": "canonical" + }, + "publication": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/publication", + "label": "Publication" + }, + "hideInSitemap": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/select", + "label": "Hide in Sitemap", + "name": "hideInSitemap", + "options": { + "no": { + "jcr:primaryType": "nt:unstructured", + "label": "No", + "value": "false" + }, + "yes": { + "jcr:primaryType": "nt:unstructured", + "label": "Yes", + "value": "true" + } + } + }, + "hideInSitemapTypeHint": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/hidden", + "name": "hideInSitemap@TypeHint", + "value": "Boolean" + }, + "template": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/text", + "label": "Template", + "name": "sling:template", + "disabled": true + } + } } \ No newline at end of file diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/pages/post/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/pages/post/edit.json index c568024..425f97b 100644 --- a/reference/src/main/resources/jcr_root/apps/reference/components/pages/post/edit.json +++ b/reference/src/main/resources/jcr_root/apps/reference/components/pages/post/edit.json @@ -1,104 +1,85 @@ { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/slingform", - "button": "Save Page", - "fields": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/general/container", - "title": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/text", - "label": "Title", - "name": "jcr:title", - "required": true - }, - "description": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/textarea", - "label": "Description", - "name": "jcr:description" - }, - "taxonomy": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/taxonomy", - "label": "Keywords", - "name": "sling:taxonomy" - }, - "taxonomyTypeHint": { - "jcr:primaryType": "nt:unstructured", - "name": "jcr:content/sling:taxonomy@TypeHint", - "value": "String[]", - "sling:resourceType": "sling-cms/components/editor/fields/hidden" - }, - "canonical": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/path", - "basePath": "/content", - "type": "page", - "label": "Canonical", - "name": "canonical" - }, - "published": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/select", - "label": "Published", - "name": "published", - "options": { - "yes": { - "jcr:primaryType": "nt:unstructured", - "label": "Yes", - "value": "true" - }, - "no": { - "jcr:primaryType": "nt:unstructured", - "label": "No", - "value": "false" - } - } - }, - "publishedTypeHint": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "published@TypeHint", - "value": "Boolean" - }, - "publishDate": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/text", - "label": "Published Date", - "name": "publishDate", - "type": "date" - }, - "hideInSitemap": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/select", - "label": "Hide in Sitemap", - "name": "hideInSitemap", - "options": { - "no": { - "jcr:primaryType": "nt:unstructured", - "label": "No", - "value": "false" - }, - "yes": { - "jcr:primaryType": "nt:unstructured", - "label": "Yes", - "value": "true" - } - } - }, - "hideInSitemapTypeHint": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "hideInSitemap@TypeHint", - "value": "Boolean" - }, - "template": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/text", - "label": "Template", - "name": "sling:template", - "disabled": true - } - } + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/slingform", + "button": "Save Page", + "fields": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/general/container", + "title": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/text", + "label": "Title", + "name": "jcr:title", + "required": true + }, + "description": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/textarea", + "label": "Description", + "name": "jcr:description" + }, + "taxonomy": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/taxonomy", + "label": "Keywords", + "name": "sling:taxonomy" + }, + "taxonomyTypeHint": { + "jcr:primaryType": "nt:unstructured", + "name": "jcr:content/sling:taxonomy@TypeHint", + "value": "String[]", + "sling:resourceType": "sling-cms/components/editor/fields/hidden" + }, + "canonical": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/path", + "basePath": "/content", + "type": "page", + "label": "Canonical", + "name": "canonical" + }, + "published": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/publication", + "label": "Published" + }, + "publishDate": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/text", + "label": "Published Date", + "name": "publishDate", + "type": "date" + }, + "hideInSitemap": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/select", + "label": "Hide in Sitemap", + "name": "hideInSitemap", + "options": { + "no": { + "jcr:primaryType": "nt:unstructured", + "label": "No", + "value": "false" + }, + "yes": { + "jcr:primaryType": "nt:unstructured", + "label": "Yes", + "value": "true" + } + } + }, + "hideInSitemapTypeHint": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/hidden", + "name": "hideInSitemap@TypeHint", + "value": "Boolean" + }, + "template": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/editor/fields/text", + "label": "Template", + "name": "sling:template", + "disabled": true + } + } } \ No newline at end of file diff --git a/ui/src/main/frontend/scss/cms.scss b/ui/src/main/frontend/scss/cms.scss index ede12e8..75dc2ed 100644 --- a/ui/src/main/frontend/scss/cms.scss +++ b/ui/src/main/frontend/scss/cms.scss @@ -37,6 +37,15 @@ body.cms { } } +.card-footer-group { + display: flex !important; + flex-direction: column; +} + +.card-footer-group small { + font-size: 0.75em; +} + dl { padding: 1em 0; } @@ -49,6 +58,10 @@ dt { font-weight: bold; } +fieldset { + min-inline-size: auto; +} + h1 { font-size: 200%; } diff --git a/ui/src/main/resources/jcr_root/conf/global.json b/ui/src/main/resources/jcr_root/conf/global.json index 622b168..1089ded 100644 --- a/ui/src/main/resources/jcr_root/conf/global.json +++ b/ui/src/main/resources/jcr_root/conf/global.json @@ -58,16 +58,9 @@ }, "published": { "jcr:primaryType": "nt:unstructured", - "options": "Yes=true, No=false", "name": "jcr:content/published", "label": "Published", - "sling:resourceType": "sling-cms/components/editor/fields/select" - }, - "publishedTypeHint": { - "jcr:primaryType": "nt:unstructured", - "name": "jcr:content/published@TypeHint", - "value": "Boolean", - "sling:resourceType": "sling-cms/components/editor/fields/hidden" + "sling:resourceType": "sling-cms/components/editor/fields/publication" }, "filemetadata": { "jcr:primaryType": "nt:unstructured", diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/columns/publish/publish.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/columns/publish/publish.jsp index c74c4a6..6edc01e 100644 --- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/columns/publish/publish.jsp +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/columns/publish/publish.jsp @@ -17,9 +17,10 @@ * under the License. */ --%> <%@include file="/libs/sling-cms/global.jsp"%> -<td data-value="${sling:getRelativeResource(resource,'jcr:content').valueMap.published ? 0 : 1}"> +<sling:adaptTo adaptable="${resource}" adaptTo="org.apache.sling.cms.PublishableResource" var="publishableResource" /> +<td data-value="${publishableResource.published ? 0 : 1}"> <c:choose> - <c:when test="${sling:getRelativeResource(resource,'jcr:content').valueMap.published}"> + <c:when test="${publishableResource.published}"> <a class="button is-success is-outlined Fetch-Modal" href="/cms/shared/unpublish.html${resource.path}" title="Content Published" data-title="Unpublish" data-path=".Main-Content form"> <i class="jam jam-check"> <span class="is-vhidden">Content Published</span> diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentgrid/contentgrid.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentgrid/contentgrid.jsp index 7678f2c..8b2d6a8 100644 --- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentgrid/contentgrid.jsp +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentgrid/contentgrid.jsp @@ -28,6 +28,18 @@ </c:forEach> <c:if test="${showCard}"> <div class="tile is-parent is-3 contentnav__item"> + <sling:getResource base="${resource}" path="types/${child.valueMap['jcr:primaryType']}/columns/name" var="nameConfig" /> + <c:choose> + <c:when test="${not empty child.valueMap['jcr:content/jcr:title']}"> + <c:set var="title" value="${child.valueMap['jcr:content/jcr:title']}" /> + </c:when> + <c:when test="${not empty child.valueMap['jcr:title']}"> + <c:set var="title" value="${child.valueMap['jcr:title']}" /> + </c:when> + <c:otherwise> + <c:set var="title" value="${child.name}" /> + </c:otherwise> + </c:choose> <div class="tile is-child"> <div class="card is-linked" title="${sling:encode(child.name,'HTML_ATTR')}" data-value="${child.path}"> <div class="card-image"> @@ -62,57 +74,47 @@ <sling:getResource base="${resource}" path="types/${child.valueMap['jcr:primaryType']}/columns/actions" var="colConfig" /> <c:forEach var="ac" items="${sling:listChildren(colConfig)}"> <c:set var="actionConfig" value="${ac}" scope="request" /> - <!-- Resource: ${resource} --> - <!-- Action Config: ${actionConfig} --> <sling:include path="${child.path}" resourceType="${actionConfig.resourceType}" /> </c:forEach> </div> </div> <footer class="card-footer"> - <sling:getResource base="${resource}" path="types/${child.valueMap['jcr:primaryType']}/columns/name" var="nameConfig" /> - <c:choose> - <c:when test="${not empty child.valueMap['jcr:content/jcr:title']}"> - <c:set var="title" value="${child.valueMap['jcr:content/jcr:title']}" /> - </c:when> - <c:when test="${not empty child.valueMap['jcr:title']}"> - <c:set var="title" value="${child.valueMap['jcr:title']}" /> - </c:when> - <c:otherwise> - <c:set var="title" value="${child.name}" /> - </c:otherwise> - </c:choose> - <div class="card-footer-item"> + <div class="card-footer-item card-footer-group"> <c:choose> <c:when test="${child.resourceType == 'sling:Site' || child.resourceType == 'sling:OrderedFolder' || child.resourceType == 'sling:Folder' || child.resourceType == 'nt:folder' || child.resourceType == 'sling:Page'}"> - <a href="${nameConfig.valueMap.prefix}${child.path}" class="item-link">${sling:encode(title,'HTML')}</a><br/> + <a href="${nameConfig.valueMap.prefix}${child.path}" class="item-link">${sling:encode(title,'HTML')}</a> </c:when> <c:otherwise> - ${sling:encode(title,'HTML')}<br/> + <span>${sling:encode(title,'HTML')}</span> </c:otherwise> </c:choose> - <small> - <c:choose> - <c:when test="${sling:getRelativeResource(child,'jcr:content').valueMap.published}"> - <a class="Fetch-Modal has-text-success" href="/cms/shared/unpublish.html${child.path}" title="Content Published" data-title="Unpublish" data-path=".Main-Content form"> - <em class="jam jam-check"> - <span class="is-vhidden">Content Published</span> - </em> - </a> - </c:when> - <c:otherwise> - <a class="has-text-warning Fetch-Modal" href="/cms/shared/publish.html${child.path}" title="Content Not Published" data-title="Publish" data-path=".Main-Content form"> - <em class="jam jam-close"> - <span class="is-vhidden">Content Not Published</span> - </em> - </a> - </c:otherwise> - </c:choose> - <c:catch var="ex"> - <fmt:formatDate type="both" dateStyle="long" timeStyle="long" value = "${child.valueMap['jcr:content/jcr:lastModified'].time}" /> - </c:catch> - </small> + <c:catch var="ex"> + <small> + <fmt:formatDate type="both" dateStyle="long" timeStyle="long" value = "${child.valueMap['jcr:content/jcr:lastModified'].time}" /> + </small> + </c:catch> </div> </footer> + <footer class="card-footer"> + <sling:adaptTo adaptable="${child}" adaptTo="org.apache.sling.cms.PublishableResource" var="publishableResource" /> + <c:if test="${child.resourceType == 'sling:Page' || child.resourceType == 'sling:File' || child.resourceType == 'nt:file'}"> + <c:choose> + <c:when test="${publishableResource.published}"> + <a class="Fetch-Modal card-footer-item" href="/cms/shared/unpublish.html${child.path}" title="Content Published" data-title="Unpublish" data-path=".Main-Content form"> + Unpublish + </a> + </c:when> + <c:otherwise> + <a class="Fetch-Modal card-footer-item" href="/cms/shared/publish.html${child.path}" title="Content Not Published" data-title="Publish" data-path=".Main-Content form"> + Publish + </a> + </c:otherwise> + </c:choose> + </c:if> + <c:if test="${child.resourceType == 'sling:Site' || child.resourceType == 'sling:OrderedFolder' || child.resourceType == 'sling:Folder' || child.resourceType == 'nt:folder' || child.resourceType == 'sling:Page'}"> + <a href="${nameConfig.valueMap.prefix}${child.path}" class="card-footer-item">Open</a> + </c:if> + </footer> </div> </div> </div> diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/publicationstatus/publicationstatus.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/publicationstatus/publicationstatus.jsp new file mode 100644 index 0000000..ddb9a49 --- /dev/null +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/publicationstatus/publicationstatus.jsp @@ -0,0 +1,53 @@ +<%-- /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ --%> +<%@include file="/libs/sling-cms/global.jsp"%> +<sling:adaptTo adaptable="${slingRequest.requestPathInfo.suffixResource}" adaptTo="org.apache.sling.cms.PublishableResource" var="publishableResource" /> +<dl class="my-3"> + <dt> + <fmt:message key="slingcms.published" /> + </dt> + <dd> + <sling:encode value="${publishableResource.published}" mode="HTML" /> + </dd> + <c:if test="${publishableResource.lastPublication.time != null}"> + <dt> + <fmt:message key="slingcms.lastpublication" /> + </dt> + <dd> + <fmt:formatDate value="${publishableResource.lastPublication.time}" type="both" /> + </dd> + </c:if> + <c:if test="${not empty publishableResource.lastPublicationBy}"> + <dt> + <fmt:message key="slingcms.lastpublicationby" /> + </dt> + <dd> + <sling:encode value="${publishableResource.lastPublicationBy}" mode="HTML" /> + </dd> + </c:if> + <c:if test="${not empty publishableResource.lastPublicationType}"> + <dt> + <fmt:message key="slingcms.lastpublicationtype" /> + </dt> + <dd> + <sling:encode value="${publishableResource.lastPublicationType}" mode="HTML" /> + </dd> + </c:if> +</dl> +<hr/> \ No newline at end of file diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/publication.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/publication.json new file mode 100644 index 0000000..b40ab8f --- /dev/null +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/publication.json @@ -0,0 +1,5 @@ +{ + "jcr:primaryType": "sling:Component", + "sling:resourceSuperType" : "sling-cms/components/editor/fields/base", + "jcr:title": "Sling CMS - Publication Field" +} \ No newline at end of file diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/publication/field.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/publication/field.jsp new file mode 100644 index 0000000..c267eb3 --- /dev/null +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/publication/field.jsp @@ -0,0 +1,73 @@ +<%-- /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ --%> + <%@include file="/libs/sling-cms/global.jsp"%> +<sling:adaptTo adaptable="${slingRequest.requestPathInfo.suffixResource.parent}" adaptTo="org.apache.sling.cms.PublishableResource" var="publishableResource" /> + +<div class="columns"> + <div class="column"> + <dl> + <dt> + <fmt:message key="slingcms.published" /> + </dt> + <dd> + <sling:encode value="${publishableResource.published}" mode="HTML" /> + </dd> + <c:if test="${publishableResource.lastPublication.time != null}"> + <dt> + <fmt:message key="slingcms.lastpublication" /> + </dt> + <dd> + <fmt:formatDate value="${publishableResource.lastPublication.time}" type="both" /> + </dd> + </c:if> + <c:if test="${not empty publishableResource.lastPublicationBy}"> + <dt> + <fmt:message key="slingcms.lastpublicationby" /> + </dt> + <dd> + <sling:encode value="${publishableResource.lastPublicationBy}" mode="HTML" /> + </dd> + </c:if> + <c:if test="${not empty publishableResource.lastPublicationType}"> + <dt> + <fmt:message key="slingcms.lastpublicationtype" /> + </dt> + <dd> + <sling:encode value="${publishableResource.lastPublicationType}" mode="HTML" /> + </dd> + </c:if> + </dl> + </div> + <div class="column"> + <c:choose> + <c:when test="${publishableResource.published}"> + <a class="Fetch-Modal button is-success is-outlined" href="/cms/shared/unpublish.html${sling:encode(slingRequest.requestPathInfo.suffixResource.parent.path,'HTML_ATTR')}" title="Content Published" data-title="Unpublish" data-path=".Main-Content form"> + Unpublish + </a> + </c:when> + <c:otherwise> + <a class="Fetch-Modal button is-warning is-outlined" href="/cms/shared/publish.html${sling:encode(slingRequest.requestPathInfo.suffixResource.parent.path,'HTML_ATTR')}" title="Content Not Published" data-title="Publish" data-path=".Main-Content form"> + Publish + </a> + </c:otherwise> + </c:choose> + </div> +</div> + + diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/publish.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/publish.json index bb76104..04bf291 100644 --- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/publish.json +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/publish.json @@ -2,11 +2,15 @@ "jcr:primaryType": "sling:Page", "jcr:content": { "sling:resourceType": "sling-cms/components/pages/modal", - "jcr:title": "Publish Content", + "jcr:title": "Publication Status", "jcr:primaryType": "nt:unstructured", "container": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "sling-cms/components/general/container", + "publicationstatus": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/cms/publicationstatus" + }, "slingform": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "sling-cms/components/editor/slingform", @@ -19,17 +23,11 @@ "sling:resourceType": "sling-cms/components/editor/fields/suffixlabel", "label": "Do you want to publish:" }, - "published": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "jcr:content/published", - "value": "true" - }, - "publishedTypeHint": { + "operation": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "jcr:content/published@TypeHint", - "value": "Boolean" + "name": ":operation", + "value": "publish" } } } diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/unpublish.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/unpublish.json index a17a473..06e44a4 100644 --- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/unpublish.json +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/unpublish.json @@ -2,11 +2,15 @@ "jcr:primaryType": "sling:Page", "jcr:content": { "sling:resourceType": "sling-cms/components/pages/modal", - "jcr:title": "Unpublish Content", + "jcr:title": "Publication Status", "jcr:primaryType": "nt:unstructured", "container": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "sling-cms/components/general/container", + "publicationstatus": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "sling-cms/components/cms/publicationstatus" + }, "slingform": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "sling-cms/components/editor/slingform", @@ -19,17 +23,11 @@ "sling:resourceType": "sling-cms/components/editor/fields/suffixlabel", "label": "Do you want to unpublish:" }, - "published": { - "jcr:primaryType": "nt:unstructured", - "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "jcr:content/published", - "value": "false" - }, - "publishedTypeHint": { + "operation": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "sling-cms/components/editor/fields/hidden", - "name": "jcr:content/published@TypeHint", - "value": "Boolean" + "name": ":operation", + "value": "unpublish" } } } diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json b/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json index 5a136bd..5441116 100644 --- a/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json +++ b/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json @@ -95,6 +95,31 @@ "sling:message": "Job Properties", "sling:key": "slingcms.jobs.properties" }, + "slingcms-publicationstatus": { + "jcr:primaryType": "sling:MessageEntry", + "sling:message": "Publication Status", + "sling:key": "slingcms.publicationstatus" + }, + "slingcms-published": { + "jcr:primaryType": "sling:MessageEntry", + "sling:message": "Published", + "sling:key": "slingcms.published" + }, + "slingcms-lastpublication": { + "jcr:primaryType": "sling:MessageEntry", + "sling:message": "Last Publication", + "sling:key": "slingcms.lastpublication" + }, + "slingcms-lastpublicationby": { + "jcr:primaryType": "sling:MessageEntry", + "sling:message": "Last Publication By", + "sling:key": "slingcms.lastpublicationby" + }, + "slingcms-lastpublicationtype": { + "jcr:primaryType": "sling:MessageEntry", + "sling:message": "Last Publication Type", + "sling:key": "slingcms.lastpublicationtype" + }, "slingcms-recentcontent": { "jcr:primaryType": "sling:MessageEntry", "sling:message": "Recent Content",
