You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by dk...@apache.org on 2019/11/08 15:32:44 UTC
[sling-org-apache-sling-app-cms] branch master updated: Fixed
SLING-8836 and SLING-8835: Adding a grid view for the sites section and the
ability to create named transformations of images
This is an automated email from the ASF dual-hosted git repository.
dklco pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git
The following commit(s) were added to refs/heads/master by this push:
new 38833c0 Fixed SLING-8836 and SLING-8835: Adding a grid view for the sites section and the ability to create named transformations of images
38833c0 is described below
commit 38833c0315a62ecce65e1ad61a6c2be14cceb8fe
Author: Dan Klco <dk...@apache.org>
AuthorDate: Wed Nov 6 20:20:30 2019 -0600
Fixed SLING-8836 and SLING-8835: Adding a grid view for the sites section and the ability to create named transformations of images
---
builder/src/main/provisioning/cms.txt | 10 ++
.../core/internal/operations/MembersOperation.java | 8 +-
.../internal/operations/UpdateStatusOperation.java | 5 +-
transformer/pom.xml | 13 ++-
.../cms/transformer/FileThumbnailTransformer.java | 61 -----------
.../sling/cms/transformer/ThumbnailProvider.java | 20 ++--
...eThumbnailProvider.java => Transformation.java} | 26 ++---
.../cms/transformer/TransformationHandler.java | 28 ++---
...ailProvider.java => TransformationManager.java} | 33 +++---
.../{ThumbnailProvider.java => Transformer.java} | 33 +++---
.../cms/transformer/internal/CropHandler.java | 17 +--
.../internal/ImageThumbnailProvider.java | 17 ++-
.../transformer/internal/PdfThumbnailProvider.java | 17 ++-
.../cms/transformer/internal/RenditionCleaner.java | 56 ++++++++++
.../cms/transformer/internal/SizeHandler.java | 31 +++---
.../internal/SlideShowThumbnailProvider.java | 22 ++--
.../transformer/internal/TikaFallbackProvider.java | 20 ++--
.../cms/transformer/internal/TransformServlet.java | 99 ++++++++++++++++--
.../internal/TransformationServiceUser.java | 48 +++++++++
...ilTransformerImpl.java => TransformerImpl.java} | 93 +++++++----------
.../internal/TransformerWebConsole.java | 11 +-
.../internal/models/TransformationImpl.java | 54 ++++++++++
.../internal/models/TransformationManagerImpl.java | 49 +++++++++
.../apache/sling/cms/transformer/package-info.java | 17 +--
.../cms/transformer/internal/CropHandlerTest.java | 35 ++++---
.../internal/FileThumbnailTransformerImplTest.java | 77 --------------
.../internal/ImageThumbnailProviderTest.java | 13 +--
.../internal/PdfThumbnailProviderTest.java | 13 +--
.../cms/transformer/internal/SizeHandlerTest.java | 44 +++++---
.../internal/SlideShowThumbnailProviderTest.java | 20 ++--
.../internal/TikaFallbackProviderTest.java | 8 +-
.../transformer/internal/TransformServletTest.java | 88 ++++++++++++----
.../transformer/internal/TransformerImplTest.java | 94 +++++++++++++++++
transformer/src/test/resources/content.json | 24 +++--
ui/src/main/frontend/js/cms.nav.js | 68 ++++++++++++
ui/src/main/frontend/js/cms.table.js | 85 ---------------
ui/src/main/frontend/scss/cms.scss | 55 ++++++++--
.../resources/SLING-INF/nodetypes/nodetypes.cnd | 1 +
ui/src/main/resources/jcr_root/conf/global.json | 65 +++++++++++-
.../sling-cms/components/caconfig/edit/edit.jsp | 4 +-
.../components/caconfig/template/config/config.jsp | 3 +
.../components/caconfig/template/config/edit.json | 13 +++
.../components/caconfig/template/template.jsp | 12 ++-
.../components/caconfig/transformation/config.json | 4 +
.../config/config.jsp} | 22 +++-
.../caconfig/transformation/config/edit.json | 16 +++
.../transformation.jsp} | 12 ++-
.../caconfig/transformationhandlers/crop.json | 5 +
.../crop/crop.jsp} | 9 +-
.../caconfig/transformationhandlers/crop/edit.json | 53 ++++++++++
.../caconfig/transformationhandlers/size.json | 5 +
.../caconfig/transformationhandlers/size/edit.json | 23 +++++
.../size/size.jsp} | 11 +-
.../components/caconfig/transformations.json | 5 +
.../transformations.jsp} | 6 +-
.../cms/contentactions/contentactions.jsp | 65 +++++++++---
.../cms/contentbreadcrumb/contentbreadcrumb.jsp | 24 ++---
.../components/cms/contentgrid/contentgrid.jsp | 114 +++++++++++++++++++++
.../contentlayout/contentlayout.jsp} | 15 ++-
.../components/cms/contenttable/contenttable.jsp | 4 +-
.../components/cms/i18ncontainer/i18ncontainer.jsp | 89 ++++++++++++++++
.../components/cms/i18ntable/i18ntable.jsp | 87 ----------------
.../fields/thumbnail/thumbnail.jsp} | 10 +-
.../libs/sling-cms/components/pages/base/nav.jsp | 5 +-
.../libs/sling-cms/content/auth/user/profile.json | 39 +++++++
.../libs/sling-cms/content/i18n/dictionary.json | 92 ++++++++---------
.../libs/sling-cms/content/site/content.json | 3 +-
.../libs/sling-cms/content/site/editgroup.json | 6 ++
.../libs/sling-cms/content/site/sites.json | 3 +-
.../jcr_root/libs/sling-cms/content/start.json | 3 +
.../sling-cms/content/transformations/create.json | 55 ++++++++++
.../sling-cms/content/transformations/edit.json | 27 +++++
.../sling-cms/content/transformations/editor.json | 102 ++++++++++++++++++
73 files changed, 1689 insertions(+), 735 deletions(-)
diff --git a/builder/src/main/provisioning/cms.txt b/builder/src/main/provisioning/cms.txt
index 2beb5a0..6390bd9 100644
--- a/builder/src/main/provisioning/cms.txt
+++ b/builder/src/main/provisioning/cms.txt
@@ -100,6 +100,11 @@
allow jcr:write,jcr:nodeTypeManagement,jcr:versionManagement on /static
allow jcr:read on /
end
+ create service user sling-cms-transformer
+ set ACL for sling-cms-metadata
+ allow jcr:write,jcr:nodeTypeManagement,jcr:versionManagement on /content
+ allow jcr:read on /conf
+ end
create service user sling-rewriter
set ACL for sling-rewriter
allow jcr:read on /
@@ -125,6 +130,11 @@
"org.apache.sling.cms.core:sling-cms-metadata\=sling-cms-metadata"
]
+ org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-sling-cms-transformer
+ user.mapping=[
+ "org.apache.sling.cms.transformer:sling-cms-transformer\=sling-cms-transformer"
+ ]
+
org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-sling-cms-versionmgr
user.mapping=[
"org.apache.sling.cms.core:sling-cms-versionmgr\=sling-cms-versionmgr"
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/operations/MembersOperation.java b/core/src/main/java/org/apache/sling/cms/core/internal/operations/MembersOperation.java
index 4a9f855..761e132 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/operations/MembersOperation.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/operations/MembersOperation.java
@@ -54,7 +54,9 @@ public class MembersOperation implements PostOperation {
List<String> auths = new ArrayList<>();
Optional.ofNullable(request.getParameterValues(PN_MEMBERS)).ifPresent(p -> auths.addAll(Arrays.asList(p)));
- AuthorizableWrapper groupWrapper = request.getResource().adaptTo(AuthorizableWrapper.class);
+ AuthorizableWrapper groupWrapper = Optional
+ .ofNullable(request.getResource().adaptTo(AuthorizableWrapper.class))
+ .orElseThrow(() -> new RepositoryException("Failed to get group"));
if (!groupWrapper.getAuthorizable().isGroup()) {
throw new RepositoryException("Provided authorizable is not a group");
}
@@ -81,7 +83,9 @@ public class MembersOperation implements PostOperation {
if (resource == null) {
throw new RepositoryException("Failed to resolve authorizable at " + path);
}
- Authorizable authorizable = resource.adaptTo(AuthorizableWrapper.class).getAuthorizable();
+ Authorizable authorizable = Optional.ofNullable(resource.adaptTo(AuthorizableWrapper.class))
+ .map(AuthorizableWrapper::getAuthorizable)
+ .orElseThrow(() -> new RepositoryException("Failed to get authorizable from: " + resource));
group.addMember(authorizable);
changes.add(Modification.onModified(authorizable.getPath()));
log.debug("Adding member {} to {}", authorizable, group);
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/operations/UpdateStatusOperation.java b/core/src/main/java/org/apache/sling/cms/core/internal/operations/UpdateStatusOperation.java
index 8f91cf9..6068ae0 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/operations/UpdateStatusOperation.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/operations/UpdateStatusOperation.java
@@ -18,6 +18,7 @@ package org.apache.sling.cms.core.internal.operations;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import javax.jcr.RepositoryException;
@@ -51,7 +52,9 @@ public class UpdateStatusOperation implements PostOperation {
String reason = request.getParameter(PN_REASON);
- AuthorizableWrapper authWrapper = request.getResource().adaptTo(AuthorizableWrapper.class);
+ AuthorizableWrapper authWrapper = Optional
+ .ofNullable(request.getResource().adaptTo(AuthorizableWrapper.class))
+ .orElseThrow(() -> new RepositoryException("Failed to get authorizable: " + request.getResource()));
if (authWrapper.getAuthorizable().isGroup()) {
throw new RepositoryException("Authorizable is not a user");
diff --git a/transformer/pom.xml b/transformer/pom.xml
index 0a64ec3..1a95c7f 100644
--- a/transformer/pom.xml
+++ b/transformer/pom.xml
@@ -30,6 +30,10 @@
<instructions>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Export-Package>org.apache.sling.cms.transformer,net.coobird.thumbnailator.*</Export-Package>
+
+ <Sling-Model-Packages>
+ org.apache.sling.cms.transformer
+ </Sling-Model-Packages>
</instructions>
</configuration>
</plugin>
@@ -111,10 +115,18 @@
</dependency>
<dependency>
<groupId>org.osgi</groupId>
+ <artifactId>osgi.annotation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
<artifactId>org.osgi.service.component.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.metatype.annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
<artifactId>osgi.core</artifactId>
</dependency>
<dependency>
@@ -134,7 +146,6 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.caconfig.api</artifactId>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/FileThumbnailTransformer.java b/transformer/src/main/java/org/apache/sling/cms/transformer/FileThumbnailTransformer.java
deleted file mode 100644
index b54bc2a..0000000
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/FileThumbnailTransformer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.transformer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.cms.File;
-
-/**
- * Transforms a Sling File into thumbnails using the registered
- * TransformationHandlers to invoke Thumbnails transformations on the file.
- */
-public interface FileThumbnailTransformer {
-
- /**
- * Gets the transformation handler for the specified command
- *
- * @param command the command string to use to look up the transformation
- * handler.
- * @return the TransformationHandler from the command string or null if none
- * found
- */
- TransformationHandler getTransformationHandler(String command);
-
- /**
- * Transforms the file into a thumbnail using the specified commands.
- *
- * @param commands the commands to execute
- * @param format the format of the file to return
- * @param out the Outputstream to write the thumbnail to
- * @throws IOException an exception occurs transforming the file
- */
- void transformFile(File file, String[] commands, OutputFileFormat format, OutputStream out) throws IOException;
-
- /**
- * Transforms the file from the resource path into a thumbnail using the
- * specified commands from the suffix.
- *
- * @param request the request to parse the file and commands from
- * @param out the Outputstream to write the thumbnail to
- * @throws IOException an exception occurs transforming the file
- */
- void transformFile(SlingHttpServletRequest request, OutputStream out) throws IOException;
-
-}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java
index decfade..93a8b18 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java
@@ -19,29 +19,29 @@ package org.apache.sling.cms.transformer;
import java.io.IOException;
import java.io.InputStream;
-import org.apache.sling.cms.File;
+import org.apache.sling.api.resource.Resource;
/**
- * Service for retrieving a thumbnail for the specified File object.
+ * Service for retrieving a thumbnail for the specified Resource.
*/
public interface ThumbnailProvider {
/**
- * Returns true if the ThumbnailProvider applies for the specified file.
+ * Returns true if the ThumbnailProvider applies for the specified resource.
*
- * @param file the file to check
- * @return true if this ThumbnailProvider will create a thumbnail for this file,
- * false otherwise
+ * @param resource the resource to check
+ * @return true if this ThumbnailProvider will create a thumbnail for this
+ * resource, false otherwise
*/
- boolean applies(File file);
+ boolean applies(Resource resource);
/**
- * Get the thumbnail from the specified file.
+ * Get the thumbnail from the specified resource.
*
- * @param file the file from which to retrieve the thumbnail
+ * @param resource the resource from which to retrieve the thumbnail
* @return the thumbnail
* @throws IOException an exception occurs retrieving the thumbnail
*/
- InputStream getThumbnail(File file) throws IOException;
+ InputStream getThumbnail(Resource resource) throws IOException;
}
\ No newline at end of file
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/Transformation.java
similarity index 53%
copy from transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
copy to transformer/src/main/java/org/apache/sling/cms/transformer/Transformation.java
index 516d8fc..2058207 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/Transformation.java
@@ -14,30 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sling.cms.transformer.internal;
+package org.apache.sling.cms.transformer;
-import java.io.InputStream;
+import java.util.List;
-import org.apache.sling.cms.File;
-import org.apache.sling.cms.transformer.ThumbnailProvider;
-import org.osgi.service.component.annotations.Component;
-
-import com.google.common.net.MediaType;
+import org.apache.sling.api.resource.Resource;
/**
- * A thumbnail provider for image files.
+ * Model representing a transformation, a series of handlers
*/
-@Component(service = ThumbnailProvider.class)
-public class ImageThumbnailProvider implements ThumbnailProvider {
-
- @Override
- public boolean applies(File file) {
- return MediaType.parse(file.getContentType()).is(MediaType.ANY_IMAGE_TYPE);
- }
+public interface Transformation {
- @Override
- public InputStream getThumbnail(File file) {
- return file.getResource().adaptTo(InputStream.class);
- }
+ String getName();
+ List<Resource> getHandlers();
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/TransformationHandler.java b/transformer/src/main/java/org/apache/sling/cms/transformer/TransformationHandler.java
index 33bb7bd..f8ed7d9 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/TransformationHandler.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/TransformationHandler.java
@@ -19,34 +19,34 @@ package org.apache.sling.cms.transformer;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.sling.api.resource.Resource;
+
import net.coobird.thumbnailator.Thumbnails.Builder;
/*
- * Transformation handlers handle the transformation of thumbnails using the Thumbnails library.
- * Each transformation handler implements a named transformation command which will be parsed out
- * of the suffix of the transformation request by splitting the suffix by slashes and checking the
- * "applies" method of each TransformationHandler, in order.
+ * Transformation handlers handle the transformation of files using the Thumbnails library.
+ * Each transformation handler implements a transformation command using the specifed configuration.
*/
+@SuppressWarnings("squid:S1214") // I don't like this rule...
public interface TransformationHandler {
+ public static final String HANDLER_RESOURCE_TYPE = "handler.resourceType";
+
/**
- * Returns true if the transformation handler should execute for the specified
- * command.
+ * Get the resource type associated with this handler
*
- * @param command the command to check
- * @return true if the handler will handle this, false otherwise
+ * @return the handler resource type
*/
- boolean applies(String command);
+ String getResourceType();
/**
- * Handles the transformation of the thumbnail using the command values from the
+ * Handles the transformation of the file using the command values from the
* suffix segment.
*
* @param builder the Thumbnails builder to use / update
- * @param cmd the command to parse to retrieve the configuration values for
- * the transformation
- * @throws IOException an exception occurs transforming the thumbnail
+ * @param config the configuration values for the transformation
+ * @throws IOException an exception occurs transforming the file
*/
- void handle(Builder<? extends InputStream> builder, String cmd) throws IOException;
+ void handle(Builder<? extends InputStream> builder, Resource config) throws IOException;
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/TransformationManager.java
similarity index 53%
copy from transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
copy to transformer/src/main/java/org/apache/sling/cms/transformer/TransformationManager.java
index 516d8fc..b32457a 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/TransformationManager.java
@@ -14,30 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sling.cms.transformer.internal;
+package org.apache.sling.cms.transformer;
-import java.io.InputStream;
-
-import org.apache.sling.cms.File;
-import org.apache.sling.cms.transformer.ThumbnailProvider;
-import org.osgi.service.component.annotations.Component;
-
-import com.google.common.net.MediaType;
+import java.util.List;
/**
- * A thumbnail provider for image files.
+ * A Sling Model interface for retrieving the transformations available to a
+ * particular resource
*/
-@Component(service = ThumbnailProvider.class)
-public class ImageThumbnailProvider implements ThumbnailProvider {
-
- @Override
- public boolean applies(File file) {
- return MediaType.parse(file.getContentType()).is(MediaType.ANY_IMAGE_TYPE);
- }
-
- @Override
- public InputStream getThumbnail(File file) {
- return file.getResource().adaptTo(InputStream.class);
- }
+public interface TransformationManager {
+ /**
+ * Gets the transformations available to a particular resource based on the CA
+ * Configs
+ *
+ * @return a list of transformations
+ */
+ List<Transformation> getTransformations();
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/Transformer.java
similarity index 55%
copy from transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java
copy to transformer/src/main/java/org/apache/sling/cms/transformer/Transformer.java
index decfade..9c5e997 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/ThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/Transformer.java
@@ -17,31 +17,26 @@
package org.apache.sling.cms.transformer;
import java.io.IOException;
-import java.io.InputStream;
+import java.io.OutputStream;
-import org.apache.sling.cms.File;
+import org.apache.sling.api.resource.Resource;
/**
- * Service for retrieving a thumbnail for the specified File object.
+ * Transforms a resource using the registered TransformationHandlers to invoke
+ * transformations on the file.
*/
-public interface ThumbnailProvider {
+public interface Transformer {
/**
- * Returns true if the ThumbnailProvider applies for the specified file.
+ * Transforms the resource
*
- * @param file the file to check
- * @return true if this ThumbnailProvider will create a thumbnail for this file,
- * false otherwise
+ * @param resource the resource to transform
+ * @param commands the commands to execute
+ * @param format the format of the stream to return
+ * @param out the OutputStream to which to write the transformed file
+ * @throws IOException an exception occurs transforming the resource
*/
- boolean applies(File file);
+ void transform(Resource resource, Transformation transformation, OutputFileFormat format, OutputStream out)
+ throws IOException;
- /**
- * Get the thumbnail from the specified file.
- *
- * @param file the file from which to retrieve the thumbnail
- * @return the thumbnail
- * @throws IOException an exception occurs retrieving the thumbnail
- */
- InputStream getThumbnail(File file) throws IOException;
-
-}
\ No newline at end of file
+}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/CropHandler.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/CropHandler.java
index ce5d813..573a915 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/CropHandler.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/CropHandler.java
@@ -19,6 +19,7 @@ package org.apache.sling.cms.transformer.internal;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.TransformationHandler;
import org.osgi.service.component.annotations.Component;
@@ -28,21 +29,25 @@ import net.coobird.thumbnailator.geometry.Positions;
/**
* A transformation handler to crop images
*/
-@Component(service = TransformationHandler.class)
+@Component(service = TransformationHandler.class, property = { TransformationHandler.HANDLER_RESOURCE_TYPE
+ + "=sling-cms/components/caconfig/transformationhandlers/crop" }, immediate = true)
public class CropHandler implements TransformationHandler {
+ public static final String PN_POSITION = "position";
+
@Override
- public boolean applies(String command) {
- return command.startsWith("crop-");
+ public String getResourceType() {
+ return "sling-cms/components/caconfig/transformationhandlers/crop";
}
@Override
- public void handle(Builder<? extends InputStream> builder, String cmd) throws IOException {
+ public void handle(Builder<? extends InputStream> builder, Resource config) throws IOException {
+ String positionStr = config.getValueMap().get(PN_POSITION, "CENTER").toUpperCase();
try {
- Positions pos = Positions.valueOf(cmd.split("\\-")[1].toUpperCase());
+ Positions pos = Positions.valueOf(positionStr);
builder.crop(pos);
} catch (IllegalArgumentException e) {
- throw new IOException("Unable to load crop position from " + cmd.split("\\-")[1], e);
+ throw new IOException("Unable to load crop position from " + positionStr, e);
}
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
index 516d8fc..79fc9bf 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProvider.java
@@ -17,7 +17,11 @@
package org.apache.sling.cms.transformer.internal;
import java.io.InputStream;
+import java.util.Optional;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.CMSConstants;
import org.apache.sling.cms.File;
import org.apache.sling.cms.transformer.ThumbnailProvider;
import org.osgi.service.component.annotations.Component;
@@ -27,17 +31,20 @@ import com.google.common.net.MediaType;
/**
* A thumbnail provider for image files.
*/
-@Component(service = ThumbnailProvider.class)
+@Component(service = ThumbnailProvider.class, immediate = true)
public class ImageThumbnailProvider implements ThumbnailProvider {
@Override
- public boolean applies(File file) {
- return MediaType.parse(file.getContentType()).is(MediaType.ANY_IMAGE_TYPE);
+ public boolean applies(Resource resource) {
+ return (CMSConstants.NT_FILE.equals(resource.getResourceType())
+ || JcrConstants.NT_FILE.equals(resource.getResourceType()))
+ && Optional.ofNullable(resource.adaptTo(File.class))
+ .map(f -> MediaType.parse(f.getContentType()).is(MediaType.ANY_IMAGE_TYPE)).orElse(false);
}
@Override
- public InputStream getThumbnail(File file) {
- return file.getResource().adaptTo(InputStream.class);
+ public InputStream getThumbnail(Resource resource) {
+ return resource.adaptTo(InputStream.class);
}
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProvider.java
index 559e828..0230da9 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProvider.java
@@ -21,12 +21,16 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Optional;
import javax.imageio.ImageIO;
+import org.apache.jackrabbit.JcrConstants;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.CMSConstants;
import org.apache.sling.cms.File;
import org.apache.sling.cms.transformer.ThumbnailProvider;
import org.osgi.service.component.annotations.Component;
@@ -36,17 +40,20 @@ import com.google.common.net.MediaType;
/**
* A thumbnail provider for PDF documents.
*/
-@Component(service = ThumbnailProvider.class)
+@Component(service = ThumbnailProvider.class, immediate = true)
public class PdfThumbnailProvider implements ThumbnailProvider {
@Override
- public boolean applies(File file) {
- return MediaType.PDF.is(MediaType.parse(file.getContentType()));
+ public boolean applies(Resource resource) {
+ return (CMSConstants.NT_FILE.equals(resource.getResourceType())
+ || JcrConstants.NT_FILE.equals(resource.getResourceType()))
+ && Optional.ofNullable(resource.adaptTo(File.class))
+ .map(r -> MediaType.PDF.is(MediaType.parse(r.getContentType()))).orElse(false);
}
@Override
- public InputStream getThumbnail(File file) throws IOException {
- try (PDDocument document = PDDocument.load(file.getResource().adaptTo(InputStream.class))) {
+ public InputStream getThumbnail(Resource resource) throws IOException {
+ try (PDDocument document = PDDocument.load(resource.adaptTo(InputStream.class))) {
PDFRenderer pdfRenderer = new PDFRenderer(document);
BufferedImage bim = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);
ByteArrayOutputStream os = new ByteArrayOutputStream();
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/RenditionCleaner.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/RenditionCleaner.java
new file mode 100644
index 0000000..d1e75ee
--- /dev/null
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/RenditionCleaner.java
@@ -0,0 +1,56 @@
+/*
+ * 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.transformer.internal;
+
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = EventHandler.class, property = {
+ EventConstants.EVENT_TOPIC + "=org/apache/sling/api/resource/Resource/CHANGED",
+ EventConstants.EVENT_FILTER + "=(&(resourceType=sling:FileContent))" })
+public class RenditionCleaner implements EventHandler {
+
+ private static final Logger log = LoggerFactory.getLogger(RenditionCleaner.class);
+
+ @Reference
+ private TransformationServiceUser transformationServiceUser;
+
+ @Override
+ public void handleEvent(Event event) {
+ try (ResourceResolver resolver = transformationServiceUser.getTransformationServiceUser()) {
+ Resource renditions = resolver.getResource(event.getProperty("path") + "/renditions");
+ if (renditions != null) {
+ resolver.delete(renditions);
+ resolver.commit();
+ }
+ } catch (LoginException | PersistenceException e) {
+ log.warn("Failed to remove renditions", e);
+ }
+ }
+
+}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SizeHandler.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SizeHandler.java
index 1d8a2c3..79bd276 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SizeHandler.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SizeHandler.java
@@ -19,34 +19,31 @@ package org.apache.sling.cms.transformer.internal;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.TransformationHandler;
import org.osgi.service.component.annotations.Component;
import net.coobird.thumbnailator.Thumbnails.Builder;
-@Component(service = TransformationHandler.class)
+/**
+ * A transformer for resizing an image
+ */
+@Component(service = TransformationHandler.class, property = { TransformationHandler.HANDLER_RESOURCE_TYPE
+ + "=sling-cms/components/caconfig/transformationhandlers/size" }, immediate = true)
public class SizeHandler implements TransformationHandler {
+ public static final String PN_HEIGHT = "height";
+ public static final String PN_WIDTH = "width";
+
@Override
- public boolean applies(String command) {
- return command.startsWith("size-");
+ public String getResourceType() {
+ return "sling-cms/components/caconfig/transformationhandlers/size";
}
@Override
- public void handle(Builder<? extends InputStream> builder, String cmd) throws IOException {
- int width = -1;
- try {
- width = Integer.parseInt(cmd.split("\\-")[1], 10);
- } catch (NumberFormatException nfe) {
- throw new IOException("Failed to get width from " + cmd.split("\\-")[1]);
- }
-
- int height = -1;
- try {
- height = Integer.parseInt(cmd.split("\\-")[2], 10);
- } catch (NumberFormatException nfe) {
- throw new IOException("Failed to get height from " + cmd.split("\\-")[2]);
- }
+ public void handle(Builder<? extends InputStream> builder, Resource config) throws IOException {
+ int width = config.getValueMap().get(PN_WIDTH, -1);
+ int height = config.getValueMap().get(PN_HEIGHT, -1);
builder.size(width, height);
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProvider.java
index eef0eb1..e87371b 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProvider.java
@@ -25,14 +25,18 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
+import java.util.Optional;
import javax.imageio.ImageIO;
import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.jackrabbit.JcrConstants;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.CMSConstants;
import org.apache.sling.cms.File;
import org.apache.sling.cms.transformer.OutputFileFormat;
import org.apache.sling.cms.transformer.ThumbnailProvider;
@@ -45,28 +49,32 @@ import com.google.common.net.MediaType;
/**
* Provides Thumbnails for Microsoft PPT and PPTX files.
*/
-@Component(service = ThumbnailProvider.class)
+@Component(service = ThumbnailProvider.class, immediate = true)
public class SlideShowThumbnailProvider implements ThumbnailProvider {
@Reference
private DynamicClassLoaderManager dclm;
@Override
- public boolean applies(File file) {
- MediaType mt = MediaType.parse(file.getContentType());
- return mt.is(MediaType.MICROSOFT_POWERPOINT) || mt.is(MediaType.OOXML_PRESENTATION);
+ public boolean applies(Resource resource) {
+ return (CMSConstants.NT_FILE.equals(resource.getResourceType())
+ || JcrConstants.NT_FILE.equals(resource.getResourceType()))
+ && Optional.ofNullable(resource.adaptTo(File.class)).map(f -> {
+ MediaType mt = MediaType.parse(f.getContentType());
+ return mt.is(MediaType.MICROSOFT_POWERPOINT) || mt.is(MediaType.OOXML_PRESENTATION);
+ }).orElse(false);
}
@Override
- public InputStream getThumbnail(File file) throws IOException {
+ public InputStream getThumbnail(Resource resource) throws IOException {
if (dclm != null) {
Thread.currentThread().setContextClassLoader(dclm.getDynamicClassLoader());
}
SlideShow<?, ?> ppt = null;
- MediaType mt = MediaType.parse(file.getContentType());
+ MediaType mt = MediaType.parse(resource.adaptTo(File.class).getContentType());
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
- InputStream is = file.getResource().adaptTo(InputStream.class)) {
+ InputStream is = resource.adaptTo(InputStream.class)) {
if (mt.is(MediaType.MICROSOFT_POWERPOINT)) {
ppt = new HSLFSlideShow(is);
} else {
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TikaFallbackProvider.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TikaFallbackProvider.java
index df23413..a95b7b5 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TikaFallbackProvider.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TikaFallbackProvider.java
@@ -26,7 +26,9 @@ import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JEditorPane;
-import org.apache.sling.cms.File;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.CMSConstants;
import org.apache.sling.cms.transformer.OutputFileFormat;
import org.apache.sling.cms.transformer.ThumbnailProvider;
import org.apache.tika.exception.TikaException;
@@ -41,24 +43,26 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
-@Component(service = ThumbnailProvider.class, property = { Constants.SERVICE_RANKING + "=" + Integer.MIN_VALUE })
+@Component(service = ThumbnailProvider.class, property = {
+ Constants.SERVICE_RANKING + "=" + Integer.MIN_VALUE }, immediate = true)
public class TikaFallbackProvider implements ThumbnailProvider {
private static final Logger log = LoggerFactory.getLogger(TikaFallbackProvider.class);
@Override
- public boolean applies(File file) {
- return true;
+ public boolean applies(Resource resource) {
+ return (CMSConstants.NT_FILE.equals(resource.getResourceType())
+ || JcrConstants.NT_FILE.equals(resource.getResourceType()));
}
@Override
- public InputStream getThumbnail(File file) throws IOException {
+ public InputStream getThumbnail(Resource resource) throws IOException {
- log.info("Extracting content thumbnail from {}", file.getPath());
+ log.info("Extracting content thumbnail from {}", resource.getPath());
try {
log.debug("Extracting file contents");
- InputStream is = file.getResource().adaptTo(InputStream.class);
+ InputStream is = resource.adaptTo(InputStream.class);
Parser parser = new AutoDetectParser();
BodyContentHandler handler = new BodyContentHandler();
Metadata md = new Metadata();
@@ -78,7 +82,7 @@ public class TikaFallbackProvider implements ThumbnailProvider {
ImageIO.write(image, OutputFileFormat.PNG.toString(), baos);
return new ByteArrayInputStream(baos.toByteArray());
} catch (SAXException | TikaException e) {
- throw new IOException("Failed to generate thumbnail from " + file.getPath(), e);
+ throw new IOException("Failed to generate thumbnail from " + resource.getPath(), e);
}
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformServlet.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformServlet.java
index c01d59f..06a1715 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformServlet.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformServlet.java
@@ -16,16 +16,33 @@
*/
package org.apache.sling.cms.transformer.internal;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import javax.jcr.query.Query;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.poi.util.IOUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
-import org.apache.sling.cms.transformer.FileThumbnailTransformer;
+import org.apache.sling.cms.CMSConstants;
import org.apache.sling.cms.transformer.OutputFileFormat;
+import org.apache.sling.cms.transformer.Transformation;
+import org.apache.sling.cms.transformer.Transformer;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
@@ -45,21 +62,87 @@ public class TransformServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = -1513067546618762171L;
- @Reference
- private transient FileThumbnailTransformer transformer;
+ public static final String SERVICE_USER = "sling-cms-transformer";
+
+ private transient TransformationServiceUser transformationServiceUser;
+
+ private transient Transformer transformer;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
throws ServletException, IOException {
+ log.trace("doGet");
+
+ String name = StringUtils.substringBeforeLast(request.getRequestPathInfo().getSuffix(), ".");
+ String format = StringUtils.substringAfterLast(request.getRequestPathInfo().getSuffix(), ".");
+ log.debug("Transforming resource: {} with transformation: {} to {}", request.getResource(), name, format);
String original = response.getContentType();
- try {
- response.setContentType(OutputFileFormat.forRequest(request).getMimeType());
- transformer.transformFile(request, response.getOutputStream());
+ try (ResourceResolver serviceResolver = transformationServiceUser.getTransformationServiceUser()) {
+ Transformation transformation = findTransformation(serviceResolver, name);
+ if (transformation != null) {
+ response.setContentType(OutputFileFormat.forRequest(request).getMimeType());
+ String expectedPath = "jcr:content/renditions/" + name + "." + format;
+ Resource rendition = request.getResource().getChild(expectedPath);
+ if (rendition != null) {
+ log.debug("Using existing rendition {}", name);
+ IOUtils.copy(rendition.adaptTo(InputStream.class), response.getOutputStream());
+ } else {
+ log.debug("Creating new rendition {}", name);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ transformer.transform(request.getResource(), transformation,
+ OutputFileFormat.valueOf(format.toUpperCase()), baos);
+ IOUtils.copy(new ByteArrayInputStream(baos.toByteArray()), response.getOutputStream());
+ if (CMSConstants.NT_FILE.equals(request.getResource().getResourceType())) {
+ Resource file = ResourceUtil.getOrCreateResource(serviceResolver,
+ request.getResource().getPath() + "/" + expectedPath,
+ Collections.singletonMap(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_FILE),
+ JcrConstants.NT_UNSTRUCTURED, false);
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ properties.put(JcrConstants.JCR_DATA, new ByteArrayInputStream(baos.toByteArray()));
+ ResourceUtil.getOrCreateResource(serviceResolver,
+ file.getPath() + "/" + JcrConstants.JCR_CONTENT, properties,
+ JcrConstants.NT_UNSTRUCTURED, true);
+ }
+
+ }
+ } else {
+ log.error("Exception transforming image: {} with transformation: {}", request.getResource(), name);
+ response.setContentType(original);
+ response.sendError(400, "Could not transform image with transformation: " + name);
+ }
} catch (Exception e) {
- log.error("Exception transforming image", e);
+ log.error("Exception rendering transformed resource", e);
response.setContentType(original);
- response.sendError(400, "Could not transform image with provided commands");
+ response.sendError(500, "Could not transform image with transformation: " + name);
+
}
}
+ protected Transformation findTransformation(ResourceResolver serviceResolver, String name) throws LoginException {
+ name = name.substring(1).replace("'", "''");
+ log.debug("Finding transformations with {}", name);
+
+ Iterator<Resource> transformations = serviceResolver.findResources(
+ "SELECT * FROM [nt:unstructured] WHERE ISDESCENDANTNODE([/conf]) AND [sling:resourceType]='sling-cms/components/caconfig/transformation' AND [name]='"
+ + name + "'",
+ Query.JCR_SQL2);
+ if (transformations.hasNext()) {
+ Resource transformation = transformations.next();
+ return transformation.adaptTo(Transformation.class);
+ }
+
+ return null;
+ }
+
+ @Reference
+ public void setTransformationServiceUser(TransformationServiceUser transformationServiceUser) {
+ this.transformationServiceUser = transformationServiceUser;
+ }
+
+ @Reference
+ public void setTransformer(Transformer transformer) {
+ this.transformer = transformer;
+ }
+
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformationServiceUser.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformationServiceUser.java
new file mode 100644
index 0000000..210729c
--- /dev/null
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformationServiceUser.java
@@ -0,0 +1,48 @@
+/*
+ * 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.transformer.internal;
+
+import java.util.Collections;
+
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Service for retrieving the service user
+ */
+@Component(service = TransformationServiceUser.class)
+public class TransformationServiceUser {
+
+ public static final String SERVICE_USER = "sling-cms-transformer";
+
+ private ResourceResolverFactory resolverFactory;
+
+ public ResourceResolver getTransformationServiceUser() throws LoginException {
+ return resolverFactory
+ .getServiceResourceResolver(Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, SERVICE_USER));
+ }
+
+ @Reference
+ public void setResolverFactory(ResourceResolverFactory resolverFactory) {
+ this.resolverFactory = resolverFactory;
+ }
+}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/FileThumbnailTransformerImpl.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerImpl.java
similarity index 51%
rename from transformer/src/main/java/org/apache/sling/cms/transformer/internal/FileThumbnailTransformerImpl.java
rename to transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerImpl.java
index e50dfd7..1fb7477 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/FileThumbnailTransformerImpl.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerImpl.java
@@ -19,16 +19,15 @@ package org.apache.sling.cms.transformer.internal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Optional;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.cms.File;
-import org.apache.sling.cms.transformer.FileThumbnailTransformer;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.OutputFileFormat;
import org.apache.sling.cms.transformer.ThumbnailProvider;
+import org.apache.sling.cms.transformer.Transformation;
import org.apache.sling.cms.transformer.TransformationHandler;
+import org.apache.sling.cms.transformer.Transformer;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
@@ -41,10 +40,10 @@ import com.google.common.collect.Lists;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;
-@Component(service = FileThumbnailTransformer.class)
-public class FileThumbnailTransformerImpl implements FileThumbnailTransformer {
+@Component(service = Transformer.class)
+public class TransformerImpl implements Transformer {
- private static final Logger log = LoggerFactory.getLogger(FileThumbnailTransformerImpl.class);
+ private static final Logger log = LoggerFactory.getLogger(TransformerImpl.class);
@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, policyOption = ReferencePolicyOption.GREEDY)
private List<TransformationHandler> handlers;
@@ -52,17 +51,27 @@ public class FileThumbnailTransformerImpl implements FileThumbnailTransformer {
@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, policyOption = ReferencePolicyOption.GREEDY)
private List<ThumbnailProvider> thumbnailProviders;
- /**
- * @return the handlers
- */
+ public void addThumbnailProvider(ThumbnailProvider thumbnailProvider) {
+ if (thumbnailProviders == null) {
+ thumbnailProviders = new ArrayList<>();
+ }
+ this.thumbnailProviders.add(thumbnailProvider);
+ }
+
+ public void addTransformationHandler(TransformationHandler handler) {
+ if (handlers == null) {
+ handlers = new ArrayList<>();
+ }
+ handlers.add(handler);
+ }
+
public List<TransformationHandler> getHandlers() {
return handlers;
}
- private ThumbnailProvider getThumbnailProvider(File file) throws IOException {
- return Lists.reverse(thumbnailProviders).stream().filter(tp -> tp.applies(file))
- .findFirst()
- .orElseThrow(() -> new IOException("Unable to find thumbnail provider for: " + file.getPath()));
+ private ThumbnailProvider getThumbnailProvider(Resource resource) throws IOException {
+ return Lists.reverse(thumbnailProviders).stream().filter(tp -> tp.applies(resource)).findFirst()
+ .orElseThrow(() -> new IOException("Unable to find thumbnail provider for: " + resource.getPath()));
}
/**
@@ -72,54 +81,30 @@ public class FileThumbnailTransformerImpl implements FileThumbnailTransformer {
return thumbnailProviders;
}
- @Override
- public TransformationHandler getTransformationHandler(String command) {
- return handlers.stream().filter(h -> h.applies(command)).findFirst().orElse(null);
- }
-
- /**
- * @param handlers the handlers to set
- */
- public void setHandlers(List<TransformationHandler> handlers) {
- this.handlers = handlers;
- }
-
- /**
- * @param thumbnailProviders the thumbnailProviders to set
- */
- public void setThumbnailProviders(List<ThumbnailProvider> thumbnailProviders) {
- this.thumbnailProviders = thumbnailProviders;
+ public TransformationHandler getTransformationHandler(String resourceType) {
+ return handlers.stream().filter(h -> resourceType.equals(h.getResourceType())).findFirst().orElse(null);
}
@Override
- public void transformFile(File file, String[] commands, OutputFileFormat format, OutputStream out)
+ public void transform(Resource resource, Transformation transformation, OutputFileFormat format, OutputStream out)
throws IOException {
- ThumbnailProvider provider = getThumbnailProvider(file);
- log.debug("Using thumbnail provider {} for file {}", provider, file);
- Builder<? extends InputStream> builder = Thumbnails.of(provider.getThumbnail(file));
- for (String command : commands) {
- if (StringUtils.isNotBlank(command)) {
- log.debug("Handling command: {}", command);
- TransformationHandler handler = getTransformationHandler(command);
- if (handler != null) {
- log.debug("Invoking handler {} for command {}", handler.getClass().getCanonicalName(), command);
- handler.handle(builder, command);
- } else {
- log.info("No handler found for: {}", command);
- }
+ ThumbnailProvider provider = getThumbnailProvider(resource);
+ log.debug("Using thumbnail provider {} for resource {}", provider, resource);
+ Builder<? extends InputStream> builder = Thumbnails.of(provider.getThumbnail(resource));
+ for (Resource config : transformation.getHandlers()) {
+ log.debug("Handling command: {}", config);
+ TransformationHandler handler = getTransformationHandler(config.getResourceType());
+ if (handler != null) {
+ log.debug("Invoking handler {} for command {}", handler.getClass().getCanonicalName(),
+ config.getName());
+ handler.handle(builder, config);
+ } else {
+ log.info("No handler found for: {}", config.getName());
}
}
builder.outputFormat(format.toString());
builder.toOutputStream(out);
- }
- @Override
- public void transformFile(SlingHttpServletRequest request, OutputStream out) throws IOException {
- OutputFileFormat fileFormat = OutputFileFormat.forRequest(request);
- transformFile(request.getResource().adaptTo(File.class),
- Optional.ofNullable(request.getRequestPathInfo().getSuffix())
- .map(s -> StringUtils.substringBeforeLast(s, ".")).map(s -> s.split("/")).orElse(new String[0]),
- fileFormat, out);
}
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerWebConsole.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerWebConsole.java
index 185699b..4422894 100644
--- a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerWebConsole.java
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/TransformerWebConsole.java
@@ -28,9 +28,9 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
-import org.apache.sling.cms.transformer.FileThumbnailTransformer;
import org.apache.sling.cms.transformer.ThumbnailProvider;
import org.apache.sling.cms.transformer.TransformationHandler;
+import org.apache.sling.cms.transformer.Transformer;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@@ -55,7 +55,7 @@ public class TransformerWebConsole extends AbstractWebConsolePlugin {
@SuppressWarnings({ "squid:S2078", "squid:S2226" }) // ignore since this field is is injected by OSGi
@Reference
- private transient FileThumbnailTransformer fileThumbnailTransformer;
+ private transient Transformer transformer;
@Override
public String getTitle() {
@@ -75,16 +75,15 @@ public class TransformerWebConsole extends AbstractWebConsolePlugin {
pw.println("<pre>");
pw.println("Registered Thumbnail Providers");
pw.println("========================");
- List<ThumbnailProvider> providers = ((FileThumbnailTransformerImpl) fileThumbnailTransformer)
- .getThumbnailProviders();
+ List<ThumbnailProvider> providers = ((TransformerImpl) transformer).getThumbnailProviders();
Lists.reverse(providers).forEach(p -> pw.println(p.getClass().getName()));
pw.println("</pre><br/>");
pw.println("<pre>");
pw.println("Registered Transformation Handlers");
pw.println("========================");
- List<TransformationHandler> handlers = ((FileThumbnailTransformerImpl) fileThumbnailTransformer).getHandlers();
- handlers.forEach(h -> pw.println(h.getClass().getName()));
+ List<TransformationHandler> handlers = ((TransformerImpl) transformer).getHandlers();
+ handlers.forEach(h -> pw.println(h.getResourceType() + "=" + h.getClass().getCanonicalName()));
pw.println("</pre>");
pw.println("</div>");
}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/models/TransformationImpl.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/models/TransformationImpl.java
new file mode 100644
index 0000000..433ac67
--- /dev/null
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/models/TransformationImpl.java
@@ -0,0 +1,54 @@
+/*
+ * 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.transformer.internal.models;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.transformer.Transformation;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.ChildResource;
+import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
+
+@Model(adaptables = Resource.class, adapters = Transformation.class)
+public class TransformationImpl implements Transformation {
+
+ @ChildResource
+ private List<Resource> handlers;
+
+ @ValueMapValue
+ private String name;
+
+ @Override
+ public List<Resource> getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public void sethandlers(List<Resource> handlers) {
+ this.handlers = handlers;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/transformer/src/main/java/org/apache/sling/cms/transformer/internal/models/TransformationManagerImpl.java b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/models/TransformationManagerImpl.java
new file mode 100644
index 0000000..44a72bd
--- /dev/null
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/internal/models/TransformationManagerImpl.java
@@ -0,0 +1,49 @@
+/*
+ * 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.transformer.internal.models;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.caconfig.resource.ConfigurationResourceResolver;
+import org.apache.sling.cms.transformer.Transformation;
+import org.apache.sling.cms.transformer.TransformationManager;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.OSGiService;
+
+@Model(adaptables = Resource.class, adapters = TransformationManager.class)
+public class TransformationManagerImpl implements TransformationManager {
+
+ private Resource resource;
+
+ @OSGiService
+ private ConfigurationResourceResolver configResourceResolver;
+
+ public TransformationManagerImpl(Resource resource) {
+ this.resource = resource;
+ }
+
+ @Override
+ public List<Transformation> getTransformations() {
+ Collection<Resource> transformationResources = configResourceResolver.getResourceCollection(resource, "file",
+ "transformations");
+ return transformationResources.stream().map(r -> r.adaptTo(Transformation.class)).collect(Collectors.toList());
+ }
+
+}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp b/transformer/src/main/java/org/apache/sling/cms/transformer/package-info.java
similarity index 78%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
copy to transformer/src/main/java/org/apache/sling/cms/transformer/package-info.java
index 69e44fa..0594c64 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
+++ b/transformer/src/main/java/org/apache/sling/cms/transformer/package-info.java
@@ -1,4 +1,4 @@
-<%-- /*
+/*
* 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
@@ -15,8 +15,13 @@
* 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"%>
-<c:if test="${slingRequest.requestPathInfo.suffixResource != null}">
- <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
-</c:if>
\ No newline at end of file
+ */
+
+/**
+ * Package with all of the common models used to access content in the Sling
+ * reference CMS
+ *
+ * @since 0.10.0
+ */
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.sling.cms.transformer;
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/CropHandlerTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/CropHandlerTest.java
index edefd0e..7f043ce 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/CropHandlerTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/CropHandlerTest.java
@@ -17,25 +17,28 @@
package org.apache.sling.cms.transformer.internal;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
-import org.apache.sling.cms.transformer.internal.CropHandler;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.testing.resourceresolver.MockResource;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;
public class CropHandlerTest {
-
+
private Builder<? extends InputStream> builder;
private CropHandler cropper;
- @Before
+ @Before
public void init() {
builder = Thumbnails.of(getClass().getClassLoader().getResourceAsStream("apache.png"));
builder.size(200, 200);
@@ -43,29 +46,31 @@ public class CropHandlerTest {
}
@Test
- public void testApplies() {
- assertTrue(cropper.applies("crop-CENTER"));
- }
-
- @Test
public void testCrop() throws IOException {
- cropper.handle(builder, "crop-CENTER");
+ Resource config = new MockResource("/conf", Collections.singletonMap(CropHandler.PN_POSITION, "CENTER"),
+ Mockito.mock(ResourceResolver.class));
+ cropper.handle(builder, config);
assertNotNull(builder.asBufferedImage());
}
-
@Test
public void testCropLower() throws IOException {
- cropper.handle(builder, "crop-center");
+
+ Resource config = new MockResource("/conf", Collections.singletonMap(CropHandler.PN_POSITION, "center"),
+ Mockito.mock(ResourceResolver.class));
+ cropper.handle(builder, config);
assertNotNull(builder.asBufferedImage());
}
-
+
@Test
public void testInvalidParam() throws IOException {
try {
- cropper.handle(builder, "crop-CENTERZ");
+
+ Resource config = new MockResource("/conf", Collections.singletonMap(CropHandler.PN_POSITION, "centerz"),
+ Mockito.mock(ResourceResolver.class));
+ cropper.handle(builder, config);
fail();
- }catch(IOException e) {
+ } catch (IOException e) {
}
}
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/FileThumbnailTransformerImplTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/FileThumbnailTransformerImplTest.java
deleted file mode 100644
index 0c391d3..0000000
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/FileThumbnailTransformerImplTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.transformer.internal;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.poi.util.IOUtils;
-import org.apache.sling.cms.transformer.FileThumbnailTransformer;
-import org.apache.sling.cms.transformer.ThumbnailProvider;
-import org.apache.sling.cms.transformer.TransformationHandler;
-import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
-import org.apache.sling.cms.transformer.internal.CropHandler;
-import org.apache.sling.cms.transformer.internal.FileThumbnailTransformerImpl;
-import org.apache.sling.cms.transformer.internal.ImageThumbnailProvider;
-import org.apache.sling.cms.transformer.internal.PdfThumbnailProvider;
-import org.apache.sling.cms.transformer.internal.SizeHandler;
-import org.apache.sling.testing.mock.sling.junit.SlingContext;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import com.google.common.collect.Lists;
-
-public class FileThumbnailTransformerImplTest {
- @Rule
- public final SlingContext context = new SlingContext();
- private FileThumbnailTransformer transformer;
-
- @Before
- public void init() {
- SlingCMSContextHelper.initContext(context);
- transformer = new FileThumbnailTransformerImpl();
- ((FileThumbnailTransformerImpl) transformer)
- .setHandlers(Lists.asList(new CropHandler(), new TransformationHandler[] { new SizeHandler() }));
- ((FileThumbnailTransformerImpl) transformer).setThumbnailProviders(
- Lists.asList(new ImageThumbnailProvider(), new ThumbnailProvider[] { new PdfThumbnailProvider() }));
- }
-
- @Test
- public void testGetHandler() {
- assertNotNull(transformer.getTransformationHandler("size-200-200"));
- assertNull(transformer.getTransformationHandler("sizey-200-200"));
- }
-
-
- @Test
- public void testImageThumbnail() throws IOException {
- context.requestPathInfo().setSuffix("/not-a-command/size-200-200/crop-center.png");
- context.currentResource("/content/apache/sling-apache-org/index/apache.png");
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- transformer.transformFile(context.request(), baos);
- assertNotNull(baos);
-
- IOUtils.copy(new ByteArrayInputStream(baos.toByteArray()), new File("src/test/resources/thumbnail.png"));
- }
-
-}
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProviderTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProviderTest.java
index ca89c09..05e85c6 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProviderTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/ImageThumbnailProviderTest.java
@@ -24,9 +24,8 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
-import org.apache.sling.cms.File;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
-import org.apache.sling.cms.transformer.internal.ImageThumbnailProvider;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -41,18 +40,16 @@ public class ImageThumbnailProviderTest {
@Rule
public final SlingContext context = new SlingContext();
- private File imageFile;
- private File pdfFile;
+ private Resource imageFile;
+ private Resource pdfFile;
@Before
public void init() {
SlingCMSContextHelper.initContext(context);
- imageFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/apache.png")
- .adaptTo(File.class);
+ imageFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/apache.png");
- pdfFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/sling.pdf")
- .adaptTo(File.class);
+ pdfFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/sling.pdf");
}
@Test
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProviderTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProviderTest.java
index 09eb986..2bf6f4a 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProviderTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/PdfThumbnailProviderTest.java
@@ -22,9 +22,8 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
-import org.apache.sling.cms.File;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
-import org.apache.sling.cms.transformer.internal.PdfThumbnailProvider;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -39,16 +38,14 @@ public class PdfThumbnailProviderTest {
@Rule
public final SlingContext context = new SlingContext();
- private File imageFile;
- private File pdfFile;
+ private Resource imageFile;
+ private Resource pdfFile;
@Before
public void init() {
SlingCMSContextHelper.initContext(context);
- imageFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/apache.png")
- .adaptTo(File.class);
- pdfFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/sling.pdf")
- .adaptTo(File.class);
+ imageFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/apache.png");
+ pdfFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/sling.pdf");
}
@Test
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SizeHandlerTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SizeHandlerTest.java
index e046f1f..55e2d51 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SizeHandlerTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SizeHandlerTest.java
@@ -17,52 +17,64 @@
package org.apache.sling.cms.transformer.internal;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
-import org.apache.sling.cms.transformer.internal.SizeHandler;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.testing.resourceresolver.MockResource;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.Thumbnails.Builder;
public class SizeHandlerTest {
-
+
private Builder<? extends InputStream> builder;
private SizeHandler sizer;
- @Before
+ @Before
public void init() {
builder = Thumbnails.of(getClass().getClassLoader().getResourceAsStream("apache.png"));
sizer = new SizeHandler();
}
@Test
- public void testApplies() {
- assertTrue(sizer.applies("size-200-200"));
- }
-
- @Test
public void testResize() throws IOException {
- sizer.handle(builder, "size-200-200");
+
+ Map<String, Object> config = new HashMap<>();
+ config.put(SizeHandler.PN_WIDTH, 200);
+ config.put(SizeHandler.PN_HEIGHT, 200);
+ sizer.handle(builder, new MockResource("/conf", config, Mockito.mock(ResourceResolver.class)));
assertNotNull(builder.asBufferedImage());
}
-
+
@Test
- public void testInvalidParam() throws IOException {
+ public void testInvalidWidth() throws IOException {
try {
- sizer.handle(builder, "size-k-200");
+ Map<String, Object> config = new HashMap<>();
+ config.put(SizeHandler.PN_WIDTH, "K");
+ config.put(SizeHandler.PN_HEIGHT, 200);
+ sizer.handle(builder, new MockResource("/conf", config, Mockito.mock(ResourceResolver.class)));
fail();
- }catch(IOException e) {
+ } catch (IOException | IllegalArgumentException e) {
}
+ }
+
+ @Test
+ public void testInvalidHeight() throws IOException {
try {
- sizer.handle(builder, "size-222-h");
+ Map<String, Object> config = new HashMap<>();
+ config.put(SizeHandler.PN_WIDTH, 200);
+ config.put(SizeHandler.PN_HEIGHT, "h");
+ sizer.handle(builder, new MockResource("/conf", config, Mockito.mock(ResourceResolver.class)));
fail();
- }catch(IOException e) {
+ } catch (IOException | IllegalArgumentException e) {
}
}
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProviderTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProviderTest.java
index 9111680..e4a059b 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProviderTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/SlideShowThumbnailProviderTest.java
@@ -22,10 +22,9 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
-import org.apache.sling.cms.File;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.ThumbnailProvider;
import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
-import org.apache.sling.cms.transformer.internal.SlideShowThumbnailProvider;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -40,24 +39,19 @@ public class SlideShowThumbnailProviderTest {
@Rule
public final SlingContext context = new SlingContext();
- private File docxFile;
- private File pptFile;
- private File pptxFile;
+ private Resource docxFile;
+ private Resource pptFile;
+ private Resource pptxFile;
private ThumbnailProvider provider;
@Before
public void init() {
SlingCMSContextHelper.initContext(context);
- docxFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.docx")
- .adaptTo(File.class);
- pptxFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.pptx")
- .adaptTo(File.class);
- pptFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.ppt")
- .adaptTo(File.class);
-
+ docxFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.docx");
+ pptxFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.pptx");
+ pptFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.ppt");
provider = new SlideShowThumbnailProvider();
-
}
@Test
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TikaFallbackProviderTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TikaFallbackProviderTest.java
index 45cc645..167a567 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TikaFallbackProviderTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TikaFallbackProviderTest.java
@@ -20,9 +20,8 @@ import static org.junit.Assert.assertNotNull;
import java.io.IOException;
-import org.apache.sling.cms.File;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
-import org.apache.sling.cms.transformer.internal.TikaFallbackProvider;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -37,13 +36,12 @@ public class TikaFallbackProviderTest {
@Rule
public final SlingContext context = new SlingContext();
- private File docxFile;
+ private Resource docxFile;
@Before
public void init() {
SlingCMSContextHelper.initContext(context);
- docxFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.docx")
- .adaptTo(File.class);
+ docxFile = context.resourceResolver().getResource("/content/apache/sling-apache-org/index/Sling.docx");
}
@Test
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformServletTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformServletTest.java
index 35c6324..5191f8b 100644
--- a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformServletTest.java
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformServletTest.java
@@ -20,48 +20,92 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import javax.servlet.ServletException;
import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.reflect.FieldUtils;
-import org.apache.sling.cms.transformer.ThumbnailProvider;
-import org.apache.sling.cms.transformer.TransformationHandler;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
-import org.apache.sling.cms.transformer.internal.CropHandler;
-import org.apache.sling.cms.transformer.internal.FileThumbnailTransformerImpl;
-import org.apache.sling.cms.transformer.internal.ImageThumbnailProvider;
-import org.apache.sling.cms.transformer.internal.PdfThumbnailProvider;
-import org.apache.sling.cms.transformer.internal.SizeHandler;
-import org.apache.sling.cms.transformer.internal.TransformServlet;
+import org.apache.sling.cms.transformer.internal.models.TransformationImpl;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.apache.sling.testing.resourceresolver.MockResource;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.Lists;
-
public class TransformServletTest {
private static final Logger log = LoggerFactory.getLogger(TransformServletTest.class);
-
- private TransformServlet ts = new TransformServlet();;
+
+ private TransformServlet ts = new TransformServlet();
@Rule
public final SlingContext context = new SlingContext();
@Before
- public void init() throws IllegalAccessException {
+ public void init() throws IllegalAccessException, LoginException {
SlingCMSContextHelper.initContext(context);
- FileThumbnailTransformerImpl transformer = new FileThumbnailTransformerImpl();
- transformer.setHandlers(Lists.asList(new CropHandler(), new TransformationHandler[] { new SizeHandler() }));
- transformer.setThumbnailProviders(
- Lists.asList(new ImageThumbnailProvider(), new ThumbnailProvider[] { new PdfThumbnailProvider() }));
-
- FieldUtils.writeDeclaredField(ts,"transformer", transformer, true);
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+
+ TransformationImpl transformation = new TransformationImpl();
+ List<Resource> handlers = new ArrayList<>();
+ Map<String, Object> size = new HashMap<>();
+ size.put(SizeHandler.PN_WIDTH, 200);
+ size.put(SizeHandler.PN_HEIGHT, 200);
+ size.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, "sling-cms/components/caconfig/transformationhandlers/size");
+ handlers.add(new MockResource("/conf", size, Mockito.mock(ResourceResolver.class)));
+
+ Map<String, Object> crop = new HashMap<>();
+ crop.put(CropHandler.PN_POSITION, "center");
+ crop.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, "sling-cms/components/caconfig/transformationhandlers/crop");
+ handlers.add(new MockResource("/conf", crop, Mockito.mock(ResourceResolver.class)));
+
+ transformation.sethandlers(handlers);
+
+ Mockito.when(resolver.findResources(Mockito.anyString(), Mockito.anyString())).thenAnswer((ans) -> {
+ List<Resource> resources = new ArrayList<>();
+ if (ans.getArgument(0, String.class).contains("test'")) {
+ Resource resource = Mockito.mock(Resource.class);
+ Mockito.when(resource.adaptTo(Mockito.any())).thenReturn(transformation);
+ resources.add(resource);
+ }
+ return resources.iterator();
+ });
+
+ Mockito.when(factory.getServiceResourceResolver(Mockito.any())).thenReturn(resolver);
+ TransformationServiceUser tsu = new TransformationServiceUser();
+ tsu.setResolverFactory(factory);
+ ts.setTransformationServiceUser(tsu);
+
+ TransformerImpl transformer = new TransformerImpl();
+ ((TransformerImpl) transformer).addTransformationHandler(new CropHandler() {
+ public String getResourceType() {
+ return "sling-cms/components/caconfig/transformationhandlers/crop";
+ }
+ });
+ ((TransformerImpl) transformer).addTransformationHandler(new SizeHandler() {
+ public String getResourceType() {
+ return "sling-cms/components/caconfig/transformationhandlers/size";
+ }
+ });
+
+ ((TransformerImpl) transformer).addThumbnailProvider(new ImageThumbnailProvider());
+ ((TransformerImpl) transformer).addThumbnailProvider(new PdfThumbnailProvider());
+
+ ts.setTransformer(transformer);
+
}
@Test
@@ -69,7 +113,7 @@ public class TransformServletTest {
log.info("testContentTypes");
context.currentResource("/content/apache/sling-apache-org/index/apache.png");
- context.requestPathInfo().setSuffix("/size-200-200/crop-center.png");
+ context.requestPathInfo().setSuffix("/test.png");
context.requestPathInfo().setExtension("transform");
ts.doGet(context.request(), context.response());
@@ -83,7 +127,7 @@ public class TransformServletTest {
log.info("testContentTypes");
context.currentResource("/content/apache/sling-apache-org/index/apache.png");
- context.requestPathInfo().setSuffix("/size-200-200/crop-left.png");
+ context.requestPathInfo().setSuffix("/test2.png");
context.requestPathInfo().setExtension("transform");
ts.doGet(context.request(), context.response());
diff --git a/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformerImplTest.java b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformerImplTest.java
new file mode 100644
index 0000000..aa6b4d3
--- /dev/null
+++ b/transformer/src/test/java/org/apache/sling/cms/transformer/internal/TransformerImplTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.transformer.internal;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.poi.util.IOUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.cms.transformer.OutputFileFormat;
+import org.apache.sling.cms.transformer.Transformer;
+import org.apache.sling.cms.transformer.helpers.SlingCMSContextHelper;
+import org.apache.sling.cms.transformer.internal.models.TransformationImpl;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TransformerImplTest {
+ @Rule
+ public final SlingContext context = new SlingContext();
+ private Transformer transformer;
+
+ @Before
+ public void init() {
+ SlingCMSContextHelper.initContext(context);
+ transformer = new TransformerImpl();
+
+ ((TransformerImpl) transformer).addTransformationHandler(new CropHandler() {
+ public String getResourceType() {
+ return "sling-cms/components/caconfig/transformationhandlers/crop";
+ }
+ });
+ ((TransformerImpl) transformer).addTransformationHandler(new SizeHandler() {
+ public String getResourceType() {
+ return "sling-cms/components/caconfig/transformationhandlers/size";
+ }
+ });
+
+ ((TransformerImpl) transformer).addThumbnailProvider(new ImageThumbnailProvider());
+ ((TransformerImpl) transformer).addThumbnailProvider(new PdfThumbnailProvider());
+ }
+
+ @Test
+ public void testImageThumbnail() throws IOException {
+ context.currentResource("/content/apache/sling-apache-org/index/apache.png");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TransformationImpl transformation = new TransformationImpl();
+ List<Resource> handlers = new ArrayList<>();
+
+ Map<String, Object> size = new HashMap<>();
+ size.put(SizeHandler.PN_WIDTH, 200);
+ size.put(SizeHandler.PN_HEIGHT, 200);
+ size.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, "sling-cms/components/caconfig/transformationhandlers/size");
+ handlers.add(new MockResource("/conf", size, Mockito.mock(ResourceResolver.class)));
+
+ Map<String, Object> crop = new HashMap<>();
+ crop.put(CropHandler.PN_POSITION, "center");
+ crop.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, "sling-cms/components/caconfig/transformationhandlers/crop");
+ handlers.add(new MockResource("/conf", crop, Mockito.mock(ResourceResolver.class)));
+
+ transformation.sethandlers(handlers);
+ transformer.transform(context.currentResource(), transformation, OutputFileFormat.PNG, baos);
+ assertNotNull(baos);
+
+ IOUtils.copy(new ByteArrayInputStream(baos.toByteArray()), new File("src/test/resources/thumbnail.png"));
+ }
+
+}
diff --git a/transformer/src/test/resources/content.json b/transformer/src/test/resources/content.json
index 82e8ffc..b7c79ed 100644
--- a/transformer/src/test/resources/content.json
+++ b/transformer/src/test/resources/content.json
@@ -93,16 +93,22 @@
"sling:resourceType": "sling-cms/components/general/richtext"
}
}
+ },
+ "apache.png": {
+ "jcr:primaryType": "sling:File"
+ },
+ "sling.pdf": {
+ "jcr:primaryType": "sling:File"
+ },
+ "Sling.docx": {
+ "jcr:primaryType": "sling:File"
+ },
+ "Sling.pptx": {
+ "jcr:primaryType": "sling:File"
+ },
+ "Sling.ppt": {
+ "jcr:primaryType": "sling:File"
}
- },
- "apache.png": {
- "jcr:primaryType": "sling:File"
- },
- "sling.pdf": {
- "jcr:primaryType": "sling:File"
- },
- "sling.docx": {
- "jcr:primaryType": "sling:File"
}
}
}
diff --git a/ui/src/main/frontend/js/cms.nav.js b/ui/src/main/frontend/js/cms.nav.js
index bb7bf01..98ed2b3 100644
--- a/ui/src/main/frontend/js/cms.nav.js
+++ b/ui/src/main/frontend/js/cms.nav.js
@@ -19,6 +19,11 @@
/* eslint-env browser, es6 */
(function (rava) {
'use strict';
+
+ var urlParams = new URLSearchParams(window.location.search),
+ resourceParam = urlParams.get('resource'),
+ searchParam = urlParams.get('search');
+
rava.bind(".navbar-burger", {
events: {
click: function () {
@@ -28,4 +33,67 @@
}
}
});
+
+ rava.bind('.layout-switch select', {
+ events: {
+ change: function () {
+ window.location = this.value;
+ }
+ }
+ });
+
+
+ rava.bind('.contentnav', {
+ callbacks : {
+ created: function () {
+ let cnav = this;
+ var search = cnav.querySelector('input[name=search]'),
+ filter = function (event) {
+ event.stopPropagation();
+ event.preventDefault();
+ var value = search.value.toLowerCase();
+ cnav.querySelectorAll('.contentnav__item').forEach(function (item) {
+ if (item.innerText.toLowerCase().indexOf(value) === -1 && !item.querySelector('*[data-value="' + resourceParam + '"]')) {
+ item.classList.add('is-hidden');
+ } else {
+ item.classList.remove('is-hidden');
+ }
+ });
+ };
+ search.addEventListener('keyup', filter);
+ search.addEventListener('change', filter);
+
+ if (resourceParam) {
+ cnav.querySelectorAll('.contentnav__item').forEach(function (item) {
+ if (item.querySelector('*[data-value="' + resourceParam + '"]')) {
+ item.classList.remove('is-hidden');
+ item.click();
+ } else {
+ item.classList.add('is-hidden');
+ }
+ });
+ cnav.querySelector('input[name=search]').value = resourceParam;
+ } else if (searchParam) {
+ cnav.querySelector('input[name=search]').value = searchParam;
+ filter(new Event('fake'));
+ }
+ }
+ }
+ });
+ rava.bind(".contentnav .contentnav__item", {
+ events: {
+ click: function () {
+ this.closest('.contentnav').querySelectorAll('.contentnav__item.is-selected').forEach(function (tr) {
+ tr.classList.remove('is-selected');
+ });
+ this.classList.add('is-selected');
+ document.querySelector('.actions-target').innerHTML = this.querySelector('.cell-actions').innerHTML;
+ },
+ dblclick: function () {
+ if(this.querySelector('.item-link')){
+ window.location = this.querySelector('.item-link').href;
+ }
+ }
+ }
+ });
}(window.rava = window.rava || {}));
\ No newline at end of file
diff --git a/ui/src/main/frontend/js/cms.table.js b/ui/src/main/frontend/js/cms.table.js
deleted file mode 100644
index 45bc48f..0000000
--- a/ui/src/main/frontend/js/cms.table.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.
- */
-
-/* eslint-env browser, es6 */
-(function (rava) {
- 'use strict';
-
- var urlParams = new URLSearchParams(window.location.search),
- resourceParam = urlParams.get('resource'),
- searchParam = urlParams.get('search');
-
- rava.bind(".table tbody tr", {
- events: {
- click: function () {
- this.closest('.table').querySelectorAll('tr.is-selected').forEach(function (tr) {
- tr.classList.remove('is-selected');
- });
- this.classList.add('is-selected');
- document.querySelector('.actions-target').innerHTML = this.querySelector('.cell-actions').innerHTML;
- },
- dblclick: function () {
- if(this.querySelector('.item-link')){
- window.location = this.querySelector('.item-link').href;
- }
- }
- }
- });
-
- rava.bind(".table", {
- callbacks : {
- created: function () {
- var table = this;
- if (table.closest('.table__wrapper')) {
- var search = table.closest('.table__wrapper').querySelector('input[name=search]'),
- filter = function (event) {
- event.stopPropagation();
- event.preventDefault();
- var value = this.value.toLowerCase();
- table.querySelectorAll('tbody tr').forEach(function (row) {
- if (row.innerText.toLowerCase().indexOf(value) === -1 && !row.querySelector('td[data-value="' + resourceParam + '"]')) {
- row.classList.add('is-hidden');
- } else {
- row.classList.remove('is-hidden');
- }
- });
- };
- search.addEventListener('keyup', filter);
- search.addEventListener('change', filter);
-
- if (resourceParam) {
- table.querySelectorAll('tbody tr').forEach(function (row) {
- if (row.querySelector('td[data-value="' + resourceParam + '"]')) {
- row.classList.remove('is-hidden');
- row.click();
- } else {
- row.classList.add('is-hidden');
- }
- });
- table.closest('.table__wrapper').querySelector('input[name=search]').value = resourceParam;
- } else if (searchParam) {
- table.closest('.table__wrapper').querySelector('input[name=search]').value = searchParam;
- filter(new Event('fake'));
- }
- }
- }
- }
- });
-
-}(window.rava = window.rava || {}));
\ 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 94145a5..cae78d7 100644
--- a/ui/src/main/frontend/scss/cms.scss
+++ b/ui/src/main/frontend/scss/cms.scss
@@ -63,8 +63,25 @@ h5 {
font-size: 120%;
}
+.card.is-selected {
+ border: 1px solid $violet;
+}
+
+.card-footer-item {
+ word-break: break-all;
+}
+
+.container {
+ height: 100vh;
+ overflow: hidden;
+ @media screen and (max-width: $tablet - 1px) {
+ height: 100%;
+ overflow: visible;
+ }
+}
+
.has-padding-1 {
- padding: .5em;
+ padding: .5em;
}
.editor-page {
@@ -91,6 +108,10 @@ h5 {
cursor: not-allowed;
}
+.is-linked {
+ cursor: pointer;
+}
+
.is-draggable {
position: relative;
}
@@ -146,21 +167,43 @@ h5 {
}
.rte-form {
- margin: .5em 0;
+ margin: .5em 0;
}
.rte-form .buttons {
- margin: .5em 0;
+ margin: .5em 0;
}
.rte-toolbar .jam:before {
- font-size: x-large;
+ font-size: x-large;
}
.rte-toolbar .level {
margin-bottom: .5em;
}
+.scroll-container {
+ overflow-y: auto;
+ height: calc(100vh - 190px);
+ overflow-x: hidden;
+ padding: 2px;
+ @media screen and (max-width: $tablet - 1px) {
+ height: 100%;
+ overflow: visible;
+ padding: 0px;
+ }
+}
+
+.scroll-container .scroll-container {
+ height: auto;
+ overflow: visible;
+ padding: 0px;
+}
+
+.scroll-container > .is-ancestor {
+ flex-wrap: wrap;
+}
+
#search-results .box {
overflow: hidden;
}
@@ -205,7 +248,7 @@ table thead .sorting_desc:after {
}
.wysihtml-sandbox {
- width: 100% !important;
- max-height: 600px !important;
+ width: 100% !important;
+ max-height: 600px !important;
min-height: 300px !important;
}
diff --git a/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd b/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd
index 0f030c5..04a8db3 100644
--- a/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd
+++ b/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd
@@ -48,6 +48,7 @@
- * (undefined) copy
- * (undefined) copy multiple
+ metadata (nt:unstructured) = nt:unstructured copy primary
+ + renditions (nt:unstructured) = nt:unstructured copy primary
[sling:Page] > nt:hierarchyNode
orderable
diff --git a/ui/src/main/resources/jcr_root/conf/global.json b/ui/src/main/resources/jcr_root/conf/global.json
index 6639ba5..97413db 100644
--- a/ui/src/main/resources/jcr_root/conf/global.json
+++ b/ui/src/main/resources/jcr_root/conf/global.json
@@ -12,6 +12,7 @@
},
"editors": {
"jcr:primaryType": "sling:Config",
+ "jcr:title": "File Editors",
"sling:resourceType": "sling-cms/components/caconfig/fileeditor",
"default": {
"jcr:primaryType": "nt:unstructured",
@@ -76,6 +77,68 @@
}
}
}
+ },
+ "transformations": {
+ "jcr:primaryType": "sling:Config",
+ "jcr:title": "Transformations",
+ "sling:resourceType": "sling-cms/components/caconfig/transformations",
+ "sling-cms-thumbnail": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": "sling-cms-thumbnail",
+ "sling:resourceType": "sling-cms/components/caconfig/transformation",
+ "handlers": {
+ "jcr:primaryType": "nt:unstructured",
+ "size": {
+ "jcr:primaryType": "nt:unstructured",
+ "height": "600",
+ "width": "480",
+ "sling:resourceType": "sling-cms/components/caconfig/transformationhandlers/size"
+ },
+ "crop": {
+ "jcr:primaryType": "nt:unstructured",
+ "position": "CENTER",
+ "sling:resourceType": "sling-cms/components/caconfig/transformationhandlers/crop"
+ }
+ }
+ },
+ "sling-cms-thumbnail128": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": "sling-cms-thumbnail128",
+ "sling:resourceType": "sling-cms/components/caconfig/transformation",
+ "handlers": {
+ "jcr:primaryType": "nt:unstructured",
+ "size": {
+ "jcr:primaryType": "nt:unstructured",
+ "height": "128",
+ "width": "128",
+ "sling:resourceType": "sling-cms/components/caconfig/transformationhandlers/size"
+ },
+ "crop": {
+ "jcr:primaryType": "nt:unstructured",
+ "position": "CENTER",
+ "sling:resourceType": "sling-cms/components/caconfig/transformationhandlers/crop"
+ }
+ }
+ },
+ "sling-cms-thumbnail32": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": "sling-cms-thumbnail32",
+ "sling:resourceType": "sling-cms/components/caconfig/transformation",
+ "handlers": {
+ "jcr:primaryType": "nt:unstructured",
+ "size": {
+ "jcr:primaryType": "nt:unstructured",
+ "height": "32",
+ "width": "32",
+ "sling:resourceType": "sling-cms/components/caconfig/transformationhandlers/size"
+ },
+ "crop": {
+ "jcr:primaryType": "nt:unstructured",
+ "position": "CENTER",
+ "sling:resourceType": "sling-cms/components/caconfig/transformationhandlers/crop"
+ }
+ }
+ }
}
},
"site": {
@@ -96,7 +159,7 @@
]
},
"policies": {
- "jcr:primaryType": "sling:Config",
+ "jcr:primaryType": "sling:Config",
"jcr:title": "Default Policy",
"sling:resourceType": "sling-cms/components/caconfig/policies",
"policy": {
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
index 69e44fa..f130dc8 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
@@ -18,5 +18,7 @@
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
<c:if test="${slingRequest.requestPathInfo.suffixResource != null}">
- <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
+ <div class="scroll-container">
+ <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
+ </div>
</c:if>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/config.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/config.jsp
index 2705df3..0291f24 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/config.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/config.jsp
@@ -19,6 +19,9 @@
<%@include file="/libs/sling-cms/global.jsp"%>
<br/>
<h3><sling:encode value="${properties['jcr:title']}" mode="HTML" /> (${resource.path})</h3>
+<c:if test="${sling:getRelativeResource(resource, 'thumbnail') != null}">
+ <img src="${resource.path}/thumbnail.transform/sling-cms-thumbnail128.png" alt="Thumbnail" class="image is-128x128" />
+</c:if>
<br/>
<div>
<h4>Allowed Paths</h4>
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/edit.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/edit.json
index cba3207..e01bec3 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/edit.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/config/edit.json
@@ -12,6 +12,19 @@
"name": "jcr:title",
"required": true
},
+ "thumbnail": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Thumbnail",
+ "name": "thumbnail",
+ "type": "file"
+ },
+ "thumbnailTypeHint": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "thumbnail@TypeHint",
+ "value": "sling:File"
+ },
"allowedPaths": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "sling-cms/components/editor/fields/repeating",
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
index f90e8b8..2fdf949 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
@@ -17,8 +17,10 @@
* under the License.
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
- <c:set var="cmsEditEnabled" value="true" scope="request" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
-<sling:include path="${slingRequest.requestPathInfo.suffix}" resourceType="sling-cms/components/caconfig/template/config" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
-<c:set var="cmsEditEnabled" value="false" scope="request" />
\ No newline at end of file
+<div class="scroll-container">
+ <c:set var="cmsEditEnabled" value="true" scope="request" />
+ <sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
+ <sling:include path="${slingRequest.requestPathInfo.suffix}" resourceType="sling-cms/components/caconfig/template/config" />
+ <sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
+ <c:set var="cmsEditEnabled" value="false" scope="request" />
+</div>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config.json
new file mode 100644
index 0000000..ef57689
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config.json
@@ -0,0 +1,4 @@
+{
+ "jcr:primaryType": "sling:Component",
+ "jcr:title": "Sling CMS - Transformation Configuration"
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config/config.jsp
similarity index 62%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config/config.jsp
index f90e8b8..117d4a2 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config/config.jsp
@@ -17,8 +17,20 @@
* under the License.
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
- <c:set var="cmsEditEnabled" value="true" scope="request" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
-<sling:include path="${slingRequest.requestPathInfo.suffix}" resourceType="sling-cms/components/caconfig/template/config" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
-<c:set var="cmsEditEnabled" value="false" scope="request" />
\ No newline at end of file
+<br/>
+<div>
+ <dl>
+ <dt>Name</dt>
+ <dd><sling:encode value="${properties.name}" mode="HTML" />
+ </dl>
+</div>
+<hr/>
+<div>
+ <h4>
+ Transformation Handlers
+ </h4>
+ <c:set var="oldAvailableTypes" value="${availableTypes}" />
+ <c:set var="availableTypes" value="SlingCMS-TransformationHandler" scope="request" />
+ <sling:include path="handlers" resourceType="sling-cms/components/general/reloadcontainer" />
+ <c:set var="availableTypes" value="${oldAvailableTypes}" scope="request" />
+</div>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config/edit.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config/edit.json
new file mode 100644
index 0000000..6c8dd08
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/config/edit.json
@@ -0,0 +1,16 @@
+ {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save Transformation",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "name": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Name",
+ "name": "name",
+ "required": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/transformation.jsp
similarity index 65%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/transformation.jsp
index f90e8b8..2534257 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformation/transformation.jsp
@@ -17,8 +17,10 @@
* under the License.
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
- <c:set var="cmsEditEnabled" value="true" scope="request" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
-<sling:include path="${slingRequest.requestPathInfo.suffix}" resourceType="sling-cms/components/caconfig/template/config" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
-<c:set var="cmsEditEnabled" value="false" scope="request" />
\ No newline at end of file
+<div class="scroll-container">
+ <c:set var="cmsEditEnabled" value="true" scope="request" />
+ <sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
+ <sling:include path="${slingRequest.requestPathInfo.suffix}" resourceType="sling-cms/components/caconfig/transformation/config" />
+ <sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
+ <c:set var="cmsEditEnabled" value="false" scope="request" />
+</div>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop.json
new file mode 100644
index 0000000..6b9670f
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType": "sling:Component",
+ "jcr:title": "Sling CMS - Transformation Crop Handler",
+ "componentType": "SlingCMS-TransformationHandler"
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop/crop.jsp
similarity index 80%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop/crop.jsp
index 69e44fa..f5d6a7d 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop/crop.jsp
@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/ --%>
-<%@include file="/libs/sling-cms/global.jsp"%>
-<c:if test="${slingRequest.requestPathInfo.suffixResource != null}">
- <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
-</c:if>
\ No newline at end of file
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<dl>
+ <dt>Position</dt>
+ <dd>${properties.position}</dd>
+</dl>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop/edit.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop/edit.json
new file mode 100644
index 0000000..4aa1dbb
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/crop/edit.json
@@ -0,0 +1,53 @@
+ {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "position": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/select",
+ "label": "Position",
+ "name": "position",
+ "options": {
+ "CENTER": {
+ "label": "Center",
+ "value": "CENTER"
+ },
+ "BOTTOM_CENTER": {
+ "label": "Bottom Center",
+ "value": "BOTTOM_CENTER"
+ },
+ "BOTTOM_LEFT": {
+ "label": "Bottom Left",
+ "value": "BOTTOM_LEFT"
+ },
+ "BOTTOM_RIGHT": {
+ "label": "Bottom Right",
+ "value": "BOTTOM_RIGHT"
+ },
+ "CENTER_LEFT": {
+ "label": "Center Left",
+ "value": "CENTER_LEFT"
+ },
+ "CENTER_RIGHT": {
+ "label": "Center Right",
+ "value": "CENTER_RIGHT"
+ },
+ "TOP_LEFT": {
+ "label": "Top Left",
+ "value": "TOP_LEFT"
+ },
+ "TOP_CENTER": {
+ "label": "Top Center",
+ "value": "TOP_CENTER"
+ },
+ "TOP_RIGHT": {
+ "label": "Top Right",
+ "value": "TOP_RIGHT"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size.json
new file mode 100644
index 0000000..55709a9
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType": "sling:Component",
+ "jcr:title": "Sling CMS - Transformation Size Handler",
+ "componentType": "SlingCMS-TransformationHandler"
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size/edit.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size/edit.json
new file mode 100644
index 0000000..4469a65
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size/edit.json
@@ -0,0 +1,23 @@
+ {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "width": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Width",
+ "name": "width",
+ "type": "number"
+ },
+ "height": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Height",
+ "name": "height",
+ "type": "number"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size/size.jsp
similarity index 80%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size/size.jsp
index 69e44fa..8c7ad92 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformationhandlers/size/size.jsp
@@ -16,7 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/ --%>
-<%@include file="/libs/sling-cms/global.jsp"%>
-<c:if test="${slingRequest.requestPathInfo.suffixResource != null}">
- <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
-</c:if>
\ No newline at end of file
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<dl>
+ <dt>Width</dt>
+ <dd>${properties.width}</dd>
+ <dt>Height</dt>
+ <dd>${properties.height}</dd>
+</dl>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformations.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformations.json
new file mode 100644
index 0000000..3ea8caa
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformations.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType": "sling:Component",
+ "jcr:title": "Sling CMS - Transformations Configuration",
+ "componentType": "SlingCMS-Config"
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformations/transformations.jsp
similarity index 76%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformations/transformations.jsp
index 69e44fa..38f596d 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/transformations/transformations.jsp
@@ -16,7 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/ --%>
-<%@include file="/libs/sling-cms/global.jsp"%>
-<c:if test="${slingRequest.requestPathInfo.suffixResource != null}">
- <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
-</c:if>
\ No newline at end of file
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<sling:include path="/mnt/overlay/sling-cms/content/transformations/editor" resourceType="sling-cms/components/general/container" replaceSuffix="${slingRequest.requestPathInfo.suffixResource.parent.path}" />
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentactions/contentactions.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentactions/contentactions.jsp
index 5880c78..e057216 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentactions/contentactions.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentactions/contentactions.jsp
@@ -18,17 +18,56 @@
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
<nav class="level">
- <div class="level-left">
- <div class="level-item">
- <div class="buttons has-addons">
- <c:forEach var="action" items="${sling:listChildren(sling:getRelativeResource(resource,'actions'))}" varStatus="status">
- <a class="button Fetch-Modal" data-title="Add ${action.valueMap.label}" data-path=".Main-Content form" href="${action.valueMap.prefix}${slingRequest.requestPathInfo.suffix}">+ ${action.valueMap.label}</a>
- </c:forEach>
- </div>
- </div>
- <div class="level-item">
- <div class="buttons has-addons actions-target">
- </div>
- </div>
- </div>
+ <div class="level-left">
+ <div class="level-item">
+ <div class="buttons has-addons">
+ <c:forEach var="action" items="${sling:listChildren(sling:getRelativeResource(resource,'actions'))}" varStatus="status">
+ <a class="button Fetch-Modal" data-title="Add ${action.valueMap.label}" data-path=".Main-Content form" href="${action.valueMap.prefix}${slingRequest.requestPathInfo.suffix}">+ ${action.valueMap.label}</a>
+ </c:forEach>
+ </div>
+ </div>
+ <div class="level-item">
+ <div class="buttons has-addons actions-target">
+ </div>
+ </div>
+ </div>
+ <c:if test="${properties.includeSwitcher}">
+ <div class="level-right">
+ <div class="level-item">
+ <div class="field">
+ <div class="control has-icons-left">
+ <sling:adaptTo adaptable="${resourceResolver}" adaptTo="org.apache.sling.cms.AuthorizableWrapper" var="auth" />
+ <sling:getResource path="${auth.authorizable.path}/profile" var="profile" />
+ <c:set var="pagePath" value="${sling:adaptTo(resource,'org.apache.sling.cms.PageManager').page.path}" />
+ <form method="get" action="" class="layout-switch">
+ <div class="select">
+ <select>
+ <c:choose>
+ <c:when test="${slingRequest.requestPathInfo.selectorString == 'table' || (profile.valueMap.defaultLayout == 'table' && slingRequest.requestPathInfo.selectorString != 'grid')}">
+ <option value="/cms${fn:substring(pagePath,30,fn:length(pagePath))}.grid.html${slingRequest.requestPathInfo.suffix}">Grid</option>
+ <option selected value="/cms${fn:substring(pagePath,30,fn:length(pagePath))}.table.html${slingRequest.requestPathInfo.suffix}">Table</option>
+ </c:when>
+ <c:otherwise>
+ <option selected value="/cms${fn:substring(pagePath,30,fn:length(pagePath))}.grid.html${slingRequest.requestPathInfo.suffix}">Grid</option>
+ <option value="/cms${fn:substring(pagePath,30,fn:length(pagePath))}.table.html${slingRequest.requestPathInfo.suffix}">Table</option>
+ </c:otherwise>
+ </c:choose>
+ </select>
+ </div>
+ <div class="icon is-small is-left">
+ <c:choose>
+ <c:when test="${slingRequest.requestPathInfo.selectorString == 'table' || (profile.valueMap.defaultLayout == 'table' && slingRequest.requestPathInfo.selectorString != 'grid')}">
+ <i class="jam jam-unordered-list"></i>
+ </c:when>
+ <c:otherwise>
+ <i class="jam jam-grid"></i>
+ </c:otherwise>
+ </c:choose>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div>
+ </div>
+ </c:if>
</nav>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentbreadcrumb/contentbreadcrumb.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentbreadcrumb/contentbreadcrumb.jsp
index 694fd5e..1fc2a82 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentbreadcrumb/contentbreadcrumb.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentbreadcrumb/contentbreadcrumb.jsp
@@ -19,18 +19,18 @@
<%@include file="/libs/sling-cms/global.jsp"%>
<sling:adaptTo var="breadcrumb" adaptable="${slingRequest}" adaptTo="org.apache.sling.cms.core.models.ContentBreadcrumb" />
<nav class="breadcrumb" aria-label="breadcrumbs">
-<ul>
- <c:forEach var="parent" items="${breadcrumb.parents}">
- <li>
- <a href="${parent.left}">
- <sling:encode value="${parent.right}" mode="HTML" />
+ <ul>
+ <c:forEach var="parent" items="${breadcrumb.parents}">
+ <li>
+ <a href="${parent.left}">
+ <sling:encode value="${parent.right}" mode="HTML" />
+ </a>
+ </li>
+ </c:forEach>
+ <li class="is-active">
+ <a href="#">
+ <sling:encode value="${breadcrumb.currentItem}" mode="HTML" />
</a>
</li>
- </c:forEach>
- <li class="is-active">
- <a href="#">
- <sling:encode value="${breadcrumb.currentItem}" mode="HTML" />
- </a>
- </li>
-</ul>
+ </ul>
</nav>
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
new file mode 100644
index 0000000..0bb2c75
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentgrid/contentgrid.jsp
@@ -0,0 +1,114 @@
+<%-- /*
+ * 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"%>
+<div class="reload-container scroll-container contentnav" data-path="${resource.path}.grid.html${slingRequest.requestPathInfo.suffix}">
+ <form method="get" class="table__filter">
+ <p class="control has-icons-left">
+ <label class="is-vhidden" for="search-term">Search</label>
+ <input class="input is-small" type="text" name="search" id="search-term">
+ <span class="icon is-small is-left">
+ <i class="jam jam-search" aria-hidden="true"></i>
+ </span>
+ </p>
+ </form>
+ <div class="tile is-ancestor">
+ <c:forEach var="child" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}" varStatus="status">
+ <c:set var="showCard" value="${false}" />
+ <c:forEach var="type" items="${sling:listChildren(sling:getRelativeResource(resource,'types'))}">
+ <c:if test="${child.valueMap['jcr:primaryType'] == type.name}">
+ <c:set var="showCard" value="${true}" />
+ </c:if>
+ </c:forEach>
+ <c:if test="${showCard}">
+ <div class="tile is-parent is-3 contentnav__item">
+ <div class="tile is-child">
+ <div class="card is-linked " data-value="${child.path}">
+ <div class="card-image">
+ <figure class="image is-5by4">
+ <c:choose>
+ <c:when test="${child.resourceType == 'sling:File' || child.resourceType == 'nt:file'}">
+ <img src="${child.path}.transform/sling-cms-thumbnail.png" alt="${child.name}">
+ </c:when>
+ <c:when test="${child.resourceType == 'sling:Site'}">
+ <img src="/static/sling-cms/thumbnails/site.png.transform/sling-cms-thumbnail.png" alt="${sling:encode(child.name, 'HTML_ATTR')}">
+ </c:when>
+ <c:when test="${child.resourceType == 'sling:OrderedFolder' || child.resourceType == 'sling:Folder' || child.resourceType == 'nt:folder'}">
+ <img src="/static/sling-cms/thumbnails/folder.png.transform/sling-cms-thumbnail.png" alt="${sling:encode(child.name, 'HTML_ATTR')}">
+ </c:when>
+ <c:when test="${child.resourceType == 'sling:Page'}">
+ <c:set var="templateThumbnail" value="${child.valueMap['jcr:content/sling:template']}/thumbnail"/>
+ <c:choose>
+ <c:when test="${sling:getResource(resourceResolver, templateThumbnail) != null}">
+ <img src="${templateThumbnail}.transform/sling-cms-thumbnail.png" alt="${sling:encode(child.name, 'HTML_ATTR')}">
+ </c:when>
+ <c:otherwise>
+ <img src="/static/sling-cms/thumbnails/page.png.transform/sling-cms-thumbnail.png" alt="${child.name}">
+ </c:otherwise>
+ </c:choose>
+ </c:when>
+ <c:otherwise>
+ <img src="/static/sling-cms/thumbnails/file.png.transform/sling-cms-thumbnail.png" alt="${child.name}">
+ </c:otherwise>
+ </c:choose>
+ </figure>
+ <div class="is-vhidden cell-actions">
+ <sling:getResource base="${resource}" path="types/${child.valueMap['jcr:primaryType']}/columns/actions" var="colConfig" />
+
+ <c:forEach var="actionConfig" items="${sling:listChildren(colConfig)}">
+ <c:choose>
+ <c:when test="${actionConfig.valueMap.modal}">
+ <a class="button Fetch-Modal" data-title="${sling:encode(actionConfig.valueMap.title,'HTML_ATTR')}" data-path="${actionConfig.valueMap.ajaxPath != null ? actionConfig.valueMap.ajaxPath : '.Main-Content form'}" href="${actionConfig.valueMap.prefix}${child.path}" title="${sling:encode(actionConfig.valueMap.title,'HTML_ATTR')}">
+ <span class="jam jam-${actionConfig.valueMap.icon}">
+ <span class="is-vhidden">
+ ${sling:encode(actionConfig.valueMap.title,'HTML')}
+ </span>
+ </span>
+ </a>
+ </c:when>
+ <c:otherwise>
+ <a class="button" ${actionConfig.valueMap.new != false ? 'target="_blank"' : ''} href="${actionConfig.valueMap.prefix}${child.path}" title="${sling:encode(actionConfig.valueMap.title,'HTML_ATTR')}">
+ <span class="jam jam-${actionConfig.valueMap.icon}">
+ <span class="is-vhidden">
+ ${sling:encode(actionConfig.valueMap.title,'HTML')}
+ </span>
+ </span>
+ </a>
+ </c:otherwise>
+ </c:choose>
+ </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="${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 item-link">${child.name}</a>
+ </c:when>
+ <c:otherwise>
+ <span class="card-footer-item">${child.name}</span>
+ </c:otherwise>
+ </c:choose>
+ </footer>
+ </div>
+ </div>
+ </div>
+ </c:if>
+ </c:forEach>
+ </div>
+</div>
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentlayout/contentlayout.jsp
similarity index 57%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentlayout/contentlayout.jsp
index f90e8b8..0dd476c 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/template/template.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contentlayout/contentlayout.jsp
@@ -17,8 +17,13 @@
* under the License.
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
- <c:set var="cmsEditEnabled" value="true" scope="request" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
-<sling:include path="${slingRequest.requestPathInfo.suffix}" resourceType="sling-cms/components/caconfig/template/config" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
-<c:set var="cmsEditEnabled" value="false" scope="request" />
\ No newline at end of file
+<sling:adaptTo adaptable="${resourceResolver}" adaptTo="org.apache.sling.cms.AuthorizableWrapper" var="auth" />
+<sling:getResource path="${auth.authorizable.path}/profile" var="profile" />
+<c:choose>
+ <c:when test="${slingRequest.requestPathInfo.selectorString == 'table' || (profile.valueMap.defaultLayout == 'table' && slingRequest.requestPathInfo.selectorString != 'grid')}">
+ <sling:include path="${resource.path}" resourceType="sling-cms/components/cms/contenttable" />
+ </c:when>
+ <c:otherwise>
+ <sling:include path="${resource.path}" resourceType="sling-cms/components/cms/contentgrid" />
+ </c:otherwise>
+</c:choose>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contenttable/contenttable.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contenttable/contenttable.jsp
index bb085e5..cde6ae5 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contenttable/contenttable.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/contenttable/contenttable.jsp
@@ -17,7 +17,7 @@
* under the License.
*/ --%>
<%@include file="/libs/sling-cms/global.jsp"%>
- <div class="reload-container table__wrapper" data-path="${resource.path}.html${slingRequest.requestPathInfo.suffix}">
+ <div class="reload-container table__wrapper scroll-container contentnav" data-path="${resource.path}.html${slingRequest.requestPathInfo.suffix}">
<form method="get" class="table__filter">
<p class="control has-icons-left">
<label class="is-vhidden" for="search-term">Search</label>
@@ -46,7 +46,7 @@
<c:forEach var="child" items="${sling:listChildren(sling:getResource(resourceResolver, parentPath))}" varStatus="status">
<sling:getResource var="typeConfig" base="${resource}" path="types/${child.valueMap['jcr:primaryType']}" />
<c:if test="${typeConfig != null && !fn:contains(child.name,':')}">
- <tr class="sortable__row" data-resource="${child.path}" data-type="${typeConfig.path}">
+ <tr class="contentnav__item sortable__row" data-resource="${child.path}" data-type="${typeConfig.path}">
<td class="Cell-Static" title="# ${status.index + 1}" data-sort-value="<fmt:formatNumber pattern="0000" value="${count}" />">
${count}
</td>
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/i18ncontainer/i18ncontainer.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/i18ncontainer/i18ncontainer.jsp
new file mode 100644
index 0000000..70829c1
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/i18ncontainer/i18ncontainer.jsp
@@ -0,0 +1,89 @@
+<%-- /*
+ * 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"%>
+<div class="scroll-container">
+ <sling:include path="${resource.path}" resourceType="sling-cms/components/general/container" />
+ <c:forEach var="language" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}">
+ <c:if test="${firstChild == null && not empty language.valueMap['jcr:language']}">
+ <c:set var="firstChild" value="${language}" />
+ </c:if>
+ </c:forEach>
+ <nav class="level">
+ <div class="level-left">
+ <div class="level-item">
+ <a class="Button Fetch-Modal" data-title="Add Entry" data-path=".Main-Content form" href="/cms/i18n/entry/create.html${firstChild.path}">+ Entry</a>
+ </div>
+ </div>
+ </nav>
+ <form method="post" action="${slingRequest.requestPathInfo.suffix}" enctype="multipart/form-data" class="Form-Ajax" data-add-date="false">
+ <fieldset class="form-wrapper field">
+ <input type="hidden" name="_charset_" value="utf-8" />
+ <table class="table is-fullwidth is-striped">
+ <thead>
+ <tr>
+ <th class="Column-key">
+ Key
+ </th>
+ <c:forEach var="language" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}">
+ <c:if test="${not empty language.valueMap['jcr:language']}">
+ <th class="Column-${language.valueMap['jcr:language']}">
+ <sling:adaptTo adaptable="${language}" adaptTo="org.apache.sling.cms.core.models.LocaleResource" var="localeResource" />
+ <sling:encode value="${localeResource.locale.displayLanguage}" mode="HTML" /> <sling:encode value="${localeResource.locale.displayCountry}" mode="HTML" />
+ <br/>
+ <small>(<sling:encode value="${language.valueMap['jcr:language']}" mode="HTML" />)</small>
+ </th>
+ </c:if>
+ </c:forEach>
+ </tr>
+ </thead>
+ <tbody>
+ <sling:adaptTo var="helper" adaptable="${slingRequest.requestPathInfo.suffixResource}" adaptTo="org.apache.sling.cms.core.models.i18nHelper" />
+ <c:forEach var="key" items="${helper.keys}">
+ <tr>
+ <td>
+ <sling:encode value="${key}" mode="HTML" />
+ </td>
+ <c:forEach var="language" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}">
+ <c:if test="${not empty language.valueMap['jcr:language']}">
+ <td>
+ <c:set var="keyfound" value="false" />
+ <c:forEach var="entry" items="${sling:listChildren(language)}">
+ <c:if test="${entry.valueMap['sling:key'] == key}">
+ <c:set var="keyfound" value="true" />
+ <input name="${language.name}/${entry.name}/sling:message" class="input" type="text" value="${sling:encode(entry.valueMap['sling:message'],'HTML_ATTR')}" />
+ <input name="${language.name}/${entry.name}/sling:key" type="hidden" value="${key}" />
+ </c:if>
+ </c:forEach>
+ <c:if test="${keyfound == 'false'}">
+ <c:set var="rand" value="${helper.random}" />
+ <input name="${language.name}/entry_${rand}/sling:message" class="input" type="text" value="" />
+ <input name="${language.name}/entry_${rand}/sling:key" type="hidden" value="${key}" />
+ <input name="${language.name}/entry_${rand}/jcr:primaryType" type="hidden" value="sling:MessageEntry" />
+ </c:if>
+ </td>
+ </c:if>
+ </c:forEach>
+ </tr>
+ </c:forEach>
+ </tbody>
+ </table>
+ <button class="button is-primary">Save i18n Dictionary</button>
+ </fieldset>
+ </form>
+</div>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/i18ntable/i18ntable.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/i18ntable/i18ntable.jsp
deleted file mode 100644
index 467bef1..0000000
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/cms/i18ntable/i18ntable.jsp
+++ /dev/null
@@ -1,87 +0,0 @@
-<%-- /*
- * 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"%>
-
-<c:forEach var="language" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}">
- <c:if test="${firstChild == null && not empty language.valueMap['jcr:language']}">
- <c:set var="firstChild" value="${language}" />
- </c:if>
-</c:forEach>
-<nav class="level">
- <div class="level-left">
- <div class="level-item">
- <a class="Button Fetch-Modal" data-title="Add Entry" data-path=".Main-Content form" href="/cms/i18n/entry/create.html${firstChild.path}">+ Entry</a>
- </div>
- </div>
-</nav>
-<form method="post" action="${slingRequest.requestPathInfo.suffix}" enctype="multipart/form-data" class="Form-Ajax" data-add-date="false">
- <fieldset class="form-wrapper field">
- <input type="hidden" name="_charset_" value="utf-8" />
- <table class="table is-fullwidth is-striped">
- <thead>
- <tr>
- <th class="Column-key">
- Key
- </th>
- <c:forEach var="language" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}">
- <c:if test="${not empty language.valueMap['jcr:language']}">
- <th class="Column-${language.valueMap['jcr:language']}">
- <sling:adaptTo adaptable="${language}" adaptTo="org.apache.sling.cms.core.models.LocaleResource" var="localeResource" />
- <sling:encode value="${localeResource.locale.displayLanguage}" mode="HTML" /> <sling:encode value="${localeResource.locale.displayCountry}" mode="HTML" />
- <br/>
- <small>(<sling:encode value="${language.valueMap['jcr:language']}" mode="HTML" />)</small>
- </th>
- </c:if>
- </c:forEach>
- </tr>
- </thead>
- <tbody>
- <sling:adaptTo var="helper" adaptable="${slingRequest.requestPathInfo.suffixResource}" adaptTo="org.apache.sling.cms.core.models.i18nHelper" />
- <c:forEach var="key" items="${helper.keys}">
- <tr>
- <td>
- <sling:encode value="${key}" mode="HTML" />
- </td>
- <c:forEach var="language" items="${sling:listChildren(slingRequest.requestPathInfo.suffixResource)}">
- <c:if test="${not empty language.valueMap['jcr:language']}">
- <td>
- <c:set var="keyfound" value="false" />
- <c:forEach var="entry" items="${sling:listChildren(language)}">
- <c:if test="${entry.valueMap['sling:key'] == key}">
- <c:set var="keyfound" value="true" />
- <input name="${language.name}/${entry.name}/sling:message" class="input" type="text" value="${sling:encode(entry.valueMap['sling:message'],'HTML_ATTR')}" />
- <input name="${language.name}/${entry.name}/sling:key" type="hidden" value="${key}" />
- </c:if>
- </c:forEach>
- <c:if test="${keyfound == 'false'}">
- <c:set var="rand" value="${helper.random}" />
- <input name="${language.name}/entry_${rand}/sling:message" class="input" type="text" value="" />
- <input name="${language.name}/entry_${rand}/sling:key" type="hidden" value="${key}" />
- <input name="${language.name}/entry_${rand}/jcr:primaryType" type="hidden" value="sling:MessageEntry" />
- </c:if>
- </td>
- </c:if>
- </c:forEach>
- </tr>
- </c:forEach>
- </tbody>
- </table>
- <button class="button is-primary">Save i18n Dictionary</button>
- </fieldset>
-</form>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/thumbnail/thumbnail.jsp
similarity index 67%
copy from ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
copy to ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/thumbnail/thumbnail.jsp
index 69e44fa..67d1e84 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/edit/edit.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/thumbnail/thumbnail.jsp
@@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/ --%>
-<%@include file="/libs/sling-cms/global.jsp"%>
-<c:if test="${slingRequest.requestPathInfo.suffixResource != null}">
- <sling:include resource="${slingRequest.requestPathInfo.suffixResource}" />
-</c:if>
\ No newline at end of file
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<div class="field">
+ <c:if test="${sling:getRelativeResource(slingRequest.requestPathInfo.suffixResource,properties.subpath) != null}">
+ <img src="${slingRequest.requestPathInfo.suffix}/${properties.subpath}${properties.suffix}" alt="${sling:encode(properties.alt,'HTML_ATTR')}" class="image ${properties.className}" />
+ </c:if>
+</div>
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/pages/base/nav.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/pages/base/nav.jsp
index e9b3f8a..be4486e 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/pages/base/nav.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/pages/base/nav.jsp
@@ -19,7 +19,7 @@
<%@include file="/libs/sling-cms/global.jsp"%>
<nav class="navbar" role="navigation" aria-label="main mavigation">
<div class="navbar-brand">
- <a class="navbar-item" href="http://sling.apache.org" >
+ <a class="navbar-item" href="http://sling.apache.org">
<img src="${branding.logo}" width="100" alt="${branding.appName}"/>
</a>
<a href="/cms/start.html" class="navbar-item" title="CMS Home">
@@ -41,6 +41,9 @@
<sling:adaptTo adaptable="${resourceResolver}" adaptTo="org.apache.sling.cms.AuthorizableWrapper" var="auth" />
<sling:getResource path="${auth.authorizable.path}/profile" var="profile" />
<a class="navbar-link">
+ <c:if test="${sling:getRelativeResource(profile,'thumbnail') != null}">
+ <img src="${profile.path}/thumbnail.transform/sling-cms-thumbnail32.png" alt="${resourceResolver.userID}" />
+ </c:if>
<sling:encode value="${profile.valueMap.name}" default="${resourceResolver.userID}" mode="HTML" />
</a>
<div class="navbar-dropdown">
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/auth/user/profile.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/auth/user/profile.json
index 2680887..3a7baa3 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/auth/user/profile.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/auth/user/profile.json
@@ -20,6 +20,27 @@
"label": "Name",
"name": "profile/name"
},
+ "thumbnail": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Thumbnail",
+ "name": "profile/thumbnail",
+ "type": "file"
+ },
+ "thumbnailTypeHint": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "profile/thumbnail@TypeHint",
+ "value": "sling:File"
+ },
+ "thumbnailPreview": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/thumbnail",
+ "alt": "User Thumbnail",
+ "className": "is-128x128",
+ "subpath": "profile/thumbnail",
+ "suffix": ".transform/sling-cms-thumbnail128.png"
+ },
"email": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "sling-cms/components/editor/fields/text",
@@ -33,6 +54,24 @@
"label": "Locale",
"name": "profile/locale",
"optionsScript": "/libs/sling-cms/components/editor/scripts/localeOptions.jsp"
+ },
+ "defaultLayout": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/select",
+ "label": "Default Layout",
+ "name": "profile/defaultLayout",
+ "options": {
+ "grid": {
+ "jcr:primaryType": "nt:unstructured",
+ "label": "Grid",
+ "value": "grid"
+ },
+ "table": {
+ "jcr:primaryType": "nt:unstructured",
+ "label": "Table",
+ "value": "table"
+ }
+ }
}
}
}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/i18n/dictionary.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/i18n/dictionary.json
index 26675fe..330916f 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/i18n/dictionary.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/i18n/dictionary.json
@@ -2,15 +2,15 @@
"jcr:primaryType": "sling:Page",
"jcr:content": {
"sling:resourceType": "sling-cms/components/pages/base",
- "jcr:title": "i18n Dictionarties",
+ "jcr:title": "i18n Dictionaries",
"jcr:primaryType": "nt:unstructured",
"container": {
"jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/general/container",
+ "sling:resourceType": "sling-cms/components/cms/container",
"richtext": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "sling-cms/components/general/richtext",
- "text": "<h3>i18n Dictionary</h3>"
+ "text": "<br/><h3>i18n Dictionary</h3><br/>"
},
"contentactions": {
"jcr:primaryType": "nt:unstructured",
@@ -23,62 +23,62 @@
}
}
},
- "contenttable": {
+ "i18ncontainer": {
"jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/contenttable",
- "columns": {
+ "sling:resourceType": "sling-cms/components/cms/i18ncontainer",
+ "contenttable": {
"jcr:primaryType": "nt:unstructured",
- "title": {
+ "sling:resourceType": "sling-cms/components/cms/contenttable",
+ "columns": {
"jcr:primaryType": "nt:unstructured",
- "title": "Language"
- },
- "language": {
- "jcr:primaryType": "nt:unstructured",
- "title": "i18n Code"
+ "title": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "Language"
+ },
+ "language": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "i18n Code"
+ },
+ "actions": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "Actions"
+ }
},
- "actions": {
- "jcr:primaryType": "nt:unstructured",
- "title": "Actions"
- }
- },
- "types": {
- "jcr:primaryType": "nt:unstructured",
- "sling:Folder": {
+ "types": {
"jcr:primaryType": "nt:unstructured",
- "columns": {
+ "sling:Folder": {
"jcr:primaryType": "nt:unstructured",
- "language": {
+ "columns": {
"jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/columns/localetitle"
- },
- "i18n": {
- "jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/columns/text",
- "property": "jcr:language"
- },
- "actions": {
- "jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/columns/actions",
- "delete": {
+ "language": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/columns/localetitle"
+ },
+ "i18n": {
"jcr:primaryType": "nt:unstructured",
- "modal": true,
- "title": "Delete i18n Dictionary",
- "icon": "trash",
- "prefix": "/cms/shared/delete.html"
+ "sling:resourceType": "sling-cms/components/cms/columns/text",
+ "property": "jcr:language"
+ },
+ "actions": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/columns/actions",
+ "delete": {
+ "jcr:primaryType": "nt:unstructured",
+ "modal": true,
+ "title": "Delete i18n Dictionary",
+ "icon": "trash",
+ "prefix": "/cms/shared/delete.html"
+ }
}
}
}
}
+ },
+ "richtext_1": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/richtext",
+ "text": "<br/><h3>i18n Dictionary Entries</h3><br/>"
}
- },
- "richtext_1": {
- "jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/general/richtext",
- "text": "<h3>i18n Dictionary Entries</h3>"
- },
- "i18ntable": {
- "jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/i18ntable"
}
}
}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/content.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/content.json
index 672c375..4040af6 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/content.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/content.json
@@ -10,6 +10,7 @@
"contentactions": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "sling-cms/components/cms/contentactions",
+ "includeSwitcher": true,
"actions": {
"page": {
"jcr:primaryType": "nt:unstructured",
@@ -36,7 +37,7 @@
},
"contenttable": {
"jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/contenttable",
+ "sling:resourceType": "sling-cms/components/cms/contentlayout",
"columns": {
"jcr:primaryType": "nt:unstructured",
"name": {
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/editgroup.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/editgroup.json
index e76236b..bf30b38 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/editgroup.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/editgroup.json
@@ -30,6 +30,12 @@
"name": "sling:configRef",
"required": false,
"type": "config"
+ },
+ "contentPrimaryType": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "jcr:content/jcr:primaryType",
+ "value": "nt:unstructured"
}
}
}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/sites.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/sites.json
index 56e6176..e0d7a9c 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/sites.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/site/sites.json
@@ -10,6 +10,7 @@
"contentactions": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "sling-cms/components/cms/contentactions",
+ "includeSwitcher": true,
"actions": {
"page": {
"jcr:primaryType": "nt:unstructured",
@@ -33,7 +34,7 @@
},
"contenttable": {
"jcr:primaryType": "nt:unstructured",
- "sling:resourceType": "sling-cms/components/cms/contenttable",
+ "sling:resourceType": "sling-cms/components/cms/contentlayout",
"columns": {
"jcr:primaryType": "nt:unstructured",
"name": {
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/start.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/start.json
index 43fe601..59e4751 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/content/start.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/start.json
@@ -33,6 +33,8 @@
"jcr:primaryType": "nt:unstructured",
"alternatives": [
"/cms/site/content.html/content",
+ "/cms/site/content.table.html/content",
+ "/cms/site/content.grid.html/content",
"/cms/file/optimize.html"
],
"link": "/cms/site/sites.html/content",
@@ -51,6 +53,7 @@
"config": {
"jcr:primaryType": "nt:unstructured",
"alternatives": [
+ "/cms/transformations/edit.html",
"/cms/template/edit.html",
"/cms/config"
],
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/create.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/create.json
new file mode 100644
index 0000000..6c15e49
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/create.json
@@ -0,0 +1,55 @@
+{
+ "jcr:primaryType": "sling:Page",
+ "jcr:content": {
+ "sling:resourceType": "sling-cms/components/pages/modal",
+ "jcr:title": "Add Transformation ",
+ "modalText": "Create Transformation",
+ "jcr:primaryType": "nt:unstructured",
+ "container": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "slingform": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "actionSuffix": "/transformations/",
+ "button": "Create Transformation",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "transformationName": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Transformation Name",
+ "name": "name",
+ "required": true,
+ "skipload":true
+ },
+ "name": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Node Name",
+ "name": ":name"
+ },
+ "nameParam": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": ":nameParam",
+ "value": "name"
+ },
+ "primaryType": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "jcr:primaryType",
+ "value": "nt:unstructured"
+ },
+ "resourceType": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "sling:resourceType",
+ "value": "sling-cms/components/caconfig/transformation"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/edit.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/edit.json
new file mode 100644
index 0000000..55b7174
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/edit.json
@@ -0,0 +1,27 @@
+{
+ "jcr:primaryType": "sling:Page",
+ "jcr:content": {
+ "sling:resourceType": "sling-cms/components/pages/base",
+ "jcr:title": "Configure Site",
+ "jcr:primaryType": "nt:unstructured",
+ "container": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "richtext": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/richtext",
+ "text": "<h2>Edit Transformation</h2>"
+ },
+ "contentbreadcrumb": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/contentbreadcrumb",
+ "depth": 1,
+ "rootTitle": "Configuration"
+ },
+ "transformationeditor": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/caconfig/transformation"
+ }
+ }
+ }
+}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/editor.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/editor.json
new file mode 100644
index 0000000..c686ccc
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/transformations/editor.json
@@ -0,0 +1,102 @@
+
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "richtext": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/richtext",
+ "text": "<br/><h3>Transformations</h3>"
+ },
+ "contentactions": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/contentactions",
+ "actions": {
+ "template": {
+ "jcr:primaryType": "nt:unstructured",
+ "label": "Transformation",
+ "prefix": "/cms/transformations/create.html"
+ }
+ }
+ },
+ "contenttable": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/contenttable",
+ "appendSuffix": "/transformations",
+ "columns": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "Name"
+ },
+ "title": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "Transformation Name"
+ },
+ "lastModified": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "Last Modified"
+ },
+ "actions": {
+ "jcr:primaryType": "nt:unstructured",
+ "title": "Actions"
+ }
+ },
+ "types": {
+ "jcr:primaryType": "nt:unstructured",
+ "nt:unstructured": {
+ "jcr:primaryType": "nt:unstructured",
+ "columns": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/columns/name",
+ "link": false
+ },
+ "transformationName": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/columns/text",
+ "property": "name"
+ },
+ "lastModified": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/columns/lastmodified",
+ "subPath": ""
+ },
+ "actions": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/cms/columns/actions",
+ "edit": {
+ "jcr:primaryType": "nt:unstructured",
+ "modal": false,
+ "new": false,
+ "title": "Edit Transformation",
+ "icon": "pencil-f",
+ "prefix": "/cms/transformations/edit.html"
+ },
+ "references": {
+ "jcr:primaryType": "nt:unstructured",
+ "modal": true,
+ "title": "References",
+ "icon": "directions",
+ "prefix": "/cms/shared/references.html"
+ },
+ "movecopy": {
+ "jcr:primaryType": "nt:unstructured",
+ "modal": true,
+ "title": "Move / Copy Transformation",
+ "icon": "move-alt",
+ "prefix": "/cms/shared/movecopy.html"
+ },
+ "delete": {
+ "jcr:primaryType": "nt:unstructured",
+ "modal": true,
+ "title": "Delete Transformation",
+ "icon": "trash",
+ "prefix": "/cms/shared/delete.html"
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file