From f8e33d101b2df4782fa27239f049efc892487a85 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 20 Jan 2022 08:34:09 +0100 Subject: [PATCH 01/43] LibreCMS Default Theme: Macro for basic page structure --- .../librecms/templates/index-page.html.ftl | 36 ++++++++----------- .../themes/librecms/templates/main.html.ftl | 15 ++++++++ 2 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index f66d6bc54..ce20c84f9 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -1,22 +1,14 @@ - - - - - - Default Template - - -
-

Index page

-

This theme works.

-
-
application
-
${application}
-
themeUrl
-
${themeUrl}
-
view
-
${view!""}
-
-
- - \ No newline at end of file +<#import "./main.html.ftl" as main> + +<@main.librecms> +

Index page

+

This theme works.

+
+
application
+
${application}
+
themeUrl
+
${themeUrl}
+
view
+
${view!""}
+
+ \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl new file mode 100644 index 000000000..cd870c2ad --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl @@ -0,0 +1,15 @@ +<#macro librecms scripts=[]> + + + + + + Default Template + + +
+ <#nested> +
+ + + \ No newline at end of file -- 2.52.0 From 0c930877d13b9a95a344343474da487e87a0665c Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 20 Jan 2022 14:07:41 +0100 Subject: [PATCH 02/43] Some changes for the default theme --- .../themes/librecms/images/libreccm.svg | 803 ++++++++++++++++++ .../themes/librecms/images/librecms.svg | 722 ++++++++++++++++ .../themes/librecms/images/scientificcms.svg | 756 +++++++++++++++++ .../librecms/templates/index-page.html.ftl | 45 +- .../themes/librecms/templates/main.html.ftl | 40 +- .../src/main/scss/_custom.scss | 3 + .../StaticThemeIndexBuilder.ts | 7 +- 7 files changed, 2362 insertions(+), 14 deletions(-) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/images/libreccm.svg create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/images/librecms.svg create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/images/scientificcms.svg diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/images/libreccm.svg b/ccm-cms-default-theme/src/main/resources/themes/librecms/images/libreccm.svg new file mode 100644 index 000000000..108c91fac --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/images/libreccm.svg @@ -0,0 +1,803 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/images/librecms.svg b/ccm-cms-default-theme/src/main/resources/themes/librecms/images/librecms.svg new file mode 100644 index 000000000..f73a74cb6 --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/images/librecms.svg @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/images/scientificcms.svg b/ccm-cms-default-theme/src/main/resources/themes/librecms/images/scientificcms.svg new file mode 100644 index 000000000..e7c9029bc --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/images/scientificcms.svg @@ -0,0 +1,756 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index ce20c84f9..1a68ad991 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -1,14 +1,39 @@ <#import "./main.html.ftl" as main> <@main.librecms> -

Index page

-

This theme works.

-
-
application
-
${application}
-
themeUrl
-
${themeUrl}
-
view
-
${view!""}
-
+
+
+
+

+ LibreCMS +

+

+ No index item has been defined. +

+ + Find out more + +
+
+ + <#if CmsPagesCategorizedItemModel.contentItem??> + Category has an index item + <#else> + Category has no index item + + +

Index page

+

This theme works.

+
+
application
+
${application}
+
themeUrl
+
${themeUrl}
+
view
+
${view!""}
+
+
+ \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl index cd870c2ad..0986a1b4d 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl @@ -6,10 +6,44 @@ Default Template - -
+ +
+ +
+
<#nested> -
+ \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/scss/_custom.scss b/ccm-cms-default-theme/src/main/scss/_custom.scss index e69de29bb..1f5871ef7 100644 --- a/ccm-cms-default-theme/src/main/scss/_custom.scss +++ b/ccm-cms-default-theme/src/main/scss/_custom.scss @@ -0,0 +1,3 @@ +a.navbar-brand { + max-width: 15%; +} \ No newline at end of file diff --git a/ccm-static-theme-index-builder/src/main/typescript/ccm-static-theme-index-generator/StaticThemeIndexBuilder.ts b/ccm-static-theme-index-builder/src/main/typescript/ccm-static-theme-index-generator/StaticThemeIndexBuilder.ts index 777c92c3f..69d0643a0 100644 --- a/ccm-static-theme-index-builder/src/main/typescript/ccm-static-theme-index-generator/StaticThemeIndexBuilder.ts +++ b/ccm-static-theme-index-builder/src/main/typescript/ccm-static-theme-index-generator/StaticThemeIndexBuilder.ts @@ -6,6 +6,8 @@ import * as fsPromises from "fs/promises"; import * as mime from "mime-types"; import { fileTypeFromFile, FileTypeResult } from "file-type"; +const AMBIGOUS_FILE_TYPES = ["application/xml"]; + console.log("Static Theme Builder"); if (process.argv.length < 3) { @@ -143,7 +145,10 @@ function mapFileTypeResultToMimeType( fileTypeResult: FileTypeResult | undefined ): string { if (fileTypeResult) { - if (fileTypeResult.mime) { + if ( + fileTypeResult.mime && + !AMBIGOUS_FILE_TYPES.includes(fileTypeResult.mime) + ) { return fileTypeResult.mime; } else { const result = mime.lookup(name); -- 2.52.0 From 2cd477eae25f45f58978a8917f80ae0ec54348f7 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Tue, 25 Jan 2022 20:16:01 +0100 Subject: [PATCH 03/43] Bugfixes for managing the index item of a category. --- .../contentsections/CategoriesController.java | 368 ++++++++++++++++-- .../ui/contentsections/CategoryModel.java | 2 +- .../categorysystems/categorysystem.xhtml | 38 +- 3 files changed, 346 insertions(+), 62 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java index 71db5db33..32a66c48e 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java @@ -18,8 +18,6 @@ */ package org.librecms.ui.contentsections; -import com.arsdigita.cms.ui.authoring.multipartarticle.SectionPreviewPanel; - import org.libreccm.api.Identifier; import org.libreccm.api.IdentifierParser; import org.libreccm.categorization.Categorization; @@ -33,8 +31,12 @@ import org.libreccm.core.CcmObject; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.PermissionChecker; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemVersion; import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSectionRepository; +import org.librecms.contentsection.Folder; import org.librecms.contentsection.privileges.AdminPrivileges; import java.time.ZoneId; @@ -87,6 +89,12 @@ public class CategoriesController { @Inject private CategorySystemModel categorySystemModel; + /** + * The {@link ContentItemManager}. + */ + @Inject + private ContentItemManager itemManager; + /** * The {@link ContentSectionModel} which stores the data of the current * content section for the view. @@ -252,7 +260,7 @@ public class CategoriesController { "sectionIdentifier", sectionIdentifier ); } - + final Optional domainResult = section .getDomains() .stream() @@ -824,6 +832,41 @@ public class CategoriesController { } } + /** + * Sets the index element of the root category. + * + * @param sectionIdentifier The identifier of the current + * {@link ContentSection}. + * @param context The mapping context of the assigned category + * system. + * @param indexElementUuid The UUID of the new index element. + * + * @return A redirect to the category page or the template for generating an + * error view. + */ + @POST + @Path( + "/{context}/categories/@index-element/{indexElementUuid}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String setIndexElement( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("indexElementUuid") final String indexElementUuid + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, "/" + ); + + return setIndexObject( + result, + sectionIdentifier, + context, + context, + indexElementUuid + ); + } + /** * Sets the index element of a category. * @@ -837,7 +880,7 @@ public class CategoriesController { * @return A redirect to the category page or the template for generating an * error view. */ - @GET + @POST @Path( "/{context}/categories/{categoryPath:(.+)?}/@index-element/{indexElementUuid}") @AuthorizationRequired @@ -851,41 +894,95 @@ public class CategoriesController { final RetrieveResult result = retrieveCategory( sectionIdentifier, context, categoryPath ); + + return setIndexObject( + result, + sectionIdentifier, + context, + categoryPath, + indexElementUuid + ); +// if (result.isSuccessful()) { +// final Category category = result.getResult(); +// final Optional categorizationResult = category +// .getObjects() +// .stream() +// .filter( +// categorization -> Objects.equals( +// categorization.getUuid(), indexElementUuid +// ) +// ).findAny(); +// if (categorizationResult.isPresent()) { +// final CcmObject object = categorizationResult +// .get() +// .getCategorizedObject(); +// try { +// categoryManager.setIndexObject(category, object); +// if (object instanceof ContentItem) { +// final ContentItem item = (ContentItem) object; +// final ContentItem live = itemManager.getDraftVersion( +// item, +// ContentItem.class +// ); +// categoryManager.setIndexObject(category, live); +// } +// } catch (ObjectNotAssignedToCategoryException ex) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// models.put("categorizationUuid", indexElementUuid); +// return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; +// } +// } else { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// models.put("categorizationUuid", indexElementUuid); +// return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; +// } +// return String.format( +// "redirect:/%s/categorysystems/%s/categories/%s#objects-sections", +// sectionIdentifier, +// context, +// categoryPath +// ); +// } else { +// return result.getFailedResponseTemplate(); +// } + } + + /** + * Resets the index object of the root category. The object is still + * associated with the category after this, but no longer the index object + * of the category. + * + * @param sectionIdentifier The identifier of the current + * {@link ContentSection}. + * @param context The mapping context of the assigned category + * system. + * + * @return A redirect to the category page or the template for generating an + * error view. + */ + @POST + @Path("/{context}/categories/@index-element/reset") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String resetIndexElement( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, "/" + ); + if (result.isSuccessful()) { final Category category = result.getResult(); - final Optional categorizationResult = category - .getObjects() - .stream() - .filter( - categorization -> Objects.equals( - categorization.getUuid(), indexElementUuid - ) - ).findAny(); - if (categorizationResult.isPresent()) { - final CcmObject object = categorizationResult - .get() - .getCategorizedObject(); - try { - categoryManager.setIndexObject(category, object); - } catch (ObjectNotAssignedToCategoryException ex) { - models.put("sectionIdentifier", sectionIdentifier); - models.put("context", context); - models.put("categoryPath", categoryPath); - models.put("categorizationUuid", indexElementUuid); - return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; - } - } else { - models.put("sectionIdentifier", sectionIdentifier); - models.put("context", context); - models.put("categoryPath", categoryPath); - models.put("categorizationUuid", indexElementUuid); - return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; - } + categoryManager.resetIndexObject(category); return String.format( - "redirect:/%s/categorysystems/%s/categories/%s#objects-sections", + "redirect:/%s/categorysystems/%s/categories/", sectionIdentifier, - context, - categoryPath + context ); } else { return result.getFailedResponseTemplate(); @@ -893,7 +990,9 @@ public class CategoriesController { } /** - * Rests (removes) the index element of a category. + * Resets the index object of a category. The object is still associated + * with the category after this, but no longer the index object of the + * category. * * @param sectionIdentifier The identifier of the current * {@link ContentSection}. @@ -904,7 +1003,7 @@ public class CategoriesController { * @return A redirect to the category page or the template for generating an * error view. */ - @GET + @POST @Path("/{context}/categories/{categoryPath:(.+)?}/@index-element/reset") @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) @@ -920,7 +1019,7 @@ public class CategoriesController { final Category category = result.getResult(); categoryManager.resetIndexObject(category); return String.format( - "redirect:/%s/categorysystems/%s/categories/%s#objects-sections", + "redirect:/%s/categorysystems/%s/categories/%s", sectionIdentifier, context, categoryPath @@ -1220,7 +1319,47 @@ public class CategoriesController { } /** - * Reorders subcategories. + * Reorders objects assigned to the root category. + * + * @param sectionIdentifier The identifier of the current + * {@link ContentSection}. + * @param context The mapping context of the assigned category + * system. + * @param objectIdentifier The identifier of the object to move. + * @param direction The direction of the move. + * + * @return A redirect to the details page of the parent category or the + * template for building an error message. + */ + @POST + @Path( + "/{context}/categories/@objects/{objectIdentifier}/order" + ) + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String orderObjects( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("objectIdentifier") final String objectIdentifier, + @FormParam("direction") final String direction + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, + context, + "/" + ); + + return orderObjects( + result, + sectionIdentifier, + context, + objectIdentifier, + direction + ); + } + + /** + * Reorders objects assigned to a category. * * @param sectionIdentifier The identifier of the current * {@link ContentSection}. @@ -1246,9 +1385,147 @@ public class CategoriesController { @FormParam("direction") final String direction ) { final RetrieveResult result = retrieveCategory( - sectionIdentifier, context, categoryPath + sectionIdentifier, + context, + categoryPath ); + return orderObjects( + result, + sectionIdentifier, + context, + objectIdentifier, + direction + ); +// +// if (result.isSuccessful()) { +// final Category category = result.getResult(); +// +// final Optional categorizationResult = category +// .getObjects() +// .stream() +// .filter( +// categorization -> Objects.equals( +// categorization.getUuid(), objectIdentifier +// ) +// ).findAny(); +// if (categorizationResult.isPresent()) { +// final CcmObject object = categorizationResult +// .get() +// .getCategorizedObject(); +// try { +// switch (direction) { +// case "DECREASE": +// categoryManager.decreaseObjectOrder( +// object, category +// ); +// break; +// case "INCREASE": +// categoryManager.increaseObjectOrder( +// object, category +// ); +// break; +// default: +// // Nothing +// break; +// } +// } catch (ObjectNotAssignedToCategoryException ex) { +// return String.format( +// "redirect:/%s/categorysystems/%s/categories/%s#objects-sections", +// sectionIdentifier, +// context, +// categoryManager.getCategoryPath(category) +// ); +// } +// } +// +// return String.format( +// "redirect:/%s/categorysystems/%s/categories/%s", +// sectionIdentifier, +// context, +// categoryManager.getCategoryPath(category) +// ); +// } else { +// return result.getFailedResponseTemplate(); +// } + } + + private String setIndexObject( + final RetrieveResult result, + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @PathParam("indexElementUuid") final String indexElementUuid + ) { + if (result.isSuccessful()) { + final Category category = result.getResult(); + final List categorizationResult = category + .getObjects() + .stream() + .filter( + categorization -> Objects.equals( + categorization.getCategorizedObject().getUuid(), + indexElementUuid + ) + ) + .collect(Collectors.toList()); + if (!categorizationResult.isEmpty()) { + for (final Categorization categorization : categorizationResult) { + final CcmObject object = categorization + .getCategorizedObject(); + try { + categoryManager.setIndexObject(category, object); + if (object instanceof ContentItem) { + final ContentItem item = (ContentItem) object; + final ContentItem live = itemManager + .getDraftVersion( + item, + ContentItem.class + ); + categoryManager.setIndexObject(category, live); + } + } catch (ObjectNotAssignedToCategoryException ex) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + models.put("categorizationUuid", indexElementUuid); + return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; + } + } + } else { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + models.put("categorizationUuid", indexElementUuid); + return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; + } + if ("/".equals(categoryPath) + || category.getParentCategory() == null) { + return String.format( + "redirect:/%s/categorysystems/%s/categories/", + sectionIdentifier, + context + ); + } else { + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } + } else { + return result.getFailedResponseTemplate(); + } + } + + private String orderObjects( + final RetrieveResult result, + final String sectionIdentifier, + final String context, + final String objectIdentifier, + final String direction + ) { if (result.isSuccessful()) { final Category category = result.getResult(); @@ -1358,7 +1635,7 @@ public class CategoriesController { ); } final ContentSection section = sectionResult.get(); - if (permissionChecker.isPermitted( + if (!permissionChecker.isPermitted( AdminPrivileges.ADMINISTER_CATEGORIES, section )) { return RetrieveResult.failed( @@ -1477,6 +1754,15 @@ public class CategoriesController { category .getObjects() .stream() + .filter( + categorization -> categorization + .getCategorizedObject() instanceof ContentItem + ) + .filter( + categorization -> ((ContentItem) categorization + .getCategorizedObject()) + .getVersion() == ContentItemVersion.DRAFT + ) .map(this::buildCategorizedObjectModel) .collect(Collectors.toList()) ); diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoryModel.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoryModel.java index 4e4f258e3..f8f6cbf55 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoryModel.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoryModel.java @@ -223,7 +223,7 @@ public class CategoryModel { } public void setObjects(final List objects) { - this.objects = new ArrayList<>(); + this.objects = new ArrayList<>(objects); } public long getCategoryOrder() { diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml index 2b4e5be4a..0eb11b699 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml @@ -451,23 +451,15 @@ #{CmsAdminMessages['contentsections.categorystems.category.objects.name']} - - #{CmsAdminMessages['contentsections.categorystems.category.objects.title']} - - #{CmsAdminMessages['contentsections.categorystems.category.objects.type']} - - #{CmsAdminMessages['contentsections.categorystems.category.objects.index']} - - #{CmsAdminMessages['contentsections.categorystems.category.objects.actions']} @@ -498,7 +490,7 @@ -
- - - - #{CmsAdminMessages['contentsections.categorystems.category.objects.index_object.reset']} - + + + - - - #{CmsAdminMessages['contentsections.categorystems.category.objects.index_object.set']} - +
+ +
-- 2.52.0 From 56e53e620563a3c5eb05372c4d937448f1b1046d Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Wed, 26 Jan 2022 20:37:26 +0100 Subject: [PATCH 04/43] Bugfixes for models --- .../librecms/pages/models/ArticleModel.java | 51 ++- .../pages/models/ContentItemModel.java | 321 +++++++++++++----- .../pages/models/ContentItemTypeModel.java | 103 +++++- .../org/librecms/pages/models/EventModel.java | 119 +++++-- .../pages/models/MultiPartArticleModel.java | 156 ++++++--- .../org/librecms/pages/models/NewsModel.java | 79 ++++- 6 files changed, 627 insertions(+), 202 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java index 88a45d662..d3de25a72 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java @@ -22,9 +22,12 @@ import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contentsection.ContentItem; import org.librecms.contenttypes.Article; +import java.util.Optional; + import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; +import javax.transaction.Transactional; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -43,26 +46,54 @@ public class ArticleModel { @Inject private GlobalizationHelper globalizationHelper; + + private String title; + + private String description; + + private String text; public String getTitle() { - return globalizationHelper - .getValueFromLocalizedString(getArticle().getTitle()); + if (title == null) { + init(); + } + return title; } public String getDescription() { - return globalizationHelper - .getValueFromLocalizedString(getArticle().getDescription()); + if (description == null) { + init(); + } + return description; } public String getText() { - return globalizationHelper - .getValueFromLocalizedString(getArticle().getText()); + if (text == null) { + init(); + } + return text; } - - protected Article getArticle() { - final ContentItem contentItem = contentItemModel.getContentItem(); + + @Transactional(Transactional.TxType.REQUIRED) + protected void init() { + final ContentItem contentItem = contentItemModel + .retrieveContentItem() + .orElse(null); if (contentItem instanceof Article) { - return (Article) contentItem; + final Article article = (Article) contentItem; + + title = Optional + .ofNullable(article.getText()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + description = Optional + .ofNullable(article.getDescription()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + text = Optional + .ofNullable(article.getText()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); } else { throw new WebApplicationException( "Current content item is not an article.", diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java index 1a475683d..370cb0c58 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java @@ -23,23 +23,20 @@ import org.apache.logging.log4j.Logger; import org.libreccm.categorization.CategoryManager; import org.libreccm.categorization.CategoryRepository; import org.libreccm.l10n.GlobalizationHelper; -import org.librecms.contentsection.AttachmentList; import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItemVersion; +import org.librecms.pages.PagesRouter; import org.librecms.pages.PagesService; import java.time.ZoneId; -import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.List; import java.util.Optional; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; import javax.persistence.EntityManager; -import javax.ws.rs.NotFoundException; +import javax.transaction.Transactional; /** * Retrieves a categorized content item for the current category. To work, the @@ -59,7 +56,7 @@ public class ContentItemModel { @Inject private CategoryManager categoryManager; - + @Inject private CategoryRepository categoryRepository; @@ -82,7 +79,8 @@ public class ContentItemModel { private ContentItemVersion itemVersion; - private Optional contentItem; +// private Optional contentItem; + private Optional contentItem; public String getItemName() { return itemName; @@ -100,157 +98,314 @@ public class ContentItemModel { this.itemVersion = itemVersion; } - /** - * Retrieves the current content item. Depending if {@link #itemName} has - * been initalized with a value either the index item of the current - * category or the item in the category identified by {@link #itemName} will - * be retrieved. The item is only received once per request. The method will - * retrieve the item on the first call and store the result in - * {@link #contentItem}. Subsequent calls will return the value of - * {@link #contentItem}. If {@link #itemName} is not {@code null} and there - * is no content item with the requested name in the category this method - * throws a {@link NotFoundException}. - * - * @return The requested categorized item. If {@link #itemName} is - * {@code null}, and the current category has not index item, the - * method will return {@code null}. - * - * @throws NotFoundException If there is no item identified by the name in - * {@link #itemName}. - */ - public ContentItem getContentItem() { - return getOrRetrieveContentItem().orElse(null); + public boolean isItemAvailable() { + return getOrRetrieveContentItem().isPresent(); } - + public long getObjectId() { return getOrRetrieveContentItem() - .map(ContentItem::getObjectId) + .map(ContentItemModelData::getObjectId) .orElse(0L); } public String getUuid() { return getOrRetrieveContentItem() - .map(ContentItem::getUuid) + .map(ContentItemModelData::getUuid) .orElse(""); } public String getDisplayName() { return getOrRetrieveContentItem() - .map(ContentItem::getDisplayName) + .map(ContentItemModelData::getDisplayName) .orElse(""); } public String getItemUuid() { return getOrRetrieveContentItem() - .map(ContentItem::getItemUuid) + .map(ContentItemModelData::getItemUuid) .orElse(""); } public String getName() { return getOrRetrieveContentItem() - .map(ContentItem::getName) - .map(globalizationHelper::getValueFromLocalizedString) + .map(ContentItemModelData::getName) .orElse(""); } public String getTitle() { return getOrRetrieveContentItem() - .map(ContentItem::getTitle) - .map(globalizationHelper::getValueFromLocalizedString) + .map(ContentItemModelData::getTitle) .orElse(""); } public String getDescription() { return getOrRetrieveContentItem() - .map(ContentItem::getDescription) - .map(globalizationHelper::getValueFromLocalizedString) + .map(ContentItemModelData::getDescription) .orElse(""); } public String getVersion() { return getOrRetrieveContentItem() - .map(ContentItem::getVersion) - .map(ContentItemVersion::toString) + .map(ContentItemModelData::getVersion) .orElse(""); } public String getCreationDate() { return getOrRetrieveContentItem() - .map(ContentItem::getCreationDate) - .map(Date::toInstant) - .map(instant -> instant.atZone(ZoneId.systemDefault())) - .map(ZonedDateTime::toLocalDateTime) - .map(dateTimeFormatter::format) + .map(ContentItemModelData::getCreationDate) .orElse(""); } public String getLastModified() { return getOrRetrieveContentItem() - .map(ContentItem::getLastModified) - .map(Date::toInstant) - .map(instant -> instant.atZone(ZoneId.systemDefault())) - .map(ZonedDateTime::toLocalDateTime) - .map(dateTimeFormatter::format) + .map(ContentItemModelData::getLastModified) .orElse(""); } public String getCreationUser() { return getOrRetrieveContentItem() - .map(ContentItem::getCreationUserName) + .map(ContentItemModelData::getCreationUser) .orElse(""); } public String getLastModifyingUserName() { return getOrRetrieveContentItem() - .map(ContentItem::getLastModifyingUserName) + .map(ContentItemModelData::getLastModifyingUserName) .orElse(""); } - public List getAttachments() { - return getContentItem().getAttachments(); - } - - private Optional getOrRetrieveContentItem() { +// public List getAttachments() { +// throw new UnsupportedOperationException("Not implemented yet."); +// } +// private Optional getOrRetrieveContentItem() { +// if (contentItem == null) { +// retrieveContentItem(); +// } +// return contentItem; +// } + @Transactional(Transactional.TxType.REQUIRED) + private Optional getOrRetrieveContentItem() { if (contentItem == null) { - retrieveContentItem(); + contentItem = retrieveContentItem().map(this::buildModelData); } return contentItem; } - private void retrieveContentItem() { - if (itemName == null) { - contentItem = pagesService.findIndexItem( + @Transactional(Transactional.TxType.REQUIRED) + protected Optional retrieveContentItem() { + final Optional item; + if (itemName == null || "index".equals(itemName)) { + item = pagesService.findIndexItem( categoryRepository - .findById(categoryModel.getCategory().getCategoryId()) - .orElseThrow( - () -> new RuntimeException( - String.format( - "The category with the ID %d is set as current " - + "category, but not category with that ID " - + "can be found in the database.", - categoryModel.getCategory().getCategoryId() + .findById(categoryModel.getCategory().getCategoryId()) + .orElseThrow( + () -> new RuntimeException( + String.format( + "The category with the ID %d is set as current " + + "category, but not category with that ID " + + "can be found in the database.", + categoryModel.getCategory().getCategoryId() + ) ) - ) - ), + ), itemVersion ); } else { - contentItem = pagesService.findCategorizedItem( + item = pagesService.findCategorizedItem( categoryRepository - .findById(categoryModel.getCategory().getCategoryId()) - .orElseThrow( - () -> new RuntimeException( - String.format( - "The category with the ID %d is set as current " - + "category, but not category with that ID " - + "can be found in the database.", - categoryModel.getCategory().getCategoryId() + .findById(categoryModel.getCategory().getCategoryId()) + .orElseThrow( + () -> new RuntimeException( + String.format( + "The category with the ID %d is set as current " + + "category, but not category with that ID " + + "can be found in the database.", + categoryModel.getCategory().getCategoryId() + ) ) - ) - ), - itemName, + ), + itemName, itemVersion ); } + + return item; } + + private ContentItemModelData buildModelData(final ContentItem item) { + final ContentItemModelData data = new ContentItemModelData(); + data.setObjectId(item.getObjectId()); + data.setUuid(item.getUuid()); + data.setDisplayName(item.getDisplayName()); + data.setItemUuid(item.getItemUuid()); + data.setName( + globalizationHelper.getValueFromLocalizedString( + item.getName() + ) + ); + data.setTitle( + globalizationHelper.getValueFromLocalizedString( + item.getTitle() + ) + ); + data.setDescription( + globalizationHelper.getValueFromLocalizedString( + item.getDescription() + ) + ); + data.setVersion(item.getVersion().toString()); + data.setCreationDate( + dateTimeFormatter.format( + item + .getCreationDate() + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + ) + ); + data.setLastModified( + dateTimeFormatter.format( + item + .getLastModified() + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + ) + ); + data.setCreationUser(item.getCreationUserName()); + data.setLastModifyingUserName(item.getLastModifyingUserName()); + + //ToDo Attachments + return data; + } + + private class ContentItemModelData { + + private long objectId; + + private String uuid; + + private String displayName; + + private String itemUuid; + + private String name; + + private String title; + + private String description; + + private String version; + + private String creationDate; + + private String lastModified; + + private String creationUser; + + private String lastModifyingUserName; + + public long getObjectId() { + return objectId; + } + + public void setObjectId(final long objectId) { + this.objectId = objectId; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(final String uuid) { + this.uuid = uuid; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(final String displayName) { + this.displayName = displayName; + } + + public String getItemUuid() { + return itemUuid; + } + + public void setItemUuid(final String itemUuid) { + this.itemUuid = itemUuid; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(final String version) { + this.version = version; + } + + public String getCreationDate() { + return creationDate; + } + + public void setCreationDate(final String creationDate) { + this.creationDate = creationDate; + } + + public String getLastModified() { + return lastModified; + } + + public void setLastModified(final String lastModified) { + this.lastModified = lastModified; + } + + public String getCreationUser() { + return creationUser; + } + + public void setCreationUser(final String creationUser) { + this.creationUser = creationUser; + } + + public String getLastModifyingUserName() { + return lastModifyingUserName; + } + + public void setLastModifyingUserName( + final String lastModifyingUserName + ) { + this.lastModifyingUserName = lastModifyingUserName; + } + +// private List getAttachments() { +// throw new UnsupportedOperationException("Not implemented yet."); +// } + } + } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java index e7d6914aa..81b4d10b9 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java @@ -27,7 +27,7 @@ import java.util.Optional; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; -import javax.swing.text.AbstractDocument.Content; +import javax.transaction.Transactional; /** * MVC model for retrieving information about the content type of the current @@ -51,55 +51,124 @@ public class ContentItemTypeModel { @Inject private GlobalizationHelper globalizationHelper; - private Optional contentType; - - public ContentType getContentType() { - return getOrRetrieveContentType().orElse(null); - } + private Optional contentType; public long getContentTypeId() { return getOrRetrieveContentType() - .map(ContentType::getObjectId) + .map(ContentItemTypeModelData::getTypeId) .orElse(0L); } public String getUuid() { return getOrRetrieveContentType() - .map(ContentType::getUuid) + .map(ContentItemTypeModelData::getUuid) .orElse(""); } public String getDisplayName() { return getOrRetrieveContentType() - .map(ContentType::getDisplayName) + .map(ContentItemTypeModelData::getDisplayName) .orElse(""); } public String getLabel() { return getOrRetrieveContentType() - .map(ContentType::getLabel) - .map(globalizationHelper::getValueFromLocalizedString) + .map(ContentItemTypeModelData::getLabel) .orElse(""); } public String getDescription() { return getOrRetrieveContentType() - .map(ContentType::getDescription) - .map(globalizationHelper::getValueFromLocalizedString) + .map(ContentItemTypeModelData::getDescription) .orElse(""); } - private Optional getOrRetrieveContentType() { + private Optional getOrRetrieveContentType() { if (contentType == null) { retrieveContentType(); } return contentType; } + @Transactional(Transactional.TxType.REQUIRED) private void retrieveContentType() { - contentType = Optional - .ofNullable(contentItemModel.getContentItem()) - .map(ContentItem::getContentType); + contentType = contentItemModel.retrieveContentItem() + .map(ContentItem::getContentType) + .map(this::buildModelData); + + } + + @Transactional(Transactional.TxType.REQUIRED) + private ContentItemTypeModelData buildModelData(final ContentType type) { + final ContentItemTypeModelData data = new ContentItemTypeModelData(); + data.setDescription( + globalizationHelper.getValueFromLocalizedString( + type.getDescription() + ) + ); + data.setDisplayName(type.getDisplayName()); + data.setLabel( + globalizationHelper.getValueFromLocalizedString( + type.getLabel() + ) + ); + data.setTypeId(type.getObjectId()); + data.setUuid(type.getUuid()); + + return data; + } + + private class ContentItemTypeModelData { + + private long typeId; + + private String uuid; + + private String displayName; + + private String label; + + private String description; + + public long getTypeId() { + return typeId; + } + + public void setTypeId(final long typeId) { + this.typeId = typeId; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(final String uuid) { + this.uuid = uuid; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(final String displayName) { + this.displayName = displayName; + } + + public String getLabel() { + return label; + } + + public void setLabel(final String label) { + this.label = label; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java index 0c7f2cde6..50916ba79 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java @@ -24,10 +24,13 @@ import org.librecms.contenttypes.Event; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Optional; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; +import javax.transaction.Transactional; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -45,46 +48,120 @@ public class EventModel { @Inject private GlobalizationHelper globalizationHelper; + private final DateTimeFormatter isoDateTimeFormatter; + + private String title; + + private String text; + + private String startDateTime; + + private String endDateTime; + + private String eventDate; + + private String location; + + private String eventType; + + public EventModel() { + isoDateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME + .withZone(ZoneId.systemDefault()); + } + public String getTitle() { - return globalizationHelper.getValueFromLocalizedString( - getEvent().getTitle() - ); + if (title == null) { + init(); + } + + return title; } public String getText() { - return globalizationHelper.getValueFromLocalizedString( - getEvent().getText() - ); + if (text == null) { + init(); + } + + return text; } public String getStartDateTime() { - return DateTimeFormatter.ISO_DATE_TIME - .withZone(ZoneId.systemDefault()) - .format(getEvent().getStartDate().toInstant()); + if (startDateTime == null) { + init(); + } + + return startDateTime; } public String getEndDateTime() { - return DateTimeFormatter.ISO_DATE_TIME - .withZone(ZoneId.systemDefault()) - .format(getEvent().getEndDate().toInstant()); + if (endDateTime == null) { + init(); + } + + return endDateTime; } public String getEventDate() { - return globalizationHelper.getValueFromLocalizedString( - getEvent().getEventDate() - ); + if (eventDate == null) { + init(); + } + return eventDate; } public String getLocation() { - return globalizationHelper.getValueFromLocalizedString( - getEvent().getLocation() - ); + if (location == null) { + init(); + } + + return location; } - protected Event getEvent() { - final ContentItem contentItem = contentItemModel.getContentItem(); + public String getEventType() { + if (eventType == null) { + init(); + } + + return eventDate; + } + + @Transactional(Transactional.TxType.REQUIRED) + protected void init() { + final ContentItem contentItem = contentItemModel + .retrieveContentItem() + .orElse(null); if (contentItem instanceof Event) { - return (Event) contentItem; + final Event event = (Event) contentItem; + + title = Optional + .ofNullable(event.getTitle()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + text = Optional + .ofNullable(event.getText()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + startDateTime = Optional + .ofNullable(event.getStartDate()) + .map(Date::toInstant) + .map(isoDateTimeFormatter::format) + .orElse(""); + endDateTime = Optional + .ofNullable(event.getEndDate()) + .map(Date::toInstant) + .map(isoDateTimeFormatter::format) + .orElse(""); + eventDate = Optional + .ofNullable(event.getEventDate()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + location = Optional + .ofNullable(event.getLocation()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + eventType = Optional + .ofNullable(event.getEventType()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); } else { throw new WebApplicationException( "Current content item is not an event", diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java index 5d0ad91fe..c8247588d 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java @@ -23,12 +23,15 @@ import org.librecms.contentsection.ContentItem; import org.librecms.contenttypes.MultiPartArticle; import org.librecms.contenttypes.MultiPartArticleSection; +import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; +import javax.transaction.Transactional; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -49,83 +52,123 @@ public class MultiPartArticleModel { @Inject private PageUrlModel pageUrlModel; + private String title; + + private String summary; + + private List sectionTitles; + + private String currentSectionTitle; + + private String currentSectionText; + + private List sections; + public String getTitle() { - return globalizationHelper.getValueFromLocalizedString( - getMultiPartArticle().getTitle() - ); + if (title == null) { + init(); + } + + return title; } public String getSummary() { - return globalizationHelper.getValueFromLocalizedString( - getMultiPartArticle().getSummary() - ); + if (summary == null) { + return null; + } + + return summary; } public List getSectionTitles() { - return getMultiPartArticle() - .getSections() - .stream() - .map(MultiPartArticleSection::getTitle) - .map(globalizationHelper::getValueFromLocalizedString) - .collect(Collectors.toList()); + if (sectionTitles == null) { + init(); + } + + return Collections.unmodifiableList(sectionTitles); } public String getCurrentSectionTitle() { - final int currentSection = readCurrentSection(); - if (getMultiPartArticle().getSections().size() > currentSection) { - throw new WebApplicationException( - Response - .status(Response.Status.NOT_FOUND) - .entity( - String.format( - "MultiPartArticle %s has not section %d.", - getMultiPartArticle().getDisplayName(), - currentSection - ) - ) - .build() - ); + if (currentSectionTitle == null) { + init(); } - - return globalizationHelper.getValueFromLocalizedString( - getMultiPartArticle().getSections().get(currentSection).getTitle() - ); + + return currentSectionTitle; } public String getCurrentSectionText() { - final int currentSection = readCurrentSection(); - if (getMultiPartArticle().getSections().size() > currentSection) { - throw new WebApplicationException( - Response - .status(Response.Status.NOT_FOUND) - .entity( - String.format( - "MultiPartArticle %s has not section %d.", - getMultiPartArticle().getDisplayName(), - currentSection - ) - ) - .build() - ); + if (currentSectionText == null) { + init(); } - - return globalizationHelper.getValueFromLocalizedString( - getMultiPartArticle().getSections().get(currentSection).getText() - ); + + return currentSectionText; } public List getSections() { - return getMultiPartArticle() - .getSections() - .stream() - .map(this::buildSectionModel) - .collect(Collectors.toList()); + if (sections == null) { + init(); + } + + return Collections.unmodifiableList(sections); } - protected MultiPartArticle getMultiPartArticle() { - final ContentItem contentItem = contentItemModel.getContentItem(); + @Transactional(Transactional.TxType.REQUIRED) + protected void init() { + final ContentItem contentItem = contentItemModel + .retrieveContentItem() + .orElse(null); if (contentItem instanceof MultiPartArticle) { - return (MultiPartArticle) contentItem; + final MultiPartArticle mpa = (MultiPartArticle) contentItem; + + title = Optional + .ofNullable(mpa.getTitle()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + summary = Optional + .ofNullable(mpa.getSummary()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(null); + sectionTitles = Optional + .ofNullable(mpa.getSections()) + .map( + mpaSections -> mpaSections + .stream() + .map(MultiPartArticleSection::getTitle) + .map(globalizationHelper::getValueFromLocalizedString) + .collect(Collectors.toList()) + ) + .orElse(Collections.emptyList()); + + final int currentSection = readCurrentSection(); + if (mpa.getSections().size() > currentSection) { + throw new WebApplicationException( + Response + .status(Response.Status.NOT_FOUND) + .entity( + String.format( + "MultiPartArticle %s has not section %d.", + mpa.getDisplayName(), + currentSection + ) + ) + .build() + ); + } + currentSectionTitle = Optional + .ofNullable(mpa.getSections().get(currentSection).getTitle()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + + currentSectionText = Optional + .ofNullable(mpa.getSections().get(currentSection).getText()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + + sections = mpa + .getSections() + .stream() + .map(this::buildSectionModel) + .collect(Collectors.toList()); } else { throw new WebApplicationException( "Current content item is not an MultiPartArticle", @@ -146,6 +189,7 @@ public class MultiPartArticleModel { } } + @Transactional(Transactional.TxType.REQUIRED) private MultiPartArticleSectionModel buildSectionModel( final MultiPartArticleSection fromSection ) { diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java index 1c3e963cc..97fd81fcd 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java @@ -26,10 +26,12 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Date; +import java.util.Optional; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; +import javax.transaction.Transactional; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -46,38 +48,85 @@ public class NewsModel { @Inject private GlobalizationHelper globalizationHelper; + + private final DateTimeFormatter isoDateTimeFormatter; + + private String title; + + private String description; + + private String text; + + private String releaseDateTime; + + private boolean homepage; + + public NewsModel() { + isoDateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME + .withZone(ZoneId.systemDefault()); + } public String getTitle() { - return globalizationHelper - .getValueFromLocalizedString(getNews().getTitle()); + if (title == null) { + init(); + } + + return title; } public String getDescription() { - return globalizationHelper - .getValueFromLocalizedString(getNews().getDescription()); + if (description == null) { + init(); + } + + return description; } public String getText() { - return globalizationHelper - .getValueFromLocalizedString(getNews().getText()); + if (text == null) { + init(); + } + return text; } public String getReleaseDateTime() { - return DateTimeFormatter.ISO_DATE_TIME - .withZone(ZoneId.systemDefault()) - .format( - LocalDateTime.from(getNews().getReleaseDate().toInstant()) - ); + if (releaseDateTime == null) { + init(); + } + + return releaseDateTime; } public boolean getHomepage() { - return getNews().isHomepage(); + return homepage; } - protected News getNews() { - final ContentItem contentItem = contentItemModel.getContentItem(); + @Transactional(Transactional.TxType.REQUIRED) + protected void init() { + final ContentItem contentItem = contentItemModel + .retrieveContentItem() + .orElse(null); if (contentItem instanceof News) { - return (News) contentItem; + final News news = (News) contentItem; + + title = Optional + .ofNullable(news.getTitle()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + description = Optional + .ofNullable(news.getDescription()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + text = Optional + .ofNullable(news.getText()) + .map(globalizationHelper::getValueFromLocalizedString) + .orElse(""); + releaseDateTime = Optional + .ofNullable(news.getReleaseDate()) + .map(Date::toInstant) + .map(isoDateTimeFormatter::format) + .orElse(""); + homepage = news.isHomepage(); } else { throw new WebApplicationException( "Current content item is not a news item.", -- 2.52.0 From 224f924673439cca145b8eb18c65015860148202 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 27 Jan 2022 20:08:45 +0100 Subject: [PATCH 05/43] Some bugfixes and optimizations --- .../librecms/pages/models/ArticleModel.java | 3 +++ .../pages/models/ContentItemModel.java | 13 ++++++++++++ .../org/librecms/pages/models/EventModel.java | 7 +++++++ .../pages/models/MultiPartArticleModel.java | 7 +++++++ .../org/librecms/pages/models/NewsModel.java | 5 +++++ .../categorization/Categorization.java | 8 ++++--- .../categorization/CategoryManager.java | 21 +++++++++---------- 7 files changed, 50 insertions(+), 14 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java index d3de25a72..1c784db9e 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java @@ -53,6 +53,7 @@ public class ArticleModel { private String text; + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { if (title == null) { init(); @@ -60,6 +61,7 @@ public class ArticleModel { return title; } + @Transactional(Transactional.TxType.REQUIRED) public String getDescription() { if (description == null) { init(); @@ -67,6 +69,7 @@ public class ArticleModel { return description; } + @Transactional(Transactional.TxType.REQUIRED) public String getText() { if (text == null) { init(); diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java index 370cb0c58..a6a8d8ff4 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java @@ -98,76 +98,89 @@ public class ContentItemModel { this.itemVersion = itemVersion; } + @Transactional(Transactional.TxType.REQUIRED) public boolean isItemAvailable() { return getOrRetrieveContentItem().isPresent(); } + @Transactional(Transactional.TxType.REQUIRED) public long getObjectId() { return getOrRetrieveContentItem() .map(ContentItemModelData::getObjectId) .orElse(0L); } + @Transactional(Transactional.TxType.REQUIRED) public String getUuid() { return getOrRetrieveContentItem() .map(ContentItemModelData::getUuid) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getDisplayName() { return getOrRetrieveContentItem() .map(ContentItemModelData::getDisplayName) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getItemUuid() { return getOrRetrieveContentItem() .map(ContentItemModelData::getItemUuid) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getName() { return getOrRetrieveContentItem() .map(ContentItemModelData::getName) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { return getOrRetrieveContentItem() .map(ContentItemModelData::getTitle) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getDescription() { return getOrRetrieveContentItem() .map(ContentItemModelData::getDescription) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getVersion() { return getOrRetrieveContentItem() .map(ContentItemModelData::getVersion) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getCreationDate() { return getOrRetrieveContentItem() .map(ContentItemModelData::getCreationDate) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getLastModified() { return getOrRetrieveContentItem() .map(ContentItemModelData::getLastModified) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getCreationUser() { return getOrRetrieveContentItem() .map(ContentItemModelData::getCreationUser) .orElse(""); } + @Transactional(Transactional.TxType.REQUIRED) public String getLastModifyingUserName() { return getOrRetrieveContentItem() .map(ContentItemModelData::getLastModifyingUserName) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java index 50916ba79..3c34c6b03 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java @@ -69,6 +69,7 @@ public class EventModel { .withZone(ZoneId.systemDefault()); } + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { if (title == null) { init(); @@ -77,6 +78,7 @@ public class EventModel { return title; } + @Transactional(Transactional.TxType.REQUIRED) public String getText() { if (text == null) { init(); @@ -85,6 +87,7 @@ public class EventModel { return text; } + @Transactional(Transactional.TxType.REQUIRED) public String getStartDateTime() { if (startDateTime == null) { init(); @@ -93,6 +96,7 @@ public class EventModel { return startDateTime; } + @Transactional(Transactional.TxType.REQUIRED) public String getEndDateTime() { if (endDateTime == null) { init(); @@ -101,6 +105,7 @@ public class EventModel { return endDateTime; } + @Transactional(Transactional.TxType.REQUIRED) public String getEventDate() { if (eventDate == null) { init(); @@ -108,6 +113,7 @@ public class EventModel { return eventDate; } + @Transactional(Transactional.TxType.REQUIRED) public String getLocation() { if (location == null) { init(); @@ -116,6 +122,7 @@ public class EventModel { return location; } + @Transactional(Transactional.TxType.REQUIRED) public String getEventType() { if (eventType == null) { init(); diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java index c8247588d..2ca5e77ec 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java @@ -64,6 +64,7 @@ public class MultiPartArticleModel { private List sections; + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { if (title == null) { init(); @@ -72,6 +73,7 @@ public class MultiPartArticleModel { return title; } + @Transactional(Transactional.TxType.REQUIRED) public String getSummary() { if (summary == null) { return null; @@ -80,6 +82,8 @@ public class MultiPartArticleModel { return summary; } + + @Transactional(Transactional.TxType.REQUIRED) public List getSectionTitles() { if (sectionTitles == null) { init(); @@ -88,6 +92,7 @@ public class MultiPartArticleModel { return Collections.unmodifiableList(sectionTitles); } + @Transactional(Transactional.TxType.REQUIRED) public String getCurrentSectionTitle() { if (currentSectionTitle == null) { init(); @@ -96,6 +101,7 @@ public class MultiPartArticleModel { return currentSectionTitle; } + @Transactional(Transactional.TxType.REQUIRED) public String getCurrentSectionText() { if (currentSectionText == null) { init(); @@ -104,6 +110,7 @@ public class MultiPartArticleModel { return currentSectionText; } + @Transactional(Transactional.TxType.REQUIRED) public List getSections() { if (sections == null) { init(); diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java index 97fd81fcd..f88c421bd 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java @@ -66,6 +66,7 @@ public class NewsModel { .withZone(ZoneId.systemDefault()); } + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { if (title == null) { init(); @@ -74,6 +75,7 @@ public class NewsModel { return title; } + @Transactional(Transactional.TxType.REQUIRED) public String getDescription() { if (description == null) { init(); @@ -82,6 +84,7 @@ public class NewsModel { return description; } + @Transactional(Transactional.TxType.REQUIRED) public String getText() { if (text == null) { init(); @@ -89,6 +92,7 @@ public class NewsModel { return text; } + @Transactional(Transactional.TxType.REQUIRED) public String getReleaseDateTime() { if (releaseDateTime == null) { init(); @@ -97,6 +101,7 @@ public class NewsModel { return releaseDateTime; } + @Transactional(Transactional.TxType.REQUIRED) public boolean getHomepage() { return homepage; } diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java b/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java index f5556b22f..a958a8e2a 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Categorization.java @@ -83,9 +83,11 @@ import javax.persistence.Table; + "AND c.type = :type"), @NamedQuery( name = "Categorization.findIndexObject", - query = "SELECT c.categorizedObject FROM Categorization c " - + "WHERE c.category = :category " - + "AND c.indexObject = TRUE"), + query = "SELECT c.categorizedObject " + + "FROM Categorization c " + + "JOIN c.category a " + + "WHERE a.uuid = :catuuid " + + "AND c.indexObject = TRUE"), @NamedQuery( name = "Categorization.findIndexObjectCategorization", query = "SELECT c FROM Categorization c " diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java index 3e38614e4..a3d2b8188 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java @@ -45,6 +45,7 @@ import java.util.Objects; import java.util.Optional; import java.util.StringJoiner; import java.util.UUID; +import java.util.stream.Collectors; /** * The {@code CategoryManager} provides several helper methods for managing @@ -58,7 +59,8 @@ public class CategoryManager implements Serializable { private static final long serialVersionUID = -3354487547729008811L; private static final Logger LOGGER = LogManager.getLogger( - CategoryManager.class); + CategoryManager.class + ); @Inject private CcmObjectRepository ccmObjectRepo; @@ -982,16 +984,13 @@ public class CategoryManager implements Serializable { */ @Transactional(Transactional.TxType.REQUIRED) public List getIndexObject(final Category category) { -// if (hasIndexObject(category)) { - final TypedQuery query = entityManager.createNamedQuery( - "Categorization.findIndexObject", CcmObject.class); - query.setParameter("category", category); - - return query.getResultList(); -// return Optional.of(query.getSingleResult()); -// } else { -// return Optional.empty(); -// } + final long start = System.currentTimeMillis(); + return category + .getObjects() + .stream() + .filter(Categorization::isIndexObject) + .map(Categorization::getCategorizedObject) + .collect(Collectors.toList()); } /** -- 2.52.0 From 65d53e9992b23d6e6fda285f15b4607b2b1c7000 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 27 Jan 2022 20:44:49 +0100 Subject: [PATCH 06/43] Bugfixes --- .../src/main/resources/log4j2.xml | 6 ++- .../librecms/pages/models/ItemListModel.java | 41 ++++++++++--------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/ccm-bundle-devel-wildfly/src/main/resources/log4j2.xml b/ccm-bundle-devel-wildfly/src/main/resources/log4j2.xml index c2eed1bd8..ff0533652 100644 --- a/ccm-bundle-devel-wildfly/src/main/resources/log4j2.xml +++ b/ccm-bundle-devel-wildfly/src/main/resources/log4j2.xml @@ -107,7 +107,11 @@ - + + + diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java index 9850fb9cb..ad33aff4d 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java @@ -18,26 +18,6 @@ */ package org.librecms.pages.models; -import com.arsdigita.kernel.KernelConfig; - -import org.libreccm.categorization.Categorization; -import org.libreccm.categorization.Category; -import org.libreccm.categorization.CategoryRepository; -import org.libreccm.configuration.ConfigurationManager; -import org.libreccm.core.UnexpectedErrorException; -import org.libreccm.l10n.GlobalizationHelper; -import org.libreccm.security.Permission; -import org.libreccm.security.PermissionChecker; -import org.libreccm.security.Role; -import org.libreccm.security.RoleManager; -import org.libreccm.security.Shiro; -import org.libreccm.security.User; -import org.libreccm.security.UserRepository; -import org.librecms.contentsection.ContentItem; -import org.librecms.contentsection.ContentItemL10NManager; -import org.librecms.contentsection.ContentItemVersion; -import org.librecms.contentsection.privileges.ItemPrivileges; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -59,6 +39,26 @@ import javax.transaction.Transactional; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; +import org.libreccm.categorization.Categorization; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryRepository; +import org.libreccm.configuration.ConfigurationManager; +import org.libreccm.core.UnexpectedErrorException; +import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.security.Permission; +import org.libreccm.security.PermissionChecker; +import org.libreccm.security.Role; +import org.libreccm.security.RoleManager; +import org.libreccm.security.Shiro; +import org.libreccm.security.User; +import org.libreccm.security.UserRepository; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemL10NManager; +import org.librecms.contentsection.ContentItemVersion; +import org.librecms.contentsection.privileges.ItemPrivileges; + +import com.arsdigita.kernel.KernelConfig; + /** * * @author Jens Pelzetter @@ -156,6 +156,7 @@ public class ItemListModel { return getOffset(pageSize); } + @Transactional(Transactional.TxType.REQUIRED) public int getListSize() { return getItems().size(); } -- 2.52.0 From 661c70073fbdb9d5f931127b803e50e39a4b9756 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 29 Jan 2022 13:16:39 +0100 Subject: [PATCH 07/43] Optimizations for the models processing content items. --- .../librecms/templates/index-page.html.ftl | 69 +++- .../librecms/pages/models/ArticleModel.java | 48 ++- .../pages/models/ContentItemModel.java | 297 +++++++++++++++--- .../pages/models/ContentItemTypeModel.java | 39 ++- .../org/librecms/pages/models/EventModel.java | 58 ++-- .../pages/models/MultiPartArticleModel.java | 71 ++--- .../org/librecms/pages/models/NewsModel.java | 81 +++-- .../pages/models/ProcessesContentItem.java | 59 ++++ 8 files changed, 497 insertions(+), 225 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/pages/models/ProcessesContentItem.java diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index 1a68ad991..17edb4f29 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -4,21 +4,33 @@
-

- LibreCMS -

-

- No index item has been defined. -

- - Find out more - + <#if CmsPagesCategorizedItemModel.itemAvailable> +

+ ${CmsPagesCategorizedItemModel.title} +

+

+ ${CmsPagesCategorizedItemModel.description} +

+ + Find out more + + <#else> +

+ LibreCMS +

+

+ No index item has been defined. +

+ + Find out more + +
- <#if CmsPagesCategorizedItemModel.contentItem??> + <#if CmsPagesCategorizedItemModel.itemAvailable> Category has an index item <#else> Category has no index item @@ -34,6 +46,39 @@
view
${view!""}
+ +

From ArticleModel

+
+
Title
+
${CmsPagesArticleModel.title}
+
Description
+
${CmsPagesArticleModel.description}
+
Text
+
${CmsPagesArticleModel.text}
+
+ +

Item List

+

Item List size: ${CmsPagesItemListModel.listSize}

+
    + <#list CmsPagesItemListModel.items as item> +
  • +
    +
    UUID
    +
    ${item.uuid}
    +
    displayName
    +
    ${item.displayName}
    +
    Name
    +
    ${item.name}
    +
    Title
    +
    ${item.title}
    +
    description
    +
    ${item.description}
    +
    Type
    +
    ${item.type}
    +
    +
  • + +
\ No newline at end of file diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java index 1c784db9e..a11d3a214 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ArticleModel.java @@ -28,8 +28,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; /** * Model for getting the special properties of an {@link Article}. For general @@ -39,7 +37,7 @@ import javax.ws.rs.core.Response; */ @RequestScoped @Named("CmsPagesArticleModel") -public class ArticleModel { +public class ArticleModel implements ProcessesContentItem { @Inject private ContentItemModel contentItemModel; @@ -47,41 +45,46 @@ public class ArticleModel { @Inject private GlobalizationHelper globalizationHelper; + private boolean initialized; + private String title; private String description; private String text; + public ArticleModel() { + initialized = false; + } + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { - if (title == null) { - init(); - } + contentItemModel.init(); + return title; } @Transactional(Transactional.TxType.REQUIRED) public String getDescription() { - if (description == null) { - init(); - } + contentItemModel.init(); + return description; } @Transactional(Transactional.TxType.REQUIRED) public String getText() { - if (text == null) { - init(); - } + contentItemModel.init(); + return text; } @Transactional(Transactional.TxType.REQUIRED) - protected void init() { - final ContentItem contentItem = contentItemModel - .retrieveContentItem() - .orElse(null); + @Override + public void init(final ContentItem contentItem) { + if (initialized) { + return; + } + if (contentItem instanceof Article) { final Article article = (Article) contentItem; @@ -97,15 +100,8 @@ public class ArticleModel { .ofNullable(article.getText()) .map(globalizationHelper::getValueFromLocalizedString) .orElse(""); - } else { - throw new WebApplicationException( - "Current content item is not an article.", - Response - .status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Current content item is not an article.") - .build() - ); - } + } + initialized = true; } - + } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java index a6a8d8ff4..09037d248 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java @@ -18,24 +18,24 @@ */ package org.librecms.pages.models; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.libreccm.categorization.CategoryManager; import org.libreccm.categorization.CategoryRepository; +import org.libreccm.core.CcmObject; import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItemVersion; +import org.librecms.pages.PagesController; import org.librecms.pages.PagesRouter; import org.librecms.pages.PagesService; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.util.Iterator; import java.util.Optional; import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Instance; import javax.inject.Inject; import javax.inject.Named; -import javax.persistence.EntityManager; import javax.transaction.Transactional; /** @@ -50,162 +50,348 @@ import javax.transaction.Transactional; @Named("CmsPagesCategorizedItemModel") public class ContentItemModel { - private static final Logger LOGGER = LogManager.getLogger( - ContentItemModel.class - ); - - @Inject - private CategoryManager categoryManager; - + /** + * Category repository used to retrieve the current category. + */ @Inject private CategoryRepository categoryRepository; + /** + * Category model used to get the curretn category. + */ @Inject private CategoryModel categoryModel; - @Inject - private EntityManager entityManager; - + /** + * Utility for globalization stuff. + */ @Inject private GlobalizationHelper globalizationHelper; + /** + * Provides some utility methods. + */ @Inject private PagesService pagesService; + /** + * All instances of implementations of the {@link ProcessesContentItem} + * interface. + */ + @Inject + private Instance contentItemProcessingModels; + + /** + * A {@link DateTimeFormatter} instance for converting dates and times to an + * ISO 8601 date/time string. + */ private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.systemDefault()); + /** + * The name of the item to be shown. + */ private String itemName; + /** + * The version of the item to be shown. + */ private ContentItemVersion itemVersion; -// private Optional contentItem; + /** + * Data of the current content item, already prepared for retrieving the + * data from a MVC template. If no item with the {@link #itemName} provided + * by the {@link PagesController} is present in the category, the + * {@link Optional} will be empty. + */ private Optional contentItem; + /** + * Gets the item name provided by the {@link PagesController}. + * + * @return The item name provided by the {@link PagesController}. + */ public String getItemName() { return itemName; } + /** + * Used by the {@link PagesController} to set the name of the requested + * content item. May be used by other controllers. + * + * @param itemName The name of the requested content item. + */ public void setItemName(final String itemName) { this.itemName = itemName; } + /** + * The requested version of the content item. + * + * @return The requested version of the content item. + */ public ContentItemVersion getItemVersion() { return itemVersion; } + /** + * Used by controllers, for example the {@link PagesController} to set the + * requested version of the content item. + * + * @param itemVersion The requested version of the content item. + */ public void setItemVersion(final ContentItemVersion itemVersion) { this.itemVersion = itemVersion; } + /** + * A convient getter for checking if a content item is available from a + * template. + * + * @return {@code true} if an item is available, {@code false} if not. + */ @Transactional(Transactional.TxType.REQUIRED) public boolean isItemAvailable() { - return getOrRetrieveContentItem().isPresent(); - } - - @Transactional(Transactional.TxType.REQUIRED) - public long getObjectId() { - return getOrRetrieveContentItem() - .map(ContentItemModelData::getObjectId) - .orElse(0L); + init(); + return contentItem.isPresent(); } + /** + * Gets the {@code objectId)} (see {@link CcmObject#objectId} of the current + * item. + * + * @return The {@code objectId} of the current item if there is an item or + * {@code -1L} if there is no item. + */ + @Transactional(Transactional.TxType.REQUIRED) + public long getObjectId() { + init(); + return contentItem + .map(ContentItemModelData::getObjectId) + .orElse(-1L); + } + + /** + * Get the UUID of the current item (see {@link CcmObject#uuid}. + * + * @return The UUID of the current item if there is an item, an empty string + * if there is not item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getUuid() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getUuid) .orElse(""); } + /** + * Gets the display name of the current item (see + * {@link CcmObject#displayName}. + * + * @return The display name of the current item, or an empty string if there + * is not current item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getDisplayName() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getDisplayName) .orElse(""); } + /** + * Gets the item UUID of the current item (see {@link ContentItem#itemUuid}. + * + * @return The item UUID of the current item, or an empty string if the is + * no current item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getItemUuid() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getItemUuid) .orElse(""); } + /** + * Gets the name of the current item {@link ContentItem#name}) for the + * current language (see {@link GlobalizationHelper#getNegotiatedLocale()}). + * + * @return The name of the the current item for the current language, or an + * empty string if there is no item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getName() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getName) .orElse(""); } + /** + * Gets the title of the current item (see {@link ContentItem#title} for the + * current language (see {@link GlobalizationHelper#getNegotiatedLocale()}). + * + * @return The title of the current item for the current language, or an + * empty string if there is no item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getTitle) .orElse(""); } + /** + * Gets the description of the current item (see + * {@link ContentItem#description} for the current language (see + * {@link GlobalizationHelper#getNegotiatedLocale()}). + * + * @return The description of the current item for the current language, or + * an empty string if there is no item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getDescription() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getDescription) .orElse(""); } + /** + * Gets the version of the current item (see {@link ContentItem#version}. + * + * @return The version of the current version as a string, or an empty + * string if there is not current item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getVersion() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getVersion) .orElse(""); } + /** + * Gets the creation date/time of the current item (see + * {@link ContentItem#creationDate}. + * + * @return The creation date/time of the current item as ISO 8601 date/time + * string, or an empty string if there is no item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getCreationDate() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getCreationDate) .orElse(""); } + /** + * Gets the date/time of the last modification of the current item (see + * {@link ContentItem#lastModified}. + * + * @return The date/time of the modification of the current item as ISO 8601 + * date/time string, or an empty string of there is not current + * item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getLastModified() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getLastModified) .orElse(""); } + /** + * Gets the user name of the user that created the item. + * + * @return The user name of the user that created the item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getCreationUser() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getCreationUser) .orElse(""); } + /** + * Gets the user name of the user that did the last modifications on the + * item. + * + * @return The user name of the user that did the last modifications on the + * item. + */ @Transactional(Transactional.TxType.REQUIRED) public String getLastModifyingUserName() { - return getOrRetrieveContentItem() + init(); + return contentItem .map(ContentItemModelData::getLastModifyingUserName) .orElse(""); } -// public List getAttachments() { -// throw new UnsupportedOperationException("Not implemented yet."); -// } -// private Optional getOrRetrieveContentItem() { -// if (contentItem == null) { -// retrieveContentItem(); -// } -// return contentItem; -// } + /** + * Initialize the this model and all models implementing + * {@link ProcessesContentItem#}. + * + * If this model has not been initalizied already this method retrieves the + * current content item using {@link #retrieveContentItem()}, and + * initializes {@link #contentItem} with an instance of + * {@link ContentItemModelData} build from the item using + * {@link #buildModelData(org.librecms.contentsection.ContentItem)}. + * + * After that, the method will invoke the implementation of + * {@link ProcessesContentItem#init(org.librecms.contentsection.ContentItem)} + * for all available implemetentations of {@link ProcessesContentItem} (see + * {@link #contentItemProcessingModels}). + * + * Models implementing SHOULD call this method in their getters before + * returning a value. There is not need to wrap the invocation of this + * method in an {@code if} statement, the method will only run its logic if + * the item has not been initialized. + * + * If there is no current item, the method will do nothing. + */ @Transactional(Transactional.TxType.REQUIRED) - private Optional getOrRetrieveContentItem() { - if (contentItem == null) { - contentItem = retrieveContentItem().map(this::buildModelData); + public void init() { + if (contentItem != null) { + return; + } + + final Optional item = retrieveContentItem(); + contentItem = item.map(this::buildModelData); + + final Iterator iterator + = contentItemProcessingModels.iterator(); + while (iterator.hasNext()) { + final ProcessesContentItem model = iterator.next(); + model.init(item.orElse(null)); } - return contentItem; } + /** + * Helper method for retrieving the current content item. If + * {@link #itemName} is {@code null} or {@code index} the method will return + * if the index item of the current category. If the category has not index + * item, an empty {@link Optional} is returned. + * + * If {@link #itemName} is not {@code null} or {@code index}, the + * method will try to find a content item associated to the category where + * {@link ContentItem#name} matches {@link #itemName}. + * + * @return The current content item if any, or an empyty {@link Optional}. + * + * @see PagesService#findIndexItem(org.libreccm.categorization.Category, + * org.librecms.contentsection.ContentItemVersion) + * @see + * PagesService#findCategorizedItem(org.libreccm.categorization.Category, + * java.lang.String, org.librecms.contentsection.ContentItemVersion) + */ @Transactional(Transactional.TxType.REQUIRED) - protected Optional retrieveContentItem() { + private Optional retrieveContentItem() { final Optional item; if (itemName == null || "index".equals(itemName)) { item = pagesService.findIndexItem( @@ -245,6 +431,15 @@ public class ContentItemModel { return item; } + /** + * Helper method for building an instance {@link ContentItemModelData} for a + * {@link ContentItem}. + * + * @param item The source content item. + * + * @return An instance of {@link ContentItemModelData} for the provided + * content item. + */ private ContentItemModelData buildModelData(final ContentItem item) { final ContentItemModelData data = new ContentItemModelData(); data.setObjectId(item.getObjectId()); @@ -292,6 +487,12 @@ public class ContentItemModel { return data; } + /** + * Encapsulates the data of content item provided by this model. To avoid to + * have to many fields in this model class we use an internal class to + * encapsulate the data. The getters of the model class return the values + * from an instance of this class. + */ private class ContentItemModelData { private long objectId; diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java index 81b4d10b9..e17c42f2e 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java @@ -43,7 +43,7 @@ import javax.transaction.Transactional; */ @RequestScoped @Named("CmsPagesContentItemTypeModel") -public class ContentItemTypeModel { +public class ContentItemTypeModel implements ProcessesContentItem { @Inject private ContentItemModel contentItemModel; @@ -54,48 +54,55 @@ public class ContentItemTypeModel { private Optional contentType; public long getContentTypeId() { - return getOrRetrieveContentType() + contentItemModel.init(); + + return contentType .map(ContentItemTypeModelData::getTypeId) .orElse(0L); } public String getUuid() { - return getOrRetrieveContentType() + contentItemModel.init(); + + return contentType .map(ContentItemTypeModelData::getUuid) .orElse(""); } public String getDisplayName() { - return getOrRetrieveContentType() + contentItemModel.init(); + + return contentType .map(ContentItemTypeModelData::getDisplayName) .orElse(""); } public String getLabel() { - return getOrRetrieveContentType() + contentItemModel.init(); + + return contentType .map(ContentItemTypeModelData::getLabel) .orElse(""); } public String getDescription() { - return getOrRetrieveContentType() + contentItemModel.init(); + + return contentType .map(ContentItemTypeModelData::getDescription) .orElse(""); } - private Optional getOrRetrieveContentType() { - if (contentType == null) { - retrieveContentType(); - } - return contentType; - } - @Transactional(Transactional.TxType.REQUIRED) - private void retrieveContentType() { - contentType = contentItemModel.retrieveContentItem() + public void init(final ContentItem contentItem) { + if (contentType != null) { + return; + } + + contentType = Optional + .ofNullable(contentItem) .map(ContentItem::getContentType) .map(this::buildModelData); - } @Transactional(Transactional.TxType.REQUIRED) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java index 3c34c6b03..3e9562130 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java @@ -31,8 +31,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; /** * @@ -40,7 +38,7 @@ import javax.ws.rs.core.Response; */ @RequestScoped @Named("CmsPagesEventModel") -public class EventModel { +public class EventModel implements ProcessesContentItem { @Inject private ContentItemModel contentItemModel; @@ -48,6 +46,8 @@ public class EventModel { @Inject private GlobalizationHelper globalizationHelper; + private boolean initialized; + private final DateTimeFormatter isoDateTimeFormatter; private String title; @@ -65,77 +65,67 @@ public class EventModel { private String eventType; public EventModel() { + initialized = false; isoDateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME .withZone(ZoneId.systemDefault()); } @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { - if (title == null) { - init(); - } + contentItemModel.init(); return title; } @Transactional(Transactional.TxType.REQUIRED) public String getText() { - if (text == null) { - init(); - } + contentItemModel.init(); return text; } @Transactional(Transactional.TxType.REQUIRED) public String getStartDateTime() { - if (startDateTime == null) { - init(); - } + contentItemModel.init(); return startDateTime; } @Transactional(Transactional.TxType.REQUIRED) public String getEndDateTime() { - if (endDateTime == null) { - init(); - } + contentItemModel.init(); return endDateTime; } @Transactional(Transactional.TxType.REQUIRED) public String getEventDate() { - if (eventDate == null) { - init(); - } + contentItemModel.init(); + return eventDate; } @Transactional(Transactional.TxType.REQUIRED) public String getLocation() { - if (location == null) { - init(); - } + contentItemModel.init(); return location; } @Transactional(Transactional.TxType.REQUIRED) public String getEventType() { - if (eventType == null) { - init(); - } + contentItemModel.init(); - return eventDate; + return eventType; } + @Override @Transactional(Transactional.TxType.REQUIRED) - protected void init() { - final ContentItem contentItem = contentItemModel - .retrieveContentItem() - .orElse(null); + public void init(final ContentItem contentItem) { + if (initialized) { + return; + } + if (contentItem instanceof Event) { final Event event = (Event) contentItem; @@ -169,15 +159,9 @@ public class EventModel { .ofNullable(event.getEventType()) .map(globalizationHelper::getValueFromLocalizedString) .orElse(""); - } else { - throw new WebApplicationException( - "Current content item is not an event", - Response - .status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Current content item is not an event.") - .build() - ); } + + initialized = true; } } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java index 2ca5e77ec..34d426507 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java @@ -41,7 +41,7 @@ import javax.ws.rs.core.Response; */ @RequestScoped @Named("CmsPagesMultiPartArticleModel") -public class MultiPartArticleModel { +public class MultiPartArticleModel implements ProcessesContentItem { @Inject private ContentItemModel contentItemModel; @@ -49,6 +49,8 @@ public class MultiPartArticleModel { @Inject private GlobalizationHelper globalizationHelper; + private boolean initialized; + @Inject private PageUrlModel pageUrlModel; @@ -61,69 +63,62 @@ public class MultiPartArticleModel { private String currentSectionTitle; private String currentSectionText; - + private List sections; + public MultiPartArticleModel() { + initialized = false; + } + @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { - if (title == null) { - init(); - } - + contentItemModel.init(); + return title; } @Transactional(Transactional.TxType.REQUIRED) public String getSummary() { - if (summary == null) { - return null; - } - + contentItemModel.init(); + return summary; } - @Transactional(Transactional.TxType.REQUIRED) public List getSectionTitles() { - if (sectionTitles == null) { - init(); - } - + contentItemModel.init(); + return Collections.unmodifiableList(sectionTitles); } @Transactional(Transactional.TxType.REQUIRED) public String getCurrentSectionTitle() { - if (currentSectionTitle == null) { - init(); - } - + contentItemModel.init(); + return currentSectionTitle; } @Transactional(Transactional.TxType.REQUIRED) public String getCurrentSectionText() { - if (currentSectionText == null) { - init(); - } - + contentItemModel.init(); + return currentSectionText; } @Transactional(Transactional.TxType.REQUIRED) public List getSections() { - if (sections == null) { - init(); - } - + contentItemModel.init(); + return Collections.unmodifiableList(sections); } + @Override @Transactional(Transactional.TxType.REQUIRED) - protected void init() { - final ContentItem contentItem = contentItemModel - .retrieveContentItem() - .orElse(null); + public void init(final ContentItem contentItem) { + if (initialized) { + return; + } + if (contentItem instanceof MultiPartArticle) { final MultiPartArticle mpa = (MultiPartArticle) contentItem; @@ -165,26 +160,20 @@ public class MultiPartArticleModel { .ofNullable(mpa.getSections().get(currentSection).getTitle()) .map(globalizationHelper::getValueFromLocalizedString) .orElse(""); - + currentSectionText = Optional .ofNullable(mpa.getSections().get(currentSection).getText()) .map(globalizationHelper::getValueFromLocalizedString) .orElse(""); - + sections = mpa .getSections() .stream() .map(this::buildSectionModel) .collect(Collectors.toList()); - } else { - throw new WebApplicationException( - "Current content item is not an MultiPartArticle", - Response - .status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Current content item is not an MultiPartArticle.") - .build() - ); } + + initialized = true; } private int readCurrentSection() { diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java index f88c421bd..426a9aef7 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java @@ -22,7 +22,6 @@ import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contentsection.ContentItem; import org.librecms.contenttypes.News; -import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Date; @@ -32,8 +31,6 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Response; /** * @@ -41,79 +38,79 @@ import javax.ws.rs.core.Response; */ @RequestScoped @Named("CmsPagesNewsModel") -public class NewsModel { +public class NewsModel implements ProcessesContentItem { @Inject private ContentItemModel contentItemModel; @Inject private GlobalizationHelper globalizationHelper; - + + private boolean initialized; + private final DateTimeFormatter isoDateTimeFormatter; - + private String title; - + private String description; - + private String text; - + private String releaseDateTime; - + private boolean homepage; - + public NewsModel() { + initialized = false; isoDateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME .withZone(ZoneId.systemDefault()); } @Transactional(Transactional.TxType.REQUIRED) public String getTitle() { - if (title == null) { - init(); - } - + contentItemModel.init(); + return title; } @Transactional(Transactional.TxType.REQUIRED) public String getDescription() { - if (description == null) { - init(); - } - + contentItemModel.init(); + return description; } @Transactional(Transactional.TxType.REQUIRED) public String getText() { - if (text == null) { - init(); - } + contentItemModel.init(); + return text; } @Transactional(Transactional.TxType.REQUIRED) public String getReleaseDateTime() { - if (releaseDateTime == null) { - init(); - } - + contentItemModel.init(); + return releaseDateTime; } - - @Transactional(Transactional.TxType.REQUIRED) - public boolean getHomepage() { - return homepage; - } @Transactional(Transactional.TxType.REQUIRED) - protected void init() { - final ContentItem contentItem = contentItemModel - .retrieveContentItem() - .orElse(null); + public boolean getHomepage() { + contentItemModel.init(); + + return homepage; + } + + @Override + @Transactional(Transactional.TxType.REQUIRED) + public void init(final ContentItem contentItem) { + if (initialized) { + return; + } + if (contentItem instanceof News) { - final News news = (News) contentItem; - + final News news = (News) contentItem; + title = Optional .ofNullable(news.getTitle()) .map(globalizationHelper::getValueFromLocalizedString) @@ -132,15 +129,9 @@ public class NewsModel { .map(isoDateTimeFormatter::format) .orElse(""); homepage = news.isHomepage(); - } else { - throw new WebApplicationException( - "Current content item is not a news item.", - Response - .status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("Current content item is not a new item.") - .build() - ); } + + initialized = true; } } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ProcessesContentItem.java b/ccm-cms/src/main/java/org/librecms/pages/models/ProcessesContentItem.java new file mode 100644 index 000000000..9d3714e29 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ProcessesContentItem.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.pages.models; + +import org.hibernate.LazyInitializationException; +import org.librecms.contentsection.ContentItem; + +import javax.transaction.Transactional; + +/** + * Models that provide data for the current content item (either the index item + * of a category or a selected content item) SHOULD implement this interface. + * + * This {@link ContentItemModel} collects all instances of classes implementing + * this interface and calls their implemententation of the + * {@link #init(org.librecms.contentsection.ContentItem)} method. + * + * For an example of an implementation please look at + * {@link ContentItemTypeModel}, {@link ArticleModel} or + * at {@link MultiPartArticleModel} for a more complex model. + * + * @author Jens Pelzetter + */ +public interface ProcessesContentItem { + + /** + * Initalizes a model providing the data of a content item for MVC + * templates. + * + * If the implementing model only provides data for specific sub classes of + * {@link ContentItem} the implementation MUST check the correct type using + * the {@code instanceof} operator. If the item is not a the correct type a + * implementation MUST gracefully ignore the item. + * + * To avoid a {@link LazyInitializationException} implementations SHOULD be + * annotated with {@link Transactional} and the + * {@link Transactional.TxType#REQUIRED}. + * + * @param item The item. + */ + void init(ContentItem item); + +} -- 2.52.0 From 79c85df4a368ef1b5058aada5e4282586552b23e Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 29 Jan 2022 17:12:14 +0100 Subject: [PATCH 08/43] Include attachments into ContentItemModel --- .../models/AbstractAssetModelBuilder.java | 31 +++-- .../AbstractBinaryAssetModelBuilder.java | 2 - .../pages/models/AssetModelBuilder.java | 2 +- .../pages/models/AttachmentListModel.java | 112 ++++++++++++++++++ .../pages/models/AttachmentModel.java | 77 ++++++++++++ .../pages/models/ContentItemModel.java | 99 +++++++++++++++- 6 files changed, 305 insertions(+), 18 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/pages/models/AttachmentListModel.java create mode 100644 ccm-cms/src/main/java/org/librecms/pages/models/AttachmentModel.java diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractAssetModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractAssetModelBuilder.java index 501676ec3..586ed79b6 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractAssetModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractAssetModelBuilder.java @@ -29,31 +29,40 @@ import javax.inject.Inject; * @param * @param */ -public abstract class AbstractAssetModelBuilder -implements AssetModelBuilder { - +public abstract class AbstractAssetModelBuilder + implements AssetModelBuilder { + @Inject private GlobalizationHelper globalizationHelper; - + @Override @SuppressWarnings("unchecked") - public M buildAssetModel(final T asset) { + public M buildAssetModel(final Asset asset) { + if (!asset.getClass().isAssignableFrom(buildsAssetModelFor())) { + throw new IllegalArgumentException( + String.format( + "This builder can only process Assets of type %s.", + buildsAssetModelFor().getName() + ) + ); + } + final M model = buildModel(); model.setDisplayName(asset.getDisplayName()); model.setTitle( globalizationHelper.getValueFromLocalizedString(asset.getTitle()) ); model.setUuid(asset.getUuid()); - - addProperties(asset, model); - + + addProperties((T) asset, model); + return model; } - + protected abstract M buildModel(); - + protected void addProperties(final T asset, final M model) { // Nothing in the default implementation. } - + } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java index 735040ab8..aa9eb03d6 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java @@ -22,7 +22,6 @@ import org.libreccm.l10n.GlobalizationHelper; import org.librecms.assets.BinaryAsset; import org.librecms.contentsection.AssetManager; -import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.transaction.Transactional; @@ -32,7 +31,6 @@ import javax.transaction.Transactional; * @param * @param */ -@RequestScoped public abstract class AbstractBinaryAssetModelBuilder extends AbstractAssetModelBuilder { diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AssetModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/AssetModelBuilder.java index e0d9ee76b..c2f2d6b8b 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AssetModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AssetModelBuilder.java @@ -28,7 +28,7 @@ import org.librecms.contentsection.Asset; */ public interface AssetModelBuilder { - M buildAssetModel(T asset); + M buildAssetModel(Asset asset); Class buildsAssetModelFor(); diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AttachmentListModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/AttachmentListModel.java new file mode 100644 index 000000000..b4163e259 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AttachmentListModel.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.pages.models; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * + * @author Jens Pelzetter + */ +public class AttachmentListModel implements Comparable{ + + private long listId; + + private String uuid; + + private String name; + + private long listOrder; + + private String title; + + private String description; + + private List attachments; + + public long getListId() { + return listId; + } + + public void setListId(final long listId) { + this.listId = listId; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(final String uuid) { + this.uuid = uuid; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getListOrder() { + return listOrder; + } + + public void setListOrder(final long listOrder) { + this.listOrder = listOrder; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public List getAttachments() { + return Collections.unmodifiableList(attachments); + } + + public void setAttachments(final List attachments) { + this.attachments = new ArrayList<>(attachments); + } + + @Override + public int compareTo(final AttachmentListModel other) { + return Comparator + .comparing(AttachmentListModel::getListOrder) + .thenComparing( + AttachmentListModel::getName, String::compareToIgnoreCase + ) + .compare(this, other); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AttachmentModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/AttachmentModel.java new file mode 100644 index 000000000..0eb48c58d --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AttachmentModel.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.pages.models; + +import java.util.Comparator; + +/** + * + * @author Jens Pelzetter + */ +public class AttachmentModel implements Comparable{ + + private long attachmentId; + + private String uuid; + + private long sortKey; + + private AbstractAssetModel asset; + + public long getAttachmentId() { + return attachmentId; + } + + public void setAttachmentId(final long attachmentId) { + this.attachmentId = attachmentId; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(final String uuid) { + this.uuid = uuid; + } + + public long getSortKey() { + return sortKey; + } + + public void setSortKey(final long sortKey) { + this.sortKey = sortKey; + } + + public AbstractAssetModel getAsset() { + return asset; + } + + public void setAsset(final AbstractAssetModel asset) { + this.asset = asset; + } + + @Override + public int compareTo(final AttachmentModel other) { + return Comparator + .comparing(AttachmentModel::getSortKey) + .thenComparing(AttachmentModel::getAttachmentId) + .compare(this, other); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java index 09037d248..c919c3927 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java @@ -21,22 +21,31 @@ package org.librecms.pages.models; import org.libreccm.categorization.CategoryRepository; import org.libreccm.core.CcmObject; import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AttachmentList; import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItemVersion; +import org.librecms.contentsection.ItemAttachment; import org.librecms.pages.PagesController; import org.librecms.pages.PagesRouter; import org.librecms.pages.PagesService; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.Instance; import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; /** * Retrieves a categorized content item for the current category. To work, the @@ -50,6 +59,11 @@ import javax.transaction.Transactional; @Named("CmsPagesCategorizedItemModel") public class ContentItemModel { + /** + * Provides access to the builders for asset models. + */ + private AssetModelBuilders assetModelBuilders; + /** * Category repository used to retrieve the current category. */ @@ -483,10 +497,79 @@ public class ContentItemModel { data.setCreationUser(item.getCreationUserName()); data.setLastModifyingUserName(item.getLastModifyingUserName()); - //ToDo Attachments + data.setAttachmentLists( + item + .getAttachments() + .stream() + .map(this::buildAttachmentListModel) + .sorted() + .collect(Collectors.toList()) + ); + return data; } + private AttachmentListModel buildAttachmentListModel( + final AttachmentList attachmentList + ) { + final AttachmentListModel model = new AttachmentListModel(); + model.setAttachments( + attachmentList + .getAttachments() + .stream() + .map(this::buildAttachmentModel) + .sorted() + .collect(Collectors.toList()) + ); + model.setDescription( + globalizationHelper.getValueFromLocalizedString( + attachmentList.getDescription() + ) + ); + model.setListId(attachmentList.getListId()); + model.setListOrder(attachmentList.getListOrder()); + model.setName(attachmentList.getName()); + model.setTitle( + globalizationHelper.getValueFromLocalizedString( + attachmentList.getTitle() + ) + ); + model.setUuid(attachmentList.getUuid()); + + return model; + } + + private AttachmentModel buildAttachmentModel( + final ItemAttachment attachment + ) { + final AttachmentModel model = new AttachmentModel(); + final Asset asset = attachment.getAsset(); + final AssetModelBuilder assetModelBuilder + = assetModelBuilders + .getModelBuilderFor(asset.getClass()) + .orElseThrow( + () -> new WebApplicationException( + Response + .status(Response.Status.INTERNAL_SERVER_ERROR) + .entity( + String.format( + "Unknown asset type %s.", + asset.getClass().getName() + ) + ) + .build() + ) + ); + model.setAsset( + assetModelBuilder.buildAssetModel(attachment.getAsset()) + ); + model.setAttachmentId(attachment.getAttachmentId()); + model.setSortKey(attachment.getSortKey()); + model.setUuid(attachment.getUuid()); + + return model; + } + /** * Encapsulates the data of content item provided by this model. To avoid to * have to many fields in this model class we use an internal class to @@ -519,6 +602,8 @@ public class ContentItemModel { private String lastModifyingUserName; + private List attachmentLists; + public long getObjectId() { return objectId; } @@ -617,9 +702,15 @@ public class ContentItemModel { this.lastModifyingUserName = lastModifyingUserName; } -// private List getAttachments() { -// throw new UnsupportedOperationException("Not implemented yet."); -// } + public List getAttachmentLists() { + return Collections.unmodifiableList(attachmentLists); + } + + public void setAttachmentLists( + final List attachmentLists) { + this.attachmentLists = new ArrayList<>(attachmentLists); + } + } } -- 2.52.0 From aa49c4c5418826db1b244a2604003da07a8dc595 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 29 Jan 2022 17:42:40 +0100 Subject: [PATCH 09/43] Primary color for theme customized --- .../src/main/java/org/librecms/pages/models/ItemListModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java index ad33aff4d..08f8a7325 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java @@ -210,7 +210,7 @@ public class ItemListModel { .where( criteriaBuilder.and( catJoin.get("category").in(categories), - criteriaBuilder.equal(catJoin.get("indexObject"), false), + criteriaBuilder.isFalse(catJoin.get("indexObject")), criteriaBuilder.isNull(catJoin.get("type")), criteriaBuilder.equal( from.get("version"), ContentItemVersion.LIVE -- 2.52.0 From 535f9bed52bb3278b9b4e559ae0bc2daecd53b00 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Mon, 31 Jan 2022 19:16:56 +0100 Subject: [PATCH 10/43] Adjusted primary color of theme --- ccm-cms-default-theme/src/main/scss/_custom.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ccm-cms-default-theme/src/main/scss/_custom.scss b/ccm-cms-default-theme/src/main/scss/_custom.scss index 1f5871ef7..0516708fd 100644 --- a/ccm-cms-default-theme/src/main/scss/_custom.scss +++ b/ccm-cms-default-theme/src/main/scss/_custom.scss @@ -1,3 +1,5 @@ +$primary: #0A9793; + a.navbar-brand { max-width: 15%; } \ No newline at end of file -- 2.52.0 From ceef94b81a17254e71ba94727d50a5e83f583d93 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 12 Feb 2022 11:59:08 +0100 Subject: [PATCH 11/43] Layout for news and event list --- .../librecms/templates/index-page.html.ftl | 153 ++++++++++++------ 1 file changed, 103 insertions(+), 50 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index 17edb4f29..2de6e2522 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -2,62 +2,115 @@ <@main.librecms>
-
-
+
+
+
+
+ <#if CmsPagesCategorizedItemModel.itemAvailable> +

+ ${CmsPagesCategorizedItemModel.title} +

+

+ ${CmsPagesCategorizedItemModel.description} +

+ + Find out more + + <#else> +

+ LibreCMS +

+

+ No index item has been defined. +

+ + Find out more + + +
+
+ <#if CmsPagesCategorizedItemModel.itemAvailable> -

- ${CmsPagesCategorizedItemModel.title} -

-

- ${CmsPagesCategorizedItemModel.description} -

- - Find out more - + Category has an index item <#else> -

- LibreCMS -

-

- No index item has been defined. -

- - Find out more - + Category has no index item + +

Index page

+

This theme works.

+
+
application
+
${application}
+
themeUrl
+
${themeUrl}
+
view
+
${view!""}
+
+ +

From ArticleModel

+
+
Title
+
${CmsPagesArticleModel.title}
+
Description
+
${CmsPagesArticleModel.description}
+
Text
+
${CmsPagesArticleModel.text}
+
- <#if CmsPagesCategorizedItemModel.itemAvailable> - Category has an index item - <#else> - Category has no index item - +
+
+

News

+
    +
  • +

    +
    News 1
    +
    2022-02-12
    +

    +

    + Elit irure dolor tempor et veniam irure cillum dolore consectetur deserunt consequat. Ad commodo proident pariatur dolore. Duis occaecat culpa anim cillum. Nostrud laboris irure fugiat eu excepteur adipisicing. Non ullamco quis minim proident culpa voluptate sint incididunt. Commodo id mollit adipisicing ad. Eu laborum adipisicing anim ullamco aute proident incididunt magna aliqua. +

    +
  • +
  • +

    +
    News 2
    +
    2022-02-11
    +

    +

    + Quis officia cillum commodo velit. Ut cupidatat officia tempor veniam minim excepteur occaecat eu cillum labore. Incididunt exercitation officia enim minim et. Laborum culpa et velit consectetur sint labore proident quis reprehenderit occaecat mollit eu laboris labore. Dolor sit enim nostrud adipisicing esse culpa deserunt ipsum incididunt Lorem ipsum ipsum anim. +

    +
  • +
+
+
+

Upcoming events

+
    +
  • +

    +
    Event 1
    +
    2022-02-16 10:00
    +

    +

    + Irure culpa et sint cupidatat mollit officia id. Labore eiusmod proident ea ut officia dolor veniam aliqua pariatur pariatur. Ipsum sint consequat tempor in cillum aliquip. Est culpa irure est adipisicing eu ea qui duis in aute magna velit. Mollit laborum officia cupidatat commodo cillum. +

    +
  • +
  • +

    +
    Event 2
    +
    2022-02-25 14:00
    +

    +

    + Velit elit veniam aliquip adipisicing irure. Commodo excepteur qui amet culpa minim culpa duis ut ut esse exercitation. Sit adipisicing labore excepteur ipsum aliquip mollit irure ullamco ex incididunt ipsum aliquip commodo exercitation. Aliquip culpa reprehenderit aliqua non ea nostrud id dolore mollit laborum est officia. +

    +
  • +
+
+ -

Index page

-

This theme works.

-
-
application
-
${application}
-
themeUrl
-
${themeUrl}
-
view
-
${view!""}
-
- -

From ArticleModel

-
-
Title
-
${CmsPagesArticleModel.title}
-
Description
-
${CmsPagesArticleModel.description}
-
Text
-
${CmsPagesArticleModel.text}
-
- -

Item List

+ <#--

Item List

Item List size: ${CmsPagesItemListModel.listSize}

    <#list CmsPagesItemListModel.items as item> @@ -78,7 +131,7 @@ -
+ -->
\ No newline at end of file -- 2.52.0 From 81482c578fcab4ba3d47f633c2b4e1deef1e3a74 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Tue, 15 Feb 2022 20:06:07 +0100 Subject: [PATCH 12/43] Item list(s) are now configurable using page properties --- .../librecms/pages/models/ItemListModel.java | 173 +++++++++++------- 1 file changed, 110 insertions(+), 63 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java index 08f8a7325..bb16c7c1c 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java @@ -59,6 +59,8 @@ import org.librecms.contentsection.privileges.ItemPrivileges; import com.arsdigita.kernel.KernelConfig; +import java.util.Arrays; + /** * * @author Jens Pelzetter @@ -67,6 +69,24 @@ import com.arsdigita.kernel.KernelConfig; @Named("CmsPagesItemListModel") public class ItemListModel { + private static final String ITEM_LIST_SETTINGS_PREFIX = "itemlist"; + + private static final String LIMIT_TO_TYPE_SETTING = "limitToType"; + + private static final String LIST_ORDER_SETTING = "listOrder"; + + private static final String PAGE_SIZE_SETTING = "pageSize"; + + private static final boolean DESCENDING_DEFAULT = false; + + private static final String LIMIT_TO_TYPE_DEFAULT = ContentItem.class + .getName(); + + private static final List LIST_ORDER_DEFAULT = List + .of("displayName"); + + private static final int PAGE_SIZE_DEFAULT = 20; + @Inject private CategoryModel categoryModel; @@ -100,62 +120,12 @@ public class ItemListModel { @Inject private Shiro shiro; + @Inject + private PagePropertiesModel pagePropertiesModel; + @Inject private PageUrlModel pageUrlModel; - private boolean descending; - - private String limitToType; - - private List listOrder; - - private int pageSize; - - private List itemList; - - public ItemListModel() { - descending = false; - limitToType = ContentItem.class.getName(); - listOrder = List.of("displayName"); - pageSize = 20; - } - - public boolean isDescending() { - return descending; - } - - public void setDescending(final boolean descending) { - this.descending = descending; - } - - public String getLimitToType() { - return limitToType; - } - - public void setLimitToType(final String limitToType) { - this.limitToType = limitToType; - } - - public List getListOrder() { - return Collections.unmodifiableList(listOrder); - } - - public void setListOrder(final List listOrder) { - this.listOrder = new ArrayList<>(listOrder); - } - - public int getPageSize() { - return pageSize; - } - - public void setPageSize(final int pageSize) { - this.pageSize = pageSize; - } - - public int getFirstItem() { - return getOffset(pageSize); - } - @Transactional(Transactional.TxType.REQUIRED) public int getListSize() { return getItems().size(); @@ -163,9 +133,16 @@ public class ItemListModel { @Transactional(Transactional.TxType.REQUIRED) public List getItems() { -// if (itemList == null) { + return getItems(""); + } + + @Transactional(Transactional.TxType.REQUIRED) + public List getItems( + final String listName + ) { + return Collections.unmodifiableList( buildList( - buildLimitToType(limitToType), + buildLimitToType(getLimitToTypeSetting(listName)), collectCategories( categoryRepository .findById(categoryModel.getCategory().getCategoryId()) @@ -180,15 +157,13 @@ public class ItemListModel { ) ) ), - listOrder, - pageSize - ); -// } - - return Collections.unmodifiableList(itemList); + getListOrderSetting(listName), + getPageSizeSetting(listName) + ) + ); } - private void buildList( + private List buildList( final Class limitToType, final List categories, final List listOrder, @@ -228,7 +203,7 @@ public class ItemListModel { .collect(Collectors.toList()) ); - itemList = entityManager + return entityManager .createQuery(criteriaQuery) .getResultList() .stream() @@ -402,6 +377,78 @@ public class ItemListModel { } } + private String getLimitToTypeSetting(final String listName) { + return Optional + .ofNullable( + pagePropertiesModel + .getProperties() + .get( + buildSettingKey( + listName, + LIMIT_TO_TYPE_SETTING + ) + ) + ) + .orElse(LIMIT_TO_TYPE_DEFAULT); + } + + private List getListOrderSetting(final String listName) { + return Optional + .ofNullable( + pagePropertiesModel + .getProperties() + .get( + buildSettingKey( + listName, + LIST_ORDER_SETTING + ) + ) + ) + .map(value -> value.split(",")) + .map( + values -> Arrays + .asList(values) + .stream() + .map(String::strip) + .collect(Collectors.toList()) + ) + .orElse(LIST_ORDER_DEFAULT); + } + + private int getPageSizeSetting(final String listName) { + return Optional + .ofNullable( + pagePropertiesModel + .getProperties() + .get( + buildSettingKey( + listName, + PAGE_SIZE_SETTING + ) + ) + ) + .filter(value -> value.matches("\\d+")) + .map(value -> Integer.parseUnsignedInt(value)) + .orElse(PAGE_SIZE_DEFAULT); + } + + private String buildSettingKey( + final String listName, + final String settingKey + ) { + return List + .of( + ITEM_LIST_SETTINGS_PREFIX, + listName, + settingKey + ) + .stream() + .filter(token -> token != null && !token.isBlank()) + .collect( + Collectors.joining(".") + ); + } + private AbstractContentItemListItemModel buildListItemModel( final ContentItem contentItem ) { -- 2.52.0 From fb285f7a29aa68926c9b977f27c619ed79a5a438 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Wed, 16 Feb 2022 18:37:00 +0100 Subject: [PATCH 13/43] Page parameter of item list is now aware of different lists --- .../librecms/pages/models/ItemListModel.java | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java index bb16c7c1c..f30c827a6 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java @@ -60,6 +60,7 @@ import org.librecms.contentsection.privileges.ItemPrivileges; import com.arsdigita.kernel.KernelConfig; import java.util.Arrays; +import java.util.stream.Stream; /** * @@ -87,6 +88,8 @@ public class ItemListModel { private static final int PAGE_SIZE_DEFAULT = 20; + private static final String PAGE_PARAM_NAME = "page"; + @Inject private CategoryModel categoryModel; @@ -158,7 +161,8 @@ public class ItemListModel { ) ), getListOrderSetting(listName), - getPageSizeSetting(listName) + getPageSizeSetting(listName), + getOffset(listName, getPageSizeSetting(listName)) ) ); } @@ -167,7 +171,8 @@ public class ItemListModel { final Class limitToType, final List categories, final List listOrder, - final int pageSize + final int pageSize, + final int offset ) { final CriteriaBuilder criteriaBuilder = entityManager .getCriteriaBuilder(); @@ -212,7 +217,7 @@ public class ItemListModel { item, globalizationHelper.getNegotiatedLocale() ) ) - .skip(getOffset(pageSize)) + .skip(offset) .limit(pageSize) .map(this::buildListItemModel) .collect(Collectors.toList()); @@ -362,16 +367,36 @@ public class ItemListModel { } } - private int getOffset(final int pageSize) { - if (pageUrlModel.getQueryParameters().containsKey("page")) { - final String value = pageUrlModel.getQueryParameters().get("page"); - if (value.matches("\\d*")) { - final int page = Integer.valueOf(value); + private int getOffset(final String listName, final int pageSize) { + final String pageParamName = Stream + .of(listName, PAGE_PARAM_NAME) + .filter(token -> token != null && !token.isBlank()) + .collect( + Collectors.joining(".") + ); - return page * pageSize; - } else { - return 0; - } + if (pageUrlModel.getQueryParameters().containsKey(pageParamName)) { + return calculateOffset(pageParamName, pageSize); + } else if (pageUrlModel.getQueryParameters().containsKey(PAGE_PARAM_NAME)) { + return calculateOffset(PAGE_PARAM_NAME, pageSize); + } else { + return 0; + } + } + + private int calculateOffset( + final String pageParamName, + final int pageSize + ) { + return parsePageParam(pageParamName) * pageSize; + } + + private int parsePageParam(final String pageParamName) { + final String value = pageUrlModel + .getQueryParameters() + .get(pageParamName); + if (value.matches("\\d+")) { + return Integer.parseUnsignedInt(value); } else { return 0; } @@ -436,13 +461,12 @@ public class ItemListModel { final String listName, final String settingKey ) { - return List + return Stream .of( ITEM_LIST_SETTINGS_PREFIX, listName, settingKey ) - .stream() .filter(token -> token != null && !token.isBlank()) .collect( Collectors.joining(".") -- 2.52.0 From 47e26b5878d4553e7d30646eeff5e264f6f9a0c6 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Wed, 16 Feb 2022 20:20:05 +0100 Subject: [PATCH 14/43] Several small things for the default and item lists. --- .../librecms/templates/index-page.html.ftl | 63 +++++++++++++++-- .../src/main/scss/_custom.scss | 4 ++ .../librecms/pages/models/ItemListModel.java | 67 +++++++++++++------ .../models/NewsListItemModelBuilder.java | 5 +- .../java/org/librecms/ui/PagesController.java | 2 +- .../org/librecms/ui/cms/page-details.xhtml | 2 +- .../org/librecms/CmsAdminMessages.properties | 2 +- .../librecms/CmsAdminMessages_de.properties | 2 +- 8 files changed, 115 insertions(+), 32 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index 2de6e2522..28fec6cbb 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -64,8 +64,17 @@

News

-
    -
  • +
      + <#list CmsPagesItemListModel.getItems("newslist") as news> +
    • +

      +
      ${news.title}
      +
      ${news.releaseDateAsString}
      +

      +

      ${news.description}

      +
    • + + <#--
    • News 1
      2022-02-12
      @@ -82,7 +91,7 @@

      Quis officia cillum commodo velit. Ut cupidatat officia tempor veniam minim excepteur occaecat eu cillum labore. Incididunt exercitation officia enim minim et. Laborum culpa et velit consectetur sint labore proident quis reprehenderit occaecat mollit eu laboris labore. Dolor sit enim nostrud adipisicing esse culpa deserunt ipsum incididunt Lorem ipsum ipsum anim.

      -

    • + -->
@@ -110,8 +119,18 @@
- <#--

Item List

+

Item List

Item List size: ${CmsPagesItemListModel.listSize}

+
+
Item List size:
+
${CmsPagesItemListModel.listSize}
+
Page size
+
${CmsPagesItemListModel.pageSize}
+
Page
+
${CmsPagesItemListModel.page}
+
Offset
+
${CmsPagesItemListModel.offset}
+
    <#list CmsPagesItemListModel.items as item>
  • @@ -131,7 +150,41 @@
  • -
--> + +
+ +

News List

+

News List size: ${CmsPagesItemListModel.getListSize("newslist")}

+
+
Item List size:
+
${CmsPagesItemListModel.getListSize("newslist")}
+
Page size
+
${CmsPagesItemListModel.getPageSize("newslist")}
+
Page
+
${CmsPagesItemListModel.getPage("newslist")}
+
Offset
+
${CmsPagesItemListModel.getOffset("newslist")}
+
+
    + <#list CmsPagesItemListModel.getItems("newslist") as item> +
  • +
    +
    UUID
    +
    ${item.uuid}
    +
    displayName
    +
    ${item.displayName}
    +
    Name
    +
    ${item.name}
    +
    Title
    +
    ${item.title}
    +
    description
    +
    ${item.description}
    +
    Type
    +
    ${item.type}
    +
    +
  • + +
\ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/scss/_custom.scss b/ccm-cms-default-theme/src/main/scss/_custom.scss index 0516708fd..fea343d9f 100644 --- a/ccm-cms-default-theme/src/main/scss/_custom.scss +++ b/ccm-cms-default-theme/src/main/scss/_custom.scss @@ -2,4 +2,8 @@ $primary: #0A9793; a.navbar-brand { max-width: 15%; +} + +.item-description { + white-space: pre; } \ No newline at end of file diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java index f30c827a6..c9de261ee 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ItemListModel.java @@ -131,7 +131,50 @@ public class ItemListModel { @Transactional(Transactional.TxType.REQUIRED) public int getListSize() { - return getItems().size(); + return getListSize(""); + } + + @Transactional(Transactional.TxType.REQUIRED) + public int getListSize(final String listName) { + return getItems(listName).size(); + } + + public int getPageSize() { + return getPageSize(""); + } + + public int getPageSize(final String listName) { + return getPageSizeSetting(listName); + } + + public int getOffset() { + return getOffset(""); + } + + public int getOffset(final String listName) { + return getOffset(listName, getPageSize(listName)); + } + + public int getPage() { + return getPage(""); + } + + public int getPage(final String listName) { + final String pageParamName = Stream + .of(listName, PAGE_PARAM_NAME) + .filter(token -> token != null && !token.isBlank()) + .collect( + Collectors.joining(".") + ); + + if (pageUrlModel.getQueryParameters().containsKey(pageParamName)) { + return parsePageParam(pageParamName); + } else if (pageUrlModel.getQueryParameters() + .containsKey(PAGE_PARAM_NAME)) { + return parsePageParam(pageParamName); + } else { + return 0; + } } @Transactional(Transactional.TxType.REQUIRED) @@ -368,27 +411,7 @@ public class ItemListModel { } private int getOffset(final String listName, final int pageSize) { - final String pageParamName = Stream - .of(listName, PAGE_PARAM_NAME) - .filter(token -> token != null && !token.isBlank()) - .collect( - Collectors.joining(".") - ); - - if (pageUrlModel.getQueryParameters().containsKey(pageParamName)) { - return calculateOffset(pageParamName, pageSize); - } else if (pageUrlModel.getQueryParameters().containsKey(PAGE_PARAM_NAME)) { - return calculateOffset(PAGE_PARAM_NAME, pageSize); - } else { - return 0; - } - } - - private int calculateOffset( - final String pageParamName, - final int pageSize - ) { - return parsePageParam(pageParamName) * pageSize; + return getPage(listName) * pageSize; } private int parsePageParam(final String pageParamName) { diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java index f16346c99..2f478b5c7 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java @@ -21,6 +21,7 @@ package org.librecms.pages.models; import org.librecms.contenttypes.News; import java.time.LocalDateTime; +import java.time.ZoneId; import javax.enterprise.context.RequestScoped; @@ -48,7 +49,9 @@ public class NewsListItemModelBuilder ) { super.addProperties(news, model); model.setReleaseDate( - LocalDateTime.from(news.getReleaseDate().toInstant()) + LocalDateTime.from( + news.getReleaseDate().toInstant().atZone(ZoneId.systemDefault()) + ) ); } diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesController.java b/ccm-cms/src/main/java/org/librecms/ui/PagesController.java index 61f500282..e3d7e741f 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/PagesController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesController.java @@ -515,7 +515,7 @@ public class PagesController { return showPageDetails(pagesInstance, categoryParam); } - if (!propertyKey.matches("^([a-z0-9-_]*)$")) { + if (!propertyKey.matches("^([a-zA-Z0-9-_\\.]*)$")) { models.put("propertyKeyInvalid", true); return showPageDetails(pagesInstance, categoryParam); } diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/cms/page-details.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/cms/page-details.xhtml index 8fe2df6a2..7c703d971 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/cms/page-details.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/cms/page-details.xhtml @@ -155,7 +155,7 @@ class="form-control" id="property-key" name="propertyKey" - pattern="^([a-zA-Z0-9-_]*)$" + pattern="^([a-zA-Z0-9-_\.]*)$" required="true" type="text" /> Date: Sat, 19 Feb 2022 11:51:21 +0100 Subject: [PATCH 15/43] Added reference to negotiated locale to models, used to format dates. --- .../models/AbstractContentItemListItemModel.java | 16 ++++++++++++++++ .../AbstractContentItemListItemModelBuilder.java | 2 ++ .../pages/models/EventListItemModel.java | 16 ++++++++++++++++ .../org/librecms/pages/models/ItemListModel.java | 5 ++++- .../librecms/pages/models/NewsListItemModel.java | 16 ++++++++++++++++ .../pages/models/NewsListItemModelBuilder.java | 1 + 6 files changed, 55 insertions(+), 1 deletion(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java index f2af5b253..64b7c612b 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java @@ -18,6 +18,8 @@ */ package org.librecms.pages.models; +import java.util.Locale; + /** * A simplified representation of a content item for use in a list of content * items.Base class for other more specific models. @@ -26,6 +28,12 @@ package org.librecms.pages.models; */ public abstract class AbstractContentItemListItemModel { + /** + * The locale negotiated with the user agent. Useful for example for + * formatting date. Only for internal use. + */ + private Locale locale; + private String uuid; private String displayName; @@ -35,6 +43,14 @@ public abstract class AbstractContentItemListItemModel { private String title; private String description; + + protected Locale getLocale() { + return locale; + } + + protected void setLocale(final Locale locale) { + this.locale = locale; + } public String getUuid() { return uuid; diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java index 39c58ae8f..35cda60d1 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java @@ -39,6 +39,8 @@ public abstract class AbstractContentItemListItemModelBuilder getItems( final String listName ) { - return Collections.unmodifiableList( + final List items + = Collections.unmodifiableList( buildList( buildLimitToType(getLimitToTypeSetting(listName)), collectCategories( @@ -208,6 +209,8 @@ public class ItemListModel { getOffset(listName, getPageSizeSetting(listName)) ) ); + + return items; } private List buildList( diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModel.java index b61ddac57..ecf84bb3f 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModel.java @@ -36,6 +36,22 @@ public class NewsListItemModel extends AbstractContentItemListItemModel { return releaseDate; } + /** + * Returns the release date of the news represeted by this model formatted + * using the provided pattern. The pattern MUST be a valid pattern for + * {@link DateTimeFormatter#ofPattern(java.lang.String) }. + * + * @param pattern The pattern to use for formatting the release date. + * + * @return The formatted release date. + */ + public String getReleaseDate(final String pattern) { + return DateTimeFormatter + .ofPattern(pattern, getLocale()) + .withZone(ZoneId.systemDefault()) + .format(releaseDate); + } + public String getReleaseDateAsString() { return DateTimeFormatter.ISO_DATE_TIME .withZone(ZoneId.systemDefault()) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java index 2f478b5c7..b3e91c4e7 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java @@ -18,6 +18,7 @@ */ package org.librecms.pages.models; +import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contenttypes.News; import java.time.LocalDateTime; -- 2.52.0 From 80729ed936e6c0cdaa6d7410eacb6fed66003c0f Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 19 Feb 2022 11:51:53 +0100 Subject: [PATCH 16/43] Template for start page cleaned up --- .../librecms/templates/index-page.html.ftl | 96 +++++++------------ 1 file changed, 37 insertions(+), 59 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index 28fec6cbb..c69b489b3 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -32,7 +32,7 @@
- <#if CmsPagesCategorizedItemModel.itemAvailable> + <#-- <#if CmsPagesCategorizedItemModel.itemAvailable> Category has an index item <#else> Category has no index item @@ -58,68 +58,46 @@
Text
${CmsPagesArticleModel.text}
- + --> -
-
-

News

-
    - <#list CmsPagesItemListModel.getItems("newslist") as news> -
  • -

    -
    ${news.title}
    -
    ${news.releaseDateAsString}
    -

    -

    ${news.description}

    -
  • - - <#--
  • -

    -
    News 1
    -
    2022-02-12
    -

    -

    - Elit irure dolor tempor et veniam irure cillum dolore consectetur deserunt consequat. Ad commodo proident pariatur dolore. Duis occaecat culpa anim cillum. Nostrud laboris irure fugiat eu excepteur adipisicing. Non ullamco quis minim proident culpa voluptate sint incididunt. Commodo id mollit adipisicing ad. Eu laborum adipisicing anim ullamco aute proident incididunt magna aliqua. -

    -
  • -
  • -

    -
    News 2
    -
    2022-02-11
    -

    -

    - Quis officia cillum commodo velit. Ut cupidatat officia tempor veniam minim excepteur occaecat eu cillum labore. Incididunt exercitation officia enim minim et. Laborum culpa et velit consectetur sint labore proident quis reprehenderit occaecat mollit eu laboris labore. Dolor sit enim nostrud adipisicing esse culpa deserunt ipsum incididunt Lorem ipsum ipsum anim. -

    -
  • --> -
-
-
-

Upcoming events

-
    -
  • -

    -
    Event 1
    -
    2022-02-16 10:00
    -

    -

    - Irure culpa et sint cupidatat mollit officia id. Labore eiusmod proident ea ut officia dolor veniam aliqua pariatur pariatur. Ipsum sint consequat tempor in cillum aliquip. Est culpa irure est adipisicing eu ea qui duis in aute magna velit. Mollit laborum officia cupidatat commodo cillum. -

    -
  • -
  • -

    -
    Event 2
    -
    2022-02-25 14:00
    -

    -

    - Velit elit veniam aliquip adipisicing irure. Commodo excepteur qui amet culpa minim culpa duis ut ut esse exercitation. Sit adipisicing labore excepteur ipsum aliquip mollit irure ullamco ex incididunt ipsum aliquip commodo exercitation. Aliquip culpa reprehenderit aliqua non ea nostrud id dolore mollit laborum est officia. -

    -
  • -
+
+ <#list CmsPagesItemListModel.getItems("newslist")> +
+

News

+
    + <#items as news> +
  • +

    +
    ${news.title}
    +
    ${news.getReleaseDate('yyyy-MM-dd')}
    +

    +

    ${news.description}

    +
  • + +
+
+ + <#list CmsPagesItemListModel.getItems("eventlist")> +
+

Upcoming events

+
    + <#items as event> +
  • +

    +
    ${event.title}
    +
    ${event.getStartDate('yyyy-MM-dd hh:mm')}
    +

    +

    ${event.description}

    +
  • + +
+
+
-

Item List

+ <#--

Item List

Item List size: ${CmsPagesItemListModel.listSize}

Item List size:
@@ -185,6 +163,6 @@ -
+ --> \ No newline at end of file -- 2.52.0 From 6332243d2d24ccbf99b723bc29f25dfacb38c137 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 19 Feb 2022 17:43:05 +0100 Subject: [PATCH 17/43] Bugfix for handling LocalDateTime in EventListItemModelBuilder --- .../pages/models/EventListItemModelBuilder.java | 13 +++++++++++-- .../pages/models/NewsListItemModelBuilder.java | 1 - 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/EventListItemModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/EventListItemModelBuilder.java index f1e1636ef..3b3e2c7de 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/EventListItemModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/EventListItemModelBuilder.java @@ -22,6 +22,7 @@ import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contenttypes.Event; import java.time.LocalDateTime; +import java.time.ZoneId; import javax.inject.Inject; @@ -50,13 +51,21 @@ public class EventListItemModelBuilder final Event event, final EventListItemModel model ) { super.addProperties(event, model); - model.setEndDate(LocalDateTime.from(event.getEndDate().toInstant())); + model.setEndDate( + LocalDateTime.from( + event.getEndDate().toInstant().atZone(ZoneId.systemDefault()) + ) + ); model.setLocation( globalizationHelper.getValueFromLocalizedString( event.getLocation() ) ); - model.setStartDate(LocalDateTime.from(event.getStartDate().toInstant())); + model.setStartDate( + LocalDateTime.from( + event.getStartDate().toInstant().atZone(ZoneId.systemDefault()) + ) + ); } } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java index b3e91c4e7..2f478b5c7 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsListItemModelBuilder.java @@ -18,7 +18,6 @@ */ package org.librecms.pages.models; -import org.libreccm.l10n.GlobalizationHelper; import org.librecms.contenttypes.News; import java.time.LocalDateTime; -- 2.52.0 From ff27e7e494548681dea215fb669a8a91dfb64e25 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 19 Feb 2022 17:43:39 +0100 Subject: [PATCH 18/43] Nicer date formatting --- .../resources/themes/librecms/templates/index-page.html.ftl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index c69b489b3..df9a06edc 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -70,7 +70,8 @@
  • ${news.title}
    -
    ${news.getReleaseDate('yyyy-MM-dd')}
    + <#--
    ${news.getReleaseDate('yyyy-MM-dd')}
    --> +
    ${news.getReleaseDate('dd. MMM yyyy')}

    ${news.description}

  • @@ -86,7 +87,7 @@
  • ${event.title}
    -
    ${event.getStartDate('yyyy-MM-dd hh:mm')}
    +
    ${event.getStartDate('dd. MMM yyyy HH:mm')}

    ${event.description}

  • -- 2.52.0 From ddb4f685f95990bc7074fb576a23ce0707406228 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Mon, 21 Feb 2022 20:29:27 +0100 Subject: [PATCH 19/43] Some bugfixes for the category administration. --- .../ui/contentsections/CategoriesController.java | 12 +++++++++--- .../categorysystems/categorysystem.xhtml | 15 +++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java index 32a66c48e..9dfe35103 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java @@ -820,12 +820,18 @@ public class CategoriesController { category.setAbstractCategory(Objects.equals("true", isAbstract)); categoryRepo.save(category); +// return String.format( +// "redirect:/%s/categorysystems/%s/categories/%s/%s", +// sectionIdentifier, +// context, +// categoryManager.getCategoryPath(category.getParentCategory()), +// categoryName +// ); return String.format( - "redirect:/%s/categorysystems/%s/categories/%s/%s", + "redirect:/%s/categorysystems/%s/categories/%s", sectionIdentifier, context, - categoryManager.getCategoryPath(category.getParentCategory()), - categoryName + categoryManager.getCategoryPath(category) ); } else { return result.getFailedResponseTemplate(); diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml index 0eb11b699..12227992b 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml @@ -154,18 +154,21 @@ pattern="[\\w-.]*" required="true" value="#{CategorySystemModel.selectedCategory.uniqueId}" /> - - + - + + value="true" />

    Et ut ea adipisicing irure mollit excepteur proident labore velit sint ex ipsum irure duis. Do irure do irure officia consectetur est. Nulla proident sit cillum veniam excepteur sint est culpa quis voluptate nostrud nulla. Minim incididunt dolor quis ullamco eu pariatur sunt deserunt aliquip elit cupidatat minim. Ipsum sunt dolore non anim minim et amet est aute. diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl index 7e03d4ac8..3bad7aaa2 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl @@ -44,6 +44,7 @@

    <#nested>
    + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/scss/_custom.scss b/ccm-cms-default-theme/src/main/scss/_custom.scss index fea343d9f..dd5d1895c 100644 --- a/ccm-cms-default-theme/src/main/scss/_custom.scss +++ b/ccm-cms-default-theme/src/main/scss/_custom.scss @@ -4,6 +4,12 @@ a.navbar-brand { max-width: 15%; } +.imgbox-button { + background-color: transparent; + border: none; + padding: 0; +} + .item-description { white-space: pre; } \ No newline at end of file -- 2.52.0 From 950421774cd6a74d01c527a3264adbd26459acc5 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Wed, 23 Feb 2022 20:45:54 +0100 Subject: [PATCH 22/43] Template for Article and News details view --- .../themes/librecms/templates/category-page.html.ftl | 10 ++++++++-- .../org.librecms.contenttypes.Article.html.ftl | 8 ++++++++ .../org.librecms.contenttypes.News.html.ftl | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl index 05f8ecb84..e7b6e46a4 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl @@ -1,10 +1,16 @@ <#import "./main.html.ftl" as main> +<#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> <@main.librecms>
    -

    Index Item Title

    + <@contentitem.details /> + <#--

    Index Item Title ${CmsPagesCategorizedItemModel.title}

    +
    +CmsPagesContentItemTypeModel.displayName = ${CmsPagesContentItemTypeModel.displayName}
    +CmsPagesContentItemTypeModel.itemClass = ${CmsPagesContentItemTypeModel.itemClass}
    +

    Enim pariatur esse nisi commodo cupidatat dolor reprehenderit commodo. Nulla mollit officia dolore ipsum elit irure excepteur ex excepteur est non aliqua. Tempor est amet id occaecat deserunt ea adipisicing laborum tempor exercitation dolor ex quis laboris. Nulla quis sit exercitation ex sunt ipsum adipisicing consequat mollit sunt. Ea fugiat commodo ullamco reprehenderit non. Ea laborum aute non ex Lorem sint anim. In sunt sit laboris amet ipsum tempor officia incididunt eu nostrud voluptate labore veniam. @@ -143,7 +149,7 @@

    Ut ut excepteur enim exercitation mollit cillum id sit magna. Ullamco ullamco do reprehenderit nisi consequat. Id dolore eu laborum ex ipsum fugiat veniam id incididunt aliquip proident nulla commodo. Officia deserunt consequat in id ex sit. Lorem nostrud officia culpa enim labore id sit. -

    +

    -->
    diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl new file mode 100644 index 000000000..7ff408349 --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl @@ -0,0 +1,8 @@ +<#macro details> +

    ${CmsPagesCategorizedItemModel.title}

    +

    ${CmsPagesCategorizedItemModel.description

    + +
    + ${CmsPagesArticleModel.text} +
    + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl new file mode 100644 index 000000000..b819394a1 --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl @@ -0,0 +1,8 @@ +<@macro details> +

    ${CmsPagesCategorizedItemModel.title}

    +

    ${CmsPagesCategorizedItemModel.description}

    + +
    + ${CmsPagesNewsModel.text} +
    + \ No newline at end of file -- 2.52.0 From fcf62c0c9d1d1ea13be793571a15a200f8a57e40 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Wed, 23 Feb 2022 20:46:09 +0100 Subject: [PATCH 23/43] Provide formattable news data in model. --- .../pages/models/ContentItemTypeModel.java | 27 ++++++++-- .../org/librecms/pages/models/NewsModel.java | 49 ++++++++++++++----- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java index e17c42f2e..16da29dde 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemTypeModel.java @@ -18,10 +18,6 @@ */ package org.librecms.pages.models; -import org.libreccm.l10n.GlobalizationHelper; -import org.librecms.contentsection.ContentItem; -import org.librecms.contentsection.ContentType; - import java.util.Optional; import javax.enterprise.context.RequestScoped; @@ -29,6 +25,10 @@ import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentType; + /** * MVC model for retrieving information about the content type of the current * content item. If there is no current content item, the methods of this model @@ -69,6 +69,14 @@ public class ContentItemTypeModel implements ProcessesContentItem { .orElse(""); } + public String getItemClass() { + contentItemModel.init(); + + return contentType + .map(ContentItemTypeModelData::getItemClass) + .orElse(""); + } + public String getDisplayName() { contentItemModel.init(); @@ -114,6 +122,7 @@ public class ContentItemTypeModel implements ProcessesContentItem { ) ); data.setDisplayName(type.getDisplayName()); + data.setItemClass(type.getContentItemClass()); data.setLabel( globalizationHelper.getValueFromLocalizedString( type.getLabel() @@ -131,6 +140,8 @@ public class ContentItemTypeModel implements ProcessesContentItem { private String uuid; + private String itemClass; + private String displayName; private String label; @@ -153,6 +164,14 @@ public class ContentItemTypeModel implements ProcessesContentItem { this.uuid = uuid; } + public String getItemClass() { + return itemClass; + } + + public void setItemClass(final String itemClass) { + this.itemClass = itemClass; + } + public String getDisplayName() { return displayName; } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java index 426a9aef7..60123d968 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java @@ -18,13 +18,9 @@ */ package org.librecms.pages.models; -import org.libreccm.l10n.GlobalizationHelper; -import org.librecms.contentsection.ContentItem; -import org.librecms.contenttypes.News; - +import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.Date; import java.util.Optional; import javax.enterprise.context.RequestScoped; @@ -32,6 +28,10 @@ import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.contentsection.ContentItem; +import org.librecms.contenttypes.News; + /** * * @author Jens Pelzetter @@ -56,7 +56,7 @@ public class NewsModel implements ProcessesContentItem { private String text; - private String releaseDateTime; + private LocalDateTime releaseDateTime; private boolean homepage; @@ -88,12 +88,34 @@ public class NewsModel implements ProcessesContentItem { } @Transactional(Transactional.TxType.REQUIRED) - public String getReleaseDateTime() { + public LocalDateTime getReleaseDateTime() { contentItemModel.init(); return releaseDateTime; } + /** + * Returns the release date of the news represeted by this model formatted + * using the provided pattern. The pattern MUST be a valid pattern for + * {@link DateTimeFormatter#ofPattern(java.lang.String) }. + * + * @param pattern The pattern to use for formatting the release date. + * + * @return The formatted release date. + */ + public String getReleaseDate(final String pattern) { + return DateTimeFormatter + .ofPattern(pattern, globalizationHelper.getNegotiatedLocale()) + .withZone(ZoneId.systemDefault()) + .format(releaseDateTime); + } + + public String getReleaseDateTimeAsString() { + return DateTimeFormatter.ISO_DATE_TIME + .withZone(ZoneId.systemDefault()) + .format(releaseDateTime); + } + @Transactional(Transactional.TxType.REQUIRED) public boolean getHomepage() { contentItemModel.init(); @@ -123,11 +145,14 @@ public class NewsModel implements ProcessesContentItem { .ofNullable(news.getText()) .map(globalizationHelper::getValueFromLocalizedString) .orElse(""); - releaseDateTime = Optional - .ofNullable(news.getReleaseDate()) - .map(Date::toInstant) - .map(isoDateTimeFormatter::format) - .orElse(""); + releaseDateTime = LocalDateTime.from( + news.getReleaseDate().toInstant().atZone(ZoneId.systemDefault()) + ); + // releaseDateTime = Optional + // .ofNullable(news.getReleaseDate()) + // .map(Date::toInstant) + // .map(isoDateTimeFormatter::format) + // .orElse(""); homepage = news.isHomepage(); } -- 2.52.0 From b034d7d3213892d90afa5652900d96c821d7bf7d Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 24 Feb 2022 20:29:46 +0100 Subject: [PATCH 24/43] Some improvments for item display --- .../themes/librecms/templates/category-page.html.ftl | 12 ++++++++++-- .../librecms/templates/contentitems/default.html.ftl | 4 ++++ .../org.librecms.contenttypes.Article.html.ftl | 2 +- .../org.librecms.contenttypes.News.html.ftl | 5 +++-- 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl index e7b6e46a4..52bf67517 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl @@ -1,11 +1,19 @@ <#import "./main.html.ftl" as main> -<#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> +<#-- <#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> --> <@main.librecms>
    - <@contentitem.details /> + <#if CmsPagesContentItemTypeModel.itemClass != ""> + <#assign itemTemplate = .getOptionalTemplate("./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl")> + <#if itemTemplate.exists> + <#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> + <#else> + <#import "./contentitems/default.html.ftl" as contentitem> + + <@contentitem.details /> + <#--

    Index Item Title ${CmsPagesCategorizedItemModel.title}

     CmsPagesContentItemTypeModel.displayName = ${CmsPagesContentItemTypeModel.displayName}
    diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl
    new file mode 100644
    index 000000000..2aa26531a
    --- /dev/null
    +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl
    @@ -0,0 +1,4 @@
    +<#macro details>
    +    

    ${CmsPagesCategorizedItemModel.title}

    +

    ${CmsPagesCategorizedItemModel.description}

    + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl index 7ff408349..6d2e6da2c 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl @@ -1,6 +1,6 @@ <#macro details>

    ${CmsPagesCategorizedItemModel.title}

    -

    ${CmsPagesCategorizedItemModel.description

    +

    ${CmsPagesCategorizedItemModel.description}

    ${CmsPagesArticleModel.text} diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl index b819394a1..4f4fd9336 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl @@ -1,8 +1,9 @@ -<@macro details> +<#macro details>

    ${CmsPagesCategorizedItemModel.title}

    +
    ${CmsPagesNewsModel.getReleaseDate('yyyy-MM-dd')}

    ${CmsPagesCategorizedItemModel.description}

    ${CmsPagesNewsModel.text}
    - \ No newline at end of file + \ No newline at end of file -- 2.52.0 From ae2d3b57eaf9b9241ed6ea9f5438164c9ae3e841 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 14:54:13 +0100 Subject: [PATCH 25/43] Get start and end date time of an event formatted using a pattern --- .../org/librecms/pages/models/EventModel.java | 118 +++++++++++++++--- 1 file changed, 99 insertions(+), 19 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java index 3e9562130..ad9bc92d7 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/EventModel.java @@ -18,13 +18,9 @@ */ package org.librecms.pages.models; -import org.libreccm.l10n.GlobalizationHelper; -import org.librecms.contentsection.ContentItem; -import org.librecms.contenttypes.Event; - +import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.Date; import java.util.Optional; import javax.enterprise.context.RequestScoped; @@ -32,6 +28,10 @@ import javax.inject.Inject; import javax.inject.Named; import javax.transaction.Transactional; +import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.contentsection.ContentItem; +import org.librecms.contenttypes.Event; + /** * * @author Jens Pelzetter @@ -48,15 +48,13 @@ public class EventModel implements ProcessesContentItem { private boolean initialized; - private final DateTimeFormatter isoDateTimeFormatter; - private String title; private String text; - private String startDateTime; + private LocalDateTime startDateTime; - private String endDateTime; + private LocalDateTime endDateTime; private String eventDate; @@ -66,8 +64,6 @@ public class EventModel implements ProcessesContentItem { public EventModel() { initialized = false; - isoDateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME - .withZone(ZoneId.systemDefault()); } @Transactional(Transactional.TxType.REQUIRED) @@ -85,19 +81,97 @@ public class EventModel implements ProcessesContentItem { } @Transactional(Transactional.TxType.REQUIRED) - public String getStartDateTime() { + public LocalDateTime getStartDateTime() { contentItemModel.init(); return startDateTime; } + /** + * Returns the start date of the event represented by this model formatted + * using the provided pattern. The pattern MUST be a valid pattern for + * {@link DateTimeFormatter#ofPattern(java.lang.String) }. + * + * @param pattern The pattern to use for formatting the release date. + * + * @return The formatted release date. + */ + public String getStartDateTime(final String pattern) { + contentItemModel.init(); + + return Optional + .ofNullable(startDateTime) + .map( + dateTime -> DateTimeFormatter + .ofPattern( + pattern, + globalizationHelper.getNegotiatedLocale() + ) + .withZone(ZoneId.systemDefault()) + .format(dateTime) + ) + .orElse(""); + } + + public String getStartDateTimeAsString() { + contentItemModel.init(); + + return Optional + .ofNullable(endDateTime) + .map( + dateTime -> DateTimeFormatter.ISO_DATE_TIME + .withZone(ZoneId.systemDefault()) + .format(dateTime) + ) + .orElse(""); + } + @Transactional(Transactional.TxType.REQUIRED) - public String getEndDateTime() { + public LocalDateTime getEndDateTime() { contentItemModel.init(); return endDateTime; } + /** + * Returns the end date of the event represented by this model formatted + * using the provided pattern. The pattern MUST be a valid pattern for + * {@link DateTimeFormatter#ofPattern(java.lang.String) }. + * + * @param pattern The pattern to use for formatting the release date. + * + * @return The formatted release date. + */ + public String getEndDateTime(final String pattern) { + contentItemModel.init(); + + return Optional + .ofNullable(endDateTime) + .map( + dateTime -> DateTimeFormatter + .ofPattern( + pattern, + globalizationHelper.getNegotiatedLocale() + ) + .withZone(ZoneId.systemDefault()) + .format(dateTime) + ) + .orElse(""); + } + + public String getEndDateTimeAsString() { + contentItemModel.init(); + + return Optional + .ofNullable(endDateTime) + .map( + dateTime -> DateTimeFormatter.ISO_DATE_TIME + .withZone(ZoneId.systemDefault()) + .format(dateTime) + ) + .orElse(""); + } + @Transactional(Transactional.TxType.REQUIRED) public String getEventDate() { contentItemModel.init(); @@ -139,14 +213,20 @@ public class EventModel implements ProcessesContentItem { .orElse(""); startDateTime = Optional .ofNullable(event.getStartDate()) - .map(Date::toInstant) - .map(isoDateTimeFormatter::format) - .orElse(""); + .map( + startDate -> LocalDateTime.from( + startDate.toInstant().atZone(ZoneId.systemDefault()) + ) + ) + .orElse(null); endDateTime = Optional .ofNullable(event.getEndDate()) - .map(Date::toInstant) - .map(isoDateTimeFormatter::format) - .orElse(""); + .map( + endDate -> LocalDateTime.from( + endDate.toInstant().atZone(ZoneId.systemDefault()) + ) + ) + .orElse(null); eventDate = Optional .ofNullable(event.getEventDate()) .map(globalizationHelper::getValueFromLocalizedString) -- 2.52.0 From 6753d96ce2f241f70063da4400e64bec8402a5df Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 14:54:36 +0100 Subject: [PATCH 26/43] Making NewsModel a bit more null-safe. --- .../org/librecms/pages/models/NewsModel.java | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java index 60123d968..a4359e327 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/NewsModel.java @@ -94,8 +94,8 @@ public class NewsModel implements ProcessesContentItem { return releaseDateTime; } - /** - * Returns the release date of the news represeted by this model formatted + /** + * Returns the release date of the news represented by this model formatted * using the provided pattern. The pattern MUST be a valid pattern for * {@link DateTimeFormatter#ofPattern(java.lang.String) }. * @@ -104,16 +104,29 @@ public class NewsModel implements ProcessesContentItem { * @return The formatted release date. */ public String getReleaseDate(final String pattern) { - return DateTimeFormatter - .ofPattern(pattern, globalizationHelper.getNegotiatedLocale()) - .withZone(ZoneId.systemDefault()) - .format(releaseDateTime); + return Optional + .ofNullable(releaseDateTime) + .map( + dateTime -> DateTimeFormatter + .ofPattern( + pattern, + globalizationHelper.getNegotiatedLocale() + ) + .withZone(ZoneId.systemDefault()) + .format(dateTime) + ) + .orElse(""); } public String getReleaseDateTimeAsString() { - return DateTimeFormatter.ISO_DATE_TIME - .withZone(ZoneId.systemDefault()) - .format(releaseDateTime); + return Optional + .ofNullable(releaseDateTime) + .map( + dateTime -> DateTimeFormatter.ISO_DATE_TIME + .withZone(ZoneId.systemDefault()) + .format(dateTime) + ) + .orElse(""); } @Transactional(Transactional.TxType.REQUIRED) @@ -145,14 +158,14 @@ public class NewsModel implements ProcessesContentItem { .ofNullable(news.getText()) .map(globalizationHelper::getValueFromLocalizedString) .orElse(""); - releaseDateTime = LocalDateTime.from( - news.getReleaseDate().toInstant().atZone(ZoneId.systemDefault()) - ); - // releaseDateTime = Optional - // .ofNullable(news.getReleaseDate()) - // .map(Date::toInstant) - // .map(isoDateTimeFormatter::format) - // .orElse(""); + releaseDateTime = Optional + .ofNullable(news.getReleaseDate()) + .map( + date -> LocalDateTime.from( + date.toInstant().atZone(ZoneId.systemDefault()) + ) + ) + .orElse(null); homepage = news.isHomepage(); } -- 2.52.0 From 4732c450126c16413e9971ce9d401e92f35d431c Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 14:54:56 +0100 Subject: [PATCH 27/43] Added display of release date of news --- .../org.librecms.contenttypes.News.html.ftl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl index 4f4fd9336..8d18d9b4f 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.News.html.ftl @@ -1,6 +1,12 @@ <#macro details> -

    ${CmsPagesCategorizedItemModel.title}

    -
    ${CmsPagesNewsModel.getReleaseDate('yyyy-MM-dd')}
    +
    +

    + ${CmsPagesCategorizedItemModel.title} + + ${CmsPagesNewsModel.getReleaseDate('yyyy-MM-dd')} + +

    +

    ${CmsPagesCategorizedItemModel.description}

    -- 2.52.0 From 5803e9b024d783042c3600398e3062169670b0e8 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 14:55:13 +0100 Subject: [PATCH 28/43] Added warning for missing template for content type --- .../themes/librecms/templates/contentitems/default.html.ftl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl index 2aa26531a..0f34ea715 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/default.html.ftl @@ -1,4 +1,7 @@ <#macro details>

    ${CmsPagesCategorizedItemModel.title}

    ${CmsPagesCategorizedItemModel.description}

    +
    + No template for ${CmsPagesContentItemTypeModel.itemClass} available +
    \ No newline at end of file -- 2.52.0 From 4024355838bfc9ef08c755bf825015e9533adb25 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 14:55:34 +0100 Subject: [PATCH 29/43] Template for Event content type. --- .../org.librecms.contenttypes.Event.html.ftl | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Event.html.ftl diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Event.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Event.html.ftl new file mode 100644 index 000000000..ef2ce59ed --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Event.html.ftl @@ -0,0 +1,25 @@ +<#macro details> +
    +

    + ${CmsPagesCategorizedItemModel.title} + + ${CmsPagesEventModel.getStartDateTime('yyyy-MM-dd')} + <#if CmsPagesEventModel.getEndDateTime()??> + - ${CmsPagesEventModel.getEndDateTime('yyyy-MM-dd')} + + +

    +
    +

    ${CmsPagesCategorizedItemModel.description}

    + +
    + ${CmsPagesEventModel.text} +
    + + <#if CmsPagesEventModel.location??> +

    Location

    +
    + ${CmsPagesEventModel.location} +
    + + \ No newline at end of file -- 2.52.0 From 35ce5479fd60c72f4e72123bfb28756d19ca188a Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 17:24:55 +0100 Subject: [PATCH 30/43] Fixed a bug when deleting content items --- .../contentsection/FolderManager.java | 21 ++++++++++++++++--- .../documents/DocumentController.java | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/FolderManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/FolderManager.java index e6ad58d21..db451c04c 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/FolderManager.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/FolderManager.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; @@ -509,13 +510,27 @@ public class FolderManager { } Collections.reverse(tokens); - final String path = String.join("/", tokens); + final String path = tokens + .stream() + .filter(token -> !"/".equals(token)) + .collect( + Collectors.joining("/") + ); + //final String path = String.join("/", tokens); if (withContentSection) { final String sectionName = folder.getSection().getDisplayName(); - return String.format("%s:/%s/", sectionName, path); + if (path.isEmpty()) { + return String.format("%s:/", sectionName); + } else { + return String.format("%s:/%s/", sectionName, path); + } } else { - return String.format("/%s/", path); + if (path.isEmpty()) { + return "/"; + } else { + return String.format("/%s/", path); + } } } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/DocumentController.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/DocumentController.java index 1d165edce..80ed0c96c 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/DocumentController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/DocumentController.java @@ -815,7 +815,7 @@ public class DocumentController { } return String.format( - "redirect:/%s/documentfolders/%s", + "redirect:/%s/documentfolders%s", sectionIdentifier, folderPath ); -- 2.52.0 From f5d3481c9a8621d6e3082bbce421b4ed155dcb8b Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 26 Feb 2022 17:55:16 +0100 Subject: [PATCH 31/43] Setting/resetting the index item of a category only worked for the root category, now works for all categories. --- .../categorysystems/categorysystem.xhtml | 4 +- .../core/AbstractEntityRepository.java | 65 +++++++++++-------- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml index 12227992b..4c60c3270 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml @@ -524,7 +524,7 @@ -
    \ No newline at end of file diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java index 65b00bea8..2d5e5f683 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/MultiPartArticleModel.java @@ -18,6 +18,7 @@ */ package org.librecms.pages.models; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -35,9 +36,6 @@ import org.librecms.contentsection.ContentItem; import org.librecms.contenttypes.MultiPartArticle; import org.librecms.contenttypes.MultiPartArticleSection; -import java.net.URL; -import java.util.ArrayList; - /** * * @author Jens Pelzetter @@ -67,6 +65,12 @@ public class MultiPartArticleModel implements ProcessesContentItem { private List sectionLinks; + private String prevSectionLink; + + private String nextSectionLink; + + private int currentSection; + private String currentSectionTitle; private String currentSectionText; @@ -105,6 +109,27 @@ public class MultiPartArticleModel implements ProcessesContentItem { return Collections.unmodifiableList(sectionLinks); } + @Transactional(Transactional.TxType.REQUIRED) + public String getPrevSectionLink() { + contentItemModel.init(); + + return prevSectionLink; + } + + @Transactional(Transactional.TxType.REQUIRED) + public String getNextSectionLink() { + contentItemModel.init(); + + return nextSectionLink; + } + + @Transactional(Transactional.TxType.REQUIRED) + public int getCurrentSection() { + contentItemModel.init(); + + return currentSection; + } + @Transactional(Transactional.TxType.REQUIRED) public String getCurrentSectionTitle() { contentItemModel.init(); @@ -156,9 +181,8 @@ public class MultiPartArticleModel implements ProcessesContentItem { ) .orElse(Collections.emptyList()); - sectionLinks = buildSectionLinks(); - - final int currentSection = readCurrentSection(); + currentSection = readCurrentSection(); + if (mpa.getSections().size() < currentSection) { throw new WebApplicationException( Response @@ -189,6 +213,7 @@ public class MultiPartArticleModel implements ProcessesContentItem { .orElse(""); } + sectionLinks = buildSectionLinks(); sections = mpa .getSections() .stream() @@ -236,8 +261,26 @@ public class MultiPartArticleModel implements ProcessesContentItem { final int size = sectionTitles.size(); final List sectionLinksList = new ArrayList<>(); for (int i = 0; i < size; i++) { - sectionLinksList.add( - String.format( + sectionLinksList.add(buildSectionLink(i)); + } + + if (currentSection == 0) { + prevSectionLink = ""; + } else { + prevSectionLink = buildSectionLink(currentSection - 1); + } + + if (currentSection < sectionLinksList.size() - 1) { + nextSectionLink = buildSectionLink(currentSection + 1); + } else { + nextSectionLink = ""; + } + + return sectionLinksList; + } + + private String buildSectionLink(final int section) { + return String.format( "?%s&%s=%d", pageUrlModel .getQueryParameters() @@ -257,12 +300,8 @@ public class MultiPartArticleModel implements ProcessesContentItem { ) .collect(Collectors.joining("&")), MPA_SECTION_QUERY_PARAM, - i - ) - ); - } - - return sectionLinksList; + section + ); } } -- 2.52.0 From 7d670d725d70a8109b45a2108964f0b6d4ea7c89 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 3 Mar 2022 20:50:01 +0100 Subject: [PATCH 36/43] Item Display --- .../themes/librecms/templates/debug.html.ftl | 21 ++++++ .../librecms/templates/default.html.ftl | 67 +++++++++++++------ .../librecms/templates/index-page.html.ftl | 8 ++- .../org/librecms/pages/PagesController.java | 23 ++++--- .../AbstractContentItemListItemModel.java | 4 ++ ...stractContentItemListItemModelBuilder.java | 6 +- .../librecms/pages/models/PageUrlModel.java | 19 +++++- 7 files changed, 111 insertions(+), 37 deletions(-) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/debug.html.ftl diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/debug.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/debug.html.ftl new file mode 100644 index 000000000..a8c0dbf69 --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/debug.html.ftl @@ -0,0 +1,21 @@ + + + + + + Default Template + + +
    +

    This theme works.

    +
    +
    application
    +
    ${application}
    +
    themeUrl
    +
    ${themeUrl}
    +
    view
    +
    ${view!""}
    +
    +
    + + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/default.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/default.html.ftl index a8c0dbf69..b584c3797 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/default.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/default.html.ftl @@ -1,21 +1,48 @@ - - - - - - Default Template - - -
    -

    This theme works.

    -
    -
    application
    -
    ${application}
    -
    themeUrl
    -
    ${themeUrl}
    -
    view
    -
    ${view!""}
    -
    +<#import "./main.html.ftl" as main> +<#-- <#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> --> + +<@main.librecms> +
    +
    +
    + <#if CmsPagesContentItemTypeModel.itemClass != ""> + <#assign itemTemplate = .getOptionalTemplate("./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl")> + <#if itemTemplate.exists> + <#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> + <#else> + <#import "./contentitems/default.html.ftl" as contentitem> + + <@contentitem.details /> + +
    +
    + +

    Notes

    +
      +
    • +

      + A side note with some text +

      +

      + Occaecat sit eu ipsum irure. Enim consectetur aute anim proident sint dolor sint ea ex eu adipisicing et. Veniam laborum mollit velit incididunt aliquip do esse officia eu ea nostrud nulla. +

      +
    • +
    +

    More information

    +

    + Consequat occaecat eu ullamco amet id tempor. +

    +
      +
    • +

      Anim ex ut reprehenderit in enim id proident duis pariatur est anim do.

      + A related link +
    • +
    • +

      Quis minim deserunt incididunt ea voluptate laboris fugiat elit nulla.

      + Some download link +
    • +
    +
    - - \ No newline at end of file +
    + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index df9a06edc..bfa8e780a 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -65,11 +65,13 @@ <#list CmsPagesItemListModel.getItems("newslist")>

    News

    -
      +
        <#items as news>
      • -
        ${news.title}
        + <#--
        ${news.getReleaseDate('yyyy-MM-dd')}
        -->
        ${news.getReleaseDate('dd. MMM yyyy')}

        @@ -80,7 +82,7 @@
    <#list CmsPagesItemListModel.getItems("eventlist")> -
    +

    Upcoming events

      <#items as event> diff --git a/ccm-cms/src/main/java/org/librecms/pages/PagesController.java b/ccm-cms/src/main/java/org/librecms/pages/PagesController.java index e485705b8..26decc332 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/PagesController.java +++ b/ccm-cms/src/main/java/org/librecms/pages/PagesController.java @@ -245,7 +245,7 @@ public class PagesController { final Category category = getCategory(domain, pages, "/"); final Versions versions = generateFromPreviewParam(preview); final String language = determineLanguage(category, versions); - + initPageUrlModel(uriInfo); final String indexPage = String.format( @@ -278,7 +278,7 @@ public class PagesController { final String language = determineLanguage(category, versions); initPageUrlModel(uriInfo); - + final String itemPage = String.format( "/%s.%s.html%s", itemName, @@ -308,7 +308,7 @@ public class PagesController { final Category category = getCategory(domain, pages, "/"); final Versions versions = generateFromPreviewParam(preview); final String language = determineLanguage(category, itemName, versions); - + initPageUrlModel(uriInfo); final String itemPage = String.format( @@ -416,7 +416,7 @@ public class PagesController { final Category category = getCategory(domain, pages, page); final Versions versions = generateFromPreviewParam(preview); final String language = determineLanguage(category, versions); - + initPageUrlModel(uriInfo); final String redirectTo; @@ -472,7 +472,7 @@ public class PagesController { final Category category = getCategory(domain, pages, page); final Versions versions = generateFromPreviewParam(preview); final String language = determineLanguage(category, versions); - + initPageUrlModel(uriInfo); final String redirectTo; @@ -561,9 +561,16 @@ public class PagesController { categoryModel.init(pages.getCategoryDomain(), category, version); final Page page = pageManager.findPageForCategory(category); pagePropertiesModel.setProperties(page.getProperties()); - return themesMvc.getMvcTemplate( - uriInfo, "pages", page.getDisplayName() - ); + if (itemName.equals("index") || itemName.isBlank()) { + return themesMvc.getMvcTemplate( + uriInfo, "pages", page.getDisplayName() + ); + } else { + return themesMvc.getMvcTemplate( + uriInfo, "pages", "item-page" + ); + } + } private void initSiteInfoModel( diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java index 64b7c612b..e4ca2c550 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModel.java @@ -92,6 +92,10 @@ public abstract class AbstractContentItemListItemModel { this.description = description; } + public String getLang() { + return locale.toString(); + } + /** * Returns the type of the content item. In most cases implementations * should return the fully qualified name of the content item class here. diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java index 35cda60d1..0d4494de8 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractContentItemListItemModelBuilder.java @@ -46,11 +46,7 @@ public abstract class AbstractContentItemListItemModelBuilderJens Pelzetter @@ -93,4 +94,20 @@ public class PageUrlModel { this.queryParameters = new HashMap<>(queryParameters); } + public String getQueryString() { + return queryParameters + .entrySet() + .stream() + .map( + entry -> String.format( + "%s=%s", + entry.getKey(), + entry.getValue() + ) + ) + .collect( + Collectors.joining("&", "?", "") + ); + } + } -- 2.52.0 From 3425657121e627c671471f2b742c2ae080fbe830 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 5 Mar 2022 14:03:10 +0100 Subject: [PATCH 37/43] Item List for category pages --- .../librecms/templates/category-page.html.ftl | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl index 52bf67517..28ce09c3f 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl @@ -188,17 +188,21 @@ CmsPagesContentItemTypeModel.itemClass = ${CmsPagesContentItemTypeModel.itemClas
    -
    -
    -
      -
    • -

      Title Item 1

      -

      - Duis non pariatur sit aliquip incididunt. Tempor ullamco ipsum dolore reprehenderit Lorem do commodo dolore in adipisicing esse duis. Est dolore occaecat sunt adipisicing ullamco pariatur. Id tempor ex excepteur enim proident. -

      -
    • -
    + <#list CmsPagesItemListModel.getItems()> +
    +
    +
      + <#items as item> +
    • +

      + ${item.title} +

      +

      ${item.description}

      +
    • + +
    +
    -
    + \ No newline at end of file -- 2.52.0 From 2e4bbc2611bf0704df020817ee577e3eecacc101 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 5 Mar 2022 14:38:37 +0100 Subject: [PATCH 38/43] Some minor fixes for links --- .../librecms/templates/category-page.html.ftl | 149 +----------------- .../librecms/templates/index-page.html.ftl | 6 +- .../themes/librecms/templates/main.html.ftl | 2 +- .../org/libreccm/theming/mvc/ThemesMvc.java | 8 + 4 files changed, 15 insertions(+), 150 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl index 28ce09c3f..ed48a0a58 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl @@ -1,5 +1,4 @@ <#import "./main.html.ftl" as main> -<#-- <#import "./contentitems/${CmsPagesContentItemTypeModel.itemClass}.html.ftl" as contentitem> --> <@main.librecms>
    @@ -13,151 +12,7 @@ <#import "./contentitems/default.html.ftl" as contentitem> <@contentitem.details /> - - <#--

    Index Item Title ${CmsPagesCategorizedItemModel.title}

    -
    -CmsPagesContentItemTypeModel.displayName = ${CmsPagesContentItemTypeModel.displayName}
    -CmsPagesContentItemTypeModel.itemClass = ${CmsPagesContentItemTypeModel.itemClass}
    -
    -
    -

    - Enim pariatur esse nisi commodo cupidatat dolor reprehenderit commodo. Nulla mollit officia dolore ipsum elit irure excepteur ex excepteur est non aliqua. Tempor est amet id occaecat deserunt ea adipisicing laborum tempor exercitation dolor ex quis laboris. Nulla quis sit exercitation ex sunt ipsum adipisicing consequat mollit sunt. Ea fugiat commodo ullamco reprehenderit non. Ea laborum aute non ex Lorem sint anim. In sunt sit laboris amet ipsum tempor officia incididunt eu nostrud voluptate labore veniam. -

    -
    - -
    Associated images (using media list images)
    -
    - - -
    -

    - Et ut ea adipisicing irure mollit excepteur proident labore velit sint ex ipsum irure duis. Do irure do irure officia consectetur est. Nulla proident sit cillum veniam excepteur sint est culpa quis voluptate nostrud nulla. Minim incididunt dolor quis ullamco eu pariatur sunt deserunt aliquip elit cupidatat minim. Ipsum sunt dolore non anim minim et amet est aute. -

    -

    - Ex reprehenderit tempor quis velit incididunt minim ex consectetur nisi dolore incididunt. Culpa ullamco enim veniam do nulla esse pariatur. Aliqua irure laborum ut reprehenderit eiusmod sunt enim ipsum commodo non. Et cupidatat sint officia mollit do Lorem eu sunt. Sint voluptate ea id consectetur elit cupidatat excepteur. Cupidatat aliquip amet enim nisi incididunt laborum nostrud pariatur eiusmod. Do ullamco tempor ex mollit cillum dolor sint voluptate. -

    -

    - Ut ut excepteur enim exercitation mollit cillum id sit magna. Ullamco ullamco do reprehenderit nisi consequat. Id dolore eu laborum ex ipsum fugiat veniam id incididunt aliquip proident nulla commodo. Officia deserunt consequat in id ex sit. Lorem nostrud officia culpa enim labore id sit. -

    --> +
    @@ -195,7 +50,7 @@ CmsPagesContentItemTypeModel.itemClass = ${CmsPagesContentItemTypeModel.itemClas <#items as item>
  • - ${item.title} + ${item.title}

    ${item.description}

  • diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl index bfa8e780a..f30dbcd68 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/index-page.html.ftl @@ -70,7 +70,7 @@
  • <#--
    ${news.getReleaseDate('yyyy-MM-dd')}
    -->
    ${news.getReleaseDate('dd. MMM yyyy')}
    @@ -88,7 +88,9 @@ <#items as event>
  • -
    ${event.title}
    +
    ${event.getStartDate('dd. MMM yyyy HH:mm')}

    ${event.description}

    diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl index 3bad7aaa2..78f5c7251 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/main.html.ftl @@ -31,7 +31,7 @@
  • diff --git a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java index ae25a34f2..fd306727f 100644 --- a/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java +++ b/ccm-core/src/main/java/org/libreccm/theming/mvc/ThemesMvc.java @@ -33,6 +33,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.libreccm.core.CoreConstants; +import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.sites.Site; import org.libreccm.sites.SiteRepository; import org.libreccm.theming.ThemeInfo; @@ -50,6 +51,9 @@ import org.libreccm.theming.manifest.ThemeTemplate; public class ThemesMvc { public static final String DEFAULT_THEME_PARAM = "--DEFAULT--"; + + @Inject + private GlobalizationHelper globalizationHelper; @Inject private Models models; @@ -146,6 +150,10 @@ public class ThemesMvc { models.put("application", application); models.put("contextPath", servletContext.getContextPath()); + models.put( + "negotiatedLocale", + globalizationHelper.getNegotiatedLocale().toString() + ); models.put("themeName", themeInfo.getName()); models.put("themeVersion", themeInfo.getVersion()); models.put( -- 2.52.0 From 359118de7d705b7968f33689c3add0f2b260f8dd Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 5 Mar 2022 17:56:28 +0100 Subject: [PATCH 39/43] Structure for showing assets in the default theme --- .../themes/librecms/templates/assets.html.ftl | 11 +++++++++++ .../librecms/templates/category-page.html.ftl | 18 ++++++++++++++++++ .../pages/models/ContentItemModel.java | 9 +++++++++ 3 files changed, 38 insertions(+) create mode 100644 ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl new file mode 100644 index 000000000..fd1f252be --- /dev/null +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl @@ -0,0 +1,11 @@ +<#macro foo> +

    foo

    + + +<#macro "org.librecms.assets.FileAsset"> +

    A file asset

    + + +<#macro "org.librecms.assets.RelatedLink"> +

    A releated link

    + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl index ed48a0a58..0207eabbd 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl @@ -1,4 +1,5 @@ <#import "./main.html.ftl" as main> +<#import "./assets.html.ftl" as assets> <@main.librecms>
    @@ -15,6 +16,23 @@
    + <#list CmsPagesCategorizedItemModel.attachmentLists as attachmentList> +

    ${attachmentList.title}

    +

    ${attachmentList.description}

    + <#list attachmentList.attachments> +
      + <#items as attachment> +
    • + ${attachment.asset.type} + <#-- ${.vars["assets"]["foo"]} --> + <#-- ${.vars["org.librecms.assets.FileAsset"]} --> + <#-- ${.vars[attachment.asset.type]} --> + <@.vars["assets"][attachment.asset.type] /> +
    • + +
    + +

    Notes

      diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java index c919c3927..90efb97e8 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java @@ -62,6 +62,7 @@ public class ContentItemModel { /** * Provides access to the builders for asset models. */ + @Inject private AssetModelBuilders assetModelBuilders; /** @@ -273,6 +274,14 @@ public class ContentItemModel { .map(ContentItemModelData::getDescription) .orElse(""); } + + @Transactional(Transactional.TxType.REQUIRED) + public List getAttachmentLists() { + init(); + return contentItem + .map(ContentItemModelData::getAttachmentLists) + .orElse(Collections.emptyList()); + } /** * Gets the version of the current item (see {@link ContentItem#version}. -- 2.52.0 From 8491c01d8bcbf87a59772f9ab2b121b26973cb84 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Mon, 7 Mar 2022 19:43:43 +0100 Subject: [PATCH 40/43] Displaying Attachment Lists --- .../themes/librecms/templates/assets.html.ftl | 24 +++++++++++--- .../librecms/templates/category-page.html.ftl | 32 +------------------ 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl index fd1f252be..d8c0413a7 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl @@ -2,10 +2,26 @@

      foo

      -<#macro "org.librecms.assets.FileAsset"> -

      A file asset

      +<#macro "org.librecms.assets.FileAsset" asset> +

      ${asset.title}

      +

      ${asset.description}

      + ${asset.mimeType} ${asset.size} Bytes + <#--

      A file asset

      --> -<#macro "org.librecms.assets.RelatedLink"> -

      A releated link

      +<#macro "org.librecms.assets.RelatedLink" asset> + <#if asset.externalLink> +
      + ${asset.title} + + + + External link +
      + <#else> + ${asset.title} + \ No newline at end of file diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl index 0207eabbd..7d63836f3 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/category-page.html.ftl @@ -23,42 +23,12 @@
        <#items as attachment>
      • - ${attachment.asset.type} - <#-- ${.vars["assets"]["foo"]} --> - <#-- ${.vars["org.librecms.assets.FileAsset"]} --> - <#-- ${.vars[attachment.asset.type]} --> - <@.vars["assets"][attachment.asset.type] /> + <@.vars["assets"][attachment.asset.type] attachment.asset />
      - -

      Notes

      -
        -
      • -

        - A side note with some text -

        -

        - Occaecat sit eu ipsum irure. Enim consectetur aute anim proident sint dolor sint ea ex eu adipisicing et. Veniam laborum mollit velit incididunt aliquip do esse officia eu ea nostrud nulla. -

        -
      • -
      -

      More information

      -

      - Consequat occaecat eu ullamco amet id tempor. -

      -
        -
      • -

        Anim ex ut reprehenderit in enim id proident duis pariatur est anim do.

        - A related link -
      • -
      • -

        Quis minim deserunt incididunt ea voluptate laboris fugiat elit nulla.

        - Some download link -
      • -

  • <#list CmsPagesItemListModel.getItems()> -- 2.52.0 From 8871eecea321a8416ae5775185630395069e7d95 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Tue, 8 Mar 2022 20:16:36 +0100 Subject: [PATCH 41/43] File download for attached file assets --- .../themes/librecms/templates/assets.html.ftl | 2 +- .../org/librecms/contentsection/rs/Files.java | 8 ++++-- .../AbstractBinaryAssetModelBuilder.java | 7 +++++ .../pages/models/BinaryAssetModel.java | 28 +++++++++++-------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl index d8c0413a7..f9f8b1b40 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl @@ -3,7 +3,7 @@ <#macro "org.librecms.assets.FileAsset" asset> -

    ${asset.title}

    +

    ${asset.title}

    ${asset.description}

    ${asset.mimeType} ${asset.size} Bytes <#--

    A file asset

    --> diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java index 14135e8b0..f44bc6db4 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Files.java @@ -32,6 +32,7 @@ import java.util.Optional; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; +import javax.transaction.Transactional; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -44,7 +45,7 @@ import javax.ws.rs.core.StreamingOutput; * @author Jens Pelzetter */ @RequestScoped -@Path("/{content-section}/files") +@Path("/{content-section}/files/") public class Files { private static final Logger LOGGER = LogManager.getLogger(Files.class); @@ -60,6 +61,7 @@ public class Files { @GET @Path("/uuid-{uuid}") + @Transactional(Transactional.TxType.REQUIRED) public Response getFileByUuid( @PathParam("content-section") final String sectionName, @PathParam("uuid") final String uuid @@ -82,7 +84,9 @@ public class Files { } @GET - @Path("/{path:^(?!uuid).+$}") + //@Path("/{path:^(?!uuid).+$}") + @Path("/{path:.+}") + @Transactional(Transactional.TxType.REQUIRED) public Response getFile( @PathParam("content-section") final String sectionName, @PathParam("path") final String path diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java index aa9eb03d6..af47bf3e7 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/AbstractBinaryAssetModelBuilder.java @@ -21,6 +21,7 @@ package org.librecms.pages.models; import org.libreccm.l10n.GlobalizationHelper; import org.librecms.assets.BinaryAsset; import org.librecms.contentsection.AssetManager; +import org.librecms.contentsection.Folder; import javax.inject.Inject; import javax.transaction.Transactional; @@ -46,6 +47,12 @@ public abstract class AbstractBinaryAssetModelBuilder folder.getSection().getDisplayName()) + .orElse("") + ); model.setDescription( globalizationHelper.getValueFromLocalizedString( asset.getDescription() diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/BinaryAssetModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/BinaryAssetModel.java index cc1dcc62b..578e0f81f 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/BinaryAssetModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/BinaryAssetModel.java @@ -27,17 +27,19 @@ import org.librecms.assets.BinaryAsset; public class BinaryAssetModel extends AbstractAssetModel { private String description; - + private String fileName; - + private String mimeType; - + private long size; - + private String binaryAssetUuid; - + + private String contentSection; + private String assetPath; - + @Override public String getType() { return BinaryAsset.class.getName(); @@ -83,6 +85,14 @@ public class BinaryAssetModel extends AbstractAssetModel { this.binaryAssetUuid = binaryAssetUuid; } + public String getContentSection() { + return contentSection; + } + + public void setContentSection(final String contentSection) { + this.contentSection = contentSection; + } + public String getAssetPath() { return assetPath; } @@ -90,9 +100,5 @@ public class BinaryAssetModel extends AbstractAssetModel { public void setAssetPath(final String assetPath) { this.assetPath = assetPath; } - - - - - + } -- 2.52.0 From b89e15479df77e3b6054f7eee1452c1046fd9625 Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Wed, 9 Mar 2022 20:18:49 +0100 Subject: [PATCH 42/43] Media attachment part 1 --- .../themes/librecms/templates/assets.html.ftl | 23 ++++++++-- ...org.librecms.contenttypes.Article.html.ftl | 9 ++++ .../main/java/org/librecms/CmsConstants.java | 2 + .../pages/models/ContentItemModel.java | 42 ++++++++++++++++++- .../pages/models/ImageModelBuilder.java | 9 ++-- .../documents/media/MediaStep.java | 11 +++-- .../documents/media/MediaStepService.java | 8 +++- 7 files changed, 91 insertions(+), 13 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl index f9f8b1b40..6c9afd791 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl @@ -1,5 +1,13 @@ -<#macro foo> -

    foo

    +<#macro "org.librecms.assets.AudioAsset" asset> +
    AudioAsset
    + + +<#macro "org.librecms.assets.ExternalAudioAsset" asset> +
    ExternalAudioAsset
    + + +<#macro "org.librecms.assets.ExternalVideoAsset" asset> +
    ExternalVideoAsset
    <#macro "org.librecms.assets.FileAsset" asset> @@ -9,6 +17,11 @@ <#--

    A file asset

    --> +<#macro "org.librecms.assets.Image" asset> +
    Image
    + + + <#macro "org.librecms.assets.RelatedLink" asset> <#if asset.externalLink>
    @@ -24,4 +37,8 @@ <#else> ${asset.title} - \ No newline at end of file + + +<#macro "org.librecms.assets.VideoAsset" asset> +
    VideoAsset
    + diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl index 6d2e6da2c..a9e3b83b9 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/contentitems/org.librecms.contenttypes.Article.html.ftl @@ -1,7 +1,16 @@ +<#import "../assets.html.ftl" as assets> + <#macro details>

    ${CmsPagesCategorizedItemModel.title}

    ${CmsPagesCategorizedItemModel.description}

    +
    + <#list CmsPagesCategorizedItemModel.mediaLists as mediaList> + <#list mediaList.attachments as media> + <@.vars["assets"][media.asset.type] media.asset /> + + +
    ${CmsPagesArticleModel.text}
    diff --git a/ccm-cms/src/main/java/org/librecms/CmsConstants.java b/ccm-cms/src/main/java/org/librecms/CmsConstants.java index 1a3ff9ad1..1c6a28feb 100644 --- a/ccm-cms/src/main/java/org/librecms/CmsConstants.java +++ b/ccm-cms/src/main/java/org/librecms/CmsConstants.java @@ -61,6 +61,8 @@ public class CmsConstants { public static final String FORM_ENCTYPE_MULTIPART = "multipart/form-data"; + public static final String MEDIA_LIST_PREFIX = ".media-"; + /** * Constant string used as key for creating service package as a legacy * application. diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java index 90efb97e8..05eb4bc41 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ContentItemModel.java @@ -21,6 +21,7 @@ package org.librecms.pages.models; import org.libreccm.categorization.CategoryRepository; import org.libreccm.core.CcmObject; import org.libreccm.l10n.GlobalizationHelper; +import org.librecms.CmsConstants; import org.librecms.contentsection.Asset; import org.librecms.contentsection.AttachmentList; import org.librecms.contentsection.ContentItem; @@ -274,7 +275,7 @@ public class ContentItemModel { .map(ContentItemModelData::getDescription) .orElse(""); } - + @Transactional(Transactional.TxType.REQUIRED) public List getAttachmentLists() { init(); @@ -283,6 +284,14 @@ public class ContentItemModel { .orElse(Collections.emptyList()); } + @Transactional(Transactional.TxType.REQUIRED) + public List getMediaLists() { + init(); + return contentItem + .map(ContentItemModelData::getMediaLists) + .orElse(Collections.emptyList()); + } + /** * Gets the version of the current item (see {@link ContentItem#version}. * @@ -510,6 +519,24 @@ public class ContentItemModel { item .getAttachments() .stream() + .filter( + list -> !list.getName().startsWith( + CmsConstants.MEDIA_LIST_PREFIX + ) + ) + .map(this::buildAttachmentListModel) + .sorted() + .collect(Collectors.toList()) + ); + data.setMediaLists( + item + .getAttachments() + .stream() + .filter( + list -> list.getName().startsWith( + CmsConstants.MEDIA_LIST_PREFIX + ) + ) .map(this::buildAttachmentListModel) .sorted() .collect(Collectors.toList()) @@ -613,6 +640,8 @@ public class ContentItemModel { private List attachmentLists; + private List mediaLists; + public long getObjectId() { return objectId; } @@ -716,10 +745,19 @@ public class ContentItemModel { } public void setAttachmentLists( - final List attachmentLists) { + final List attachmentLists + ) { this.attachmentLists = new ArrayList<>(attachmentLists); } + public List getMediaLists() { + return Collections.unmodifiableList(mediaLists); + } + + public void setMediaLists(final List mediaLists) { + this.mediaLists = new ArrayList<>(mediaLists); + } + } } diff --git a/ccm-cms/src/main/java/org/librecms/pages/models/ImageModelBuilder.java b/ccm-cms/src/main/java/org/librecms/pages/models/ImageModelBuilder.java index 9da299934..f60006c01 100644 --- a/ccm-cms/src/main/java/org/librecms/pages/models/ImageModelBuilder.java +++ b/ccm-cms/src/main/java/org/librecms/pages/models/ImageModelBuilder.java @@ -50,9 +50,12 @@ public class ImageModelBuilder protected void addProperties(final Image image, final ImageModel model) { super.addProperties(image, model); model.setHeight(image.getHeight()); - model.setLegalMetadata( - legalMetadataModelBuilder.buildAssetModel(image.getLegalMetadata()) - ); + if (image.getLegalMetadata() != null) { + model.setLegalMetadata( + legalMetadataModelBuilder.buildAssetModel( + image.getLegalMetadata()) + ); + } model.setWidth(image.getWidth()); } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStep.java index 66b0866dc..eb79ab20b 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStep.java @@ -23,6 +23,7 @@ import org.libreccm.api.IdentifierParser; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.PermissionChecker; import org.libreccm.ui.BaseUrl; +import org.librecms.CmsConstants; import org.librecms.assets.AssetTypesManager; import org.librecms.contentsection.Asset; import org.librecms.contentsection.AssetManager; @@ -63,6 +64,8 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; +import static org.librecms.CmsConstants.MEDIA_LIST_PREFIX; + /** * * @author Jens Pelzetter @@ -83,8 +86,6 @@ public class MediaStep extends AbstractMvcAuthoringStep { */ static final String PATH_FRAGMENT = "media"; - protected static final String MEDIA_LIST_PREFIX = ".media-"; - /** * {@link AssetManager} instance of managing {@link Asset}s. */ @@ -186,7 +187,11 @@ public class MediaStep extends AbstractMvcAuthoringStep { getDocument() .getAttachments() .stream() - .filter(list -> list.getName().startsWith(MEDIA_LIST_PREFIX)) + .filter( + list -> list.getName().startsWith( + CmsConstants.MEDIA_LIST_PREFIX + ) + ) .map(this::buildMediaListDto) .collect(Collectors.toList()) ); diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStepService.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStepService.java index 0b15ee0c7..32f15cd44 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStepService.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/media/MediaStepService.java @@ -18,6 +18,7 @@ */ package org.librecms.ui.contentsections.documents.media; +import org.librecms.CmsConstants; import org.librecms.contentsection.AttachmentList; import org.librecms.contentsection.AttachmentListRepository; import org.librecms.contentsection.ContentItem; @@ -102,7 +103,10 @@ public class MediaStepService { .getAttachments() .stream() .filter( - list -> list.getName().startsWith(MediaStep.MEDIA_LIST_PREFIX)) + list -> list.getName().startsWith( + CmsConstants.MEDIA_LIST_PREFIX + ) + ) .collect(Collectors.toList()); final List attachmentListsOrder = order .getMediaListsOrder(); @@ -147,7 +151,7 @@ public class MediaStepService { .stream() .filter( list -> list.getName().startsWith( - MediaStep.MEDIA_LIST_PREFIX + CmsConstants.MEDIA_LIST_PREFIX ) ) .filter(list -> attachmentsOrder.getKey().equals(list.getUuid())) -- 2.52.0 From 28fd511f959fab51e13f244d1c19f9aaa7a2e14c Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 12 Mar 2022 17:05:23 +0100 Subject: [PATCH 43/43] Display of media assets --- .../themes/librecms/templates/assets.html.ftl | 31 +++++++++++++++---- .../contentsection/rs/AudioMedia.java | 20 ++++++------ .../librecms/contentsection/rs/Images.java | 18 +++++------ .../librecms/contentsection/rs/Videos.java | 20 ++++++------ 4 files changed, 54 insertions(+), 35 deletions(-) diff --git a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl index 6c9afd791..087d2b556 100644 --- a/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl +++ b/ccm-cms-default-theme/src/main/resources/themes/librecms/templates/assets.html.ftl @@ -1,24 +1,38 @@ <#macro "org.librecms.assets.AudioAsset" asset> -
    AudioAsset
    +
    + +
    ${asset.description}
    +
    <#macro "org.librecms.assets.ExternalAudioAsset" asset> -
    ExternalAudioAsset
    +
    + +
    ${asset.description}
    +
    <#macro "org.librecms.assets.ExternalVideoAsset" asset> -
    ExternalVideoAsset
    +
    + +
    ${asset.description}
    +
    <#macro "org.librecms.assets.FileAsset" asset>

    ${asset.title}

    ${asset.description}

    ${asset.mimeType} ${asset.size} Bytes - <#--

    A file asset

    --> <#macro "org.librecms.assets.Image" asset> -
    Image
    +
    + +
    ${asset.description}
    +
    @@ -40,5 +54,10 @@ <#macro "org.librecms.assets.VideoAsset" asset> -
    VideoAsset
    +
    + +
    ${asset.description}
    +
    diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java index ad2d28f47..4cf68dc7c 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/AudioMedia.java @@ -18,15 +18,6 @@ */ package org.librecms.contentsection.rs; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.librecms.assets.BinaryAssetDataService; -import org.librecms.assets.AudioAsset; -import org.librecms.contentsection.Asset; -import org.librecms.contentsection.AssetRepository; -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentSectionRepository; - import java.io.IOException; import java.io.OutputStream; import java.util.Optional; @@ -40,6 +31,15 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.librecms.assets.AudioAsset; +import org.librecms.assets.BinaryAssetDataService; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; + /** * * @author Jens Pelzetter @@ -84,7 +84,7 @@ public class AudioMedia { } @GET - @Path("/{path:^(?!uuid).+$}") + @Path("/{path:.+}") public Response getAudio( @PathParam("content-section") final String sectionName, @PathParam("path") final String path diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java index e77275739..69aa2739b 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Images.java @@ -18,14 +18,6 @@ */ package org.librecms.contentsection.rs; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.librecms.assets.Image; -import org.librecms.contentsection.Asset; -import org.librecms.contentsection.AssetRepository; -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentSectionRepository; - import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -45,6 +37,14 @@ import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.librecms.assets.Image; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; + /** * * @author Jens Pelzetter @@ -139,7 +139,7 @@ public class Images { * @return A {@link Response} containing the scaled image or an error value. */ @GET - @Path("/{path:^(?!uuid).+$}") + @Path("/{path:.+}") public Response getImage( @PathParam("content-section") final String sectionName, @PathParam("path") final String path, diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java index cecd277ac..6453e4f1b 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/rs/Videos.java @@ -18,15 +18,6 @@ */ package org.librecms.contentsection.rs; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.librecms.assets.BinaryAssetDataService; -import org.librecms.assets.VideoAsset; -import org.librecms.contentsection.Asset; -import org.librecms.contentsection.AssetRepository; -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentSectionRepository; - import java.io.IOException; import java.io.OutputStream; import java.util.Optional; @@ -40,6 +31,15 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.librecms.assets.BinaryAssetDataService; +import org.librecms.assets.VideoAsset; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionRepository; + /** * * @author Jens Pelzetter @@ -84,7 +84,7 @@ public class Videos { } @GET - @Path("/{path:^(?!uuid).+$}") + @Path("/{path:.+}") public Response getVideo( @PathParam("content-section") final String sectionName, @PathParam("path") final String path -- 2.52.0