From 05246c361420f99860172805d54db18d6ecd8e76 Mon Sep 17 00:00:00 2001 From: Boubaker Khanfir Date: Fri, 17 May 2024 15:56:06 +0100 Subject: [PATCH] feat: Allow to manage Page Template Status - MEED-6845 - Meeds-io/MIPs#133 --- .../meeds/layout/rest/PageTemplateRest.java | 13 ++++ .../layout/service/PageTemplateService.java | 28 ++++++--- .../service/PageTemplateServiceTest.java | 60 +++++++++++++++++++ .../locale/portlet/LayoutEditor_en.properties | 3 + .../js/PageTemplateService.js | 21 +++++-- .../components/drawer/PageTemplateDrawer.vue | 7 ++- .../components/list/PageTemplateItem.vue | 33 +++++++++- .../components/list/PageTemplates.vue | 16 ++++- 8 files changed, 163 insertions(+), 18 deletions(-) diff --git a/layout-service/src/main/java/io/meeds/layout/rest/PageTemplateRest.java b/layout-service/src/main/java/io/meeds/layout/rest/PageTemplateRest.java index 9bf8320cc..556e6821d 100644 --- a/layout-service/src/main/java/io/meeds/layout/rest/PageTemplateRest.java +++ b/layout-service/src/main/java/io/meeds/layout/rest/PageTemplateRest.java @@ -61,6 +61,19 @@ public List getPageTemplates(HttpServletRequest request) { return pageTemplateService.getPageTemplates(request.getLocale(), true); } + @GetMapping("{id}") + @Secured("users") + @Operation(summary = "Retrieve a page template designated by its id", method = "GET", + description = "This will retrieve a page template designated by its id") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Request fulfilled"), }) + public PageTemplate getPageTemplate( + HttpServletRequest request, + @Parameter(description = "Page template identifier") + @PathVariable("id") + long id) { + return pageTemplateService.getPageTemplate(id, request.getLocale(), true); + } + @PostMapping @Secured("users") @Operation(summary = "Create a page template", method = "POST", description = "This creates a new page template") diff --git a/layout-service/src/main/java/io/meeds/layout/service/PageTemplateService.java b/layout-service/src/main/java/io/meeds/layout/service/PageTemplateService.java index fb373ac17..7cf962c58 100644 --- a/layout-service/src/main/java/io/meeds/layout/service/PageTemplateService.java +++ b/layout-service/src/main/java/io/meeds/layout/service/PageTemplateService.java @@ -70,19 +70,19 @@ public List getPageTemplates(boolean expand) { public List getPageTemplates(Locale locale, boolean expand) { List pageTemplates = pageTemplateStorage.getPageTemplates(); if (expand) { - pageTemplates.forEach(pageTemplate -> { - pageTemplate.setName(getLabel(pageTemplate.getId(), PageTemplateTranslationPlugin.TITLE_FIELD_NAME, locale)); - pageTemplate.setDescription(getLabel(pageTemplate.getId(), PageTemplateTranslationPlugin.DESCRIPTION_FIELD_NAME, locale)); - List attachmentFileIds = attachmentService.getAttachmentFileIds(PageTemplateAttachmentPlugin.OBJECT_TYPE, - String.valueOf(pageTemplate.getId())); - if (CollectionUtils.isNotEmpty(attachmentFileIds)) { - pageTemplate.setIllustrationId(Long.parseLong(attachmentFileIds.get(0))); - } - }); + pageTemplates.forEach(pageTemplate -> computePageTemplateAttributes(locale, pageTemplate)); } return pageTemplates; } + public PageTemplate getPageTemplate(long id, Locale locale, boolean expand) { + PageTemplate pageTemplate = pageTemplateStorage.getPageTemplate(id); + if (expand) { + computePageTemplateAttributes(locale, pageTemplate); + } + return pageTemplate; + } + public PageTemplate getPageTemplate(long id) { return pageTemplateStorage.getPageTemplate(id); } @@ -157,4 +157,14 @@ private String getLabel(long templateId, String fieldName, Locale locale) { } } + private void computePageTemplateAttributes(Locale locale, PageTemplate pageTemplate) { + pageTemplate.setName(getLabel(pageTemplate.getId(), PageTemplateTranslationPlugin.TITLE_FIELD_NAME, locale)); + pageTemplate.setDescription(getLabel(pageTemplate.getId(), PageTemplateTranslationPlugin.DESCRIPTION_FIELD_NAME, locale)); + List attachmentFileIds = attachmentService.getAttachmentFileIds(PageTemplateAttachmentPlugin.OBJECT_TYPE, + String.valueOf(pageTemplate.getId())); + if (CollectionUtils.isNotEmpty(attachmentFileIds)) { + pageTemplate.setIllustrationId(Long.parseLong(attachmentFileIds.get(0))); + } + } + } diff --git a/layout-service/src/test/java/io/meeds/layout/service/PageTemplateServiceTest.java b/layout-service/src/test/java/io/meeds/layout/service/PageTemplateServiceTest.java index ad52b090e..dc4604c00 100644 --- a/layout-service/src/test/java/io/meeds/layout/service/PageTemplateServiceTest.java +++ b/layout-service/src/test/java/io/meeds/layout/service/PageTemplateServiceTest.java @@ -176,6 +176,66 @@ public void getPageTemplatesWithExpand() throws ObjectNotFoundException { assertEquals(32l, pageTemplates.get(0).getIllustrationId()); } + @Test + public void getPageTemplateWithExpand() throws ObjectNotFoundException { + PageTemplate template = new PageTemplate(2l, false, LAYOUT_CATEGORY, LAYOUT_CONTENT); + when(localeConfigService.getDefaultLocaleConfig()).thenReturn(defaultLocaleConfig); + when(defaultLocaleConfig.getLocale()).thenReturn(Locale.ENGLISH); + + when(pageTemplateStorage.getPageTemplate(2l)).thenReturn(template); + + PageTemplate retrievedPageTemplate = pageTemplateService.getPageTemplate(2l); + assertNotNull(retrievedPageTemplate); + assertEquals(template.getId(), retrievedPageTemplate.getId()); + assertEquals(template.getContent(), retrievedPageTemplate.getContent()); + assertNull(retrievedPageTemplate.getName()); + assertNull(retrievedPageTemplate.getDescription()); + assertEquals(0l, retrievedPageTemplate.getIllustrationId()); + + when(translationService.getTranslationField(PageTemplateTranslationPlugin.OBJECT_TYPE, + template.getId(), + PageTemplateTranslationPlugin.TITLE_FIELD_NAME)).thenThrow(ObjectNotFoundException.class); + retrievedPageTemplate = pageTemplateService.getPageTemplate(2l, Locale.FRENCH, true); + assertNotNull(retrievedPageTemplate); + + reset(translationService); + + TranslationField titleTranslationField = mock(TranslationField.class); + when(translationService.getTranslationField(PageTemplateTranslationPlugin.OBJECT_TYPE, + template.getId(), + PageTemplateTranslationPlugin.TITLE_FIELD_NAME)).thenReturn(titleTranslationField); + retrievedPageTemplate = pageTemplateService.getPageTemplate(2l, Locale.FRENCH, true); + assertNotNull(retrievedPageTemplate); + assertEquals(template.getId(), retrievedPageTemplate.getId()); + assertEquals(template.getContent(), retrievedPageTemplate.getContent()); + assertNull(retrievedPageTemplate.getName()); + assertNull(retrievedPageTemplate.getDescription()); + assertEquals(0l, retrievedPageTemplate.getIllustrationId()); + + String frTitle = "testTitle"; + when(titleTranslationField.getLabels()).thenReturn(Collections.singletonMap(Locale.FRENCH, frTitle)); + + retrievedPageTemplate = pageTemplateService.getPageTemplate(2l, Locale.FRENCH, true); + assertEquals(frTitle, retrievedPageTemplate.getName()); + + TranslationField descriptionTranslationField = mock(TranslationField.class); + when(translationService.getTranslationField(PageTemplateTranslationPlugin.OBJECT_TYPE, + template.getId(), + PageTemplateTranslationPlugin.DESCRIPTION_FIELD_NAME)).thenReturn(descriptionTranslationField); + String enDesc = "testDescription"; + when(descriptionTranslationField.getLabels()).thenReturn(Collections.singletonMap(Locale.ENGLISH, enDesc)); + + retrievedPageTemplate = pageTemplateService.getPageTemplate(2l, Locale.ENGLISH, true); + assertNotNull(retrievedPageTemplate); + assertEquals(enDesc, retrievedPageTemplate.getDescription()); + + when(attachmentService.getAttachmentFileIds(PageTemplateAttachmentPlugin.OBJECT_TYPE, + "2")).thenReturn(Collections.singletonList("32")); + retrievedPageTemplate = pageTemplateService.getPageTemplate(2l, Locale.GERMAN, true); + assertNotNull(retrievedPageTemplate); + assertEquals(32l, retrievedPageTemplate.getIllustrationId()); + } + @Test public void getPageTemplate() { when(pageTemplateStorage.getPageTemplate(2l)).thenReturn(pageTemplate); diff --git a/layout-webapp/src/main/resources/locale/portlet/LayoutEditor_en.properties b/layout-webapp/src/main/resources/locale/portlet/LayoutEditor_en.properties index dff10c3dd..0aa89d8ca 100644 --- a/layout-webapp/src/main/resources/locale/portlet/LayoutEditor_en.properties +++ b/layout-webapp/src/main/resources/locale/portlet/LayoutEditor_en.properties @@ -117,4 +117,7 @@ pageTemplates.filter.placeholder=Filter by name, description pageTemplates.label.name=Name pageTemplates.label.description=Description pageTemplates.label.category=Category +pageTemplates.label.status=Status pageTemplate.label.preview=Preview of {0} template +pageTemplate.status.update.success=Template status successfully updated +pageTemplate.status.update.error=An unknown error occurred while updating template status. Please contact the administrator or try agan later. diff --git a/layout-webapp/src/main/webapp/vue-app/common-layout-components/js/PageTemplateService.js b/layout-webapp/src/main/webapp/vue-app/common-layout-components/js/PageTemplateService.js index 427b30787..7e874ddf9 100644 --- a/layout-webapp/src/main/webapp/vue-app/common-layout-components/js/PageTemplateService.js +++ b/layout-webapp/src/main/webapp/vue-app/common-layout-components/js/PageTemplateService.js @@ -30,6 +30,19 @@ export function getPageTemplates() { }); } +export function getPageTemplate(id) { + return fetch(`/layout/rest/pageTemplates/${id}`, { + method: 'GET', + credentials: 'include', + }).then(resp => { + if (!resp?.ok) { + throw new Error('Error when retrieving page template'); + } else { + return resp.json(); + } + }); +} + export function createPageTemplate(pageContent) { return fetch('/layout/rest/pageTemplates', { credentials: 'include', @@ -49,16 +62,14 @@ export function createPageTemplate(pageContent) { }); } -export function updatePageTemplate(pageContent, id) { - return fetch(`/layout/rest/pageTemplates/${id}`, { +export function updatePageTemplate(pageTemplate) { + return fetch(`/layout/rest/pageTemplates/${pageTemplate.id}`, { credentials: 'include', method: 'PUT', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ - content: JSON.stringify(pageContent), - }), + body: JSON.stringify(pageTemplate), }).then((resp) => { if (!resp?.ok) { throw new Error('Error when creating page template'); diff --git a/layout-webapp/src/main/webapp/vue-app/layout-editor/components/drawer/PageTemplateDrawer.vue b/layout-webapp/src/main/webapp/vue-app/layout-editor/components/drawer/PageTemplateDrawer.vue index 1d6fbb502..3c7436120 100644 --- a/layout-webapp/src/main/webapp/vue-app/layout-editor/components/drawer/PageTemplateDrawer.vue +++ b/layout-webapp/src/main/webapp/vue-app/layout-editor/components/drawer/PageTemplateDrawer.vue @@ -152,7 +152,12 @@ export default { save() { const pageLayout = this.$layoutUtils.cleanAttributes(this.$root.layout, true, true); const savePageRequest = - this.templateId ? this.$pageTemplateService.updatePageTemplate(pageLayout, this.templateId) + this.templateId ? + this.$pageTemplateService.getPageTemplate(this.templateId) + .then(pageTemplate => this.$pageTemplateService.updatePageTemplate({ + ...pageTemplate, + content: JSON.stringify(pageLayout), + })) : this.$pageTemplateService.createPageTemplate(pageLayout); return savePageRequest .then(pageTemplate => { diff --git a/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplateItem.vue b/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplateItem.vue index c35aab3c3..c8f1f9916 100644 --- a/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplateItem.vue +++ b/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplateItem.vue @@ -24,10 +24,21 @@ {{ category }} + + + \ No newline at end of file diff --git a/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplates.vue b/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplates.vue index fb1e8432a..74743df7e 100644 --- a/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplates.vue +++ b/layout-webapp/src/main/webapp/vue-app/page-templates-management/components/list/PageTemplates.vue @@ -57,8 +57,16 @@ export default { { text: this.$t('pageTemplates.label.category'), value: 'category', - align: 'left', - sortable: false, + align: 'center', + sortable: true, + class: 'page-template-category-header', + width: '120px' + }, + { + text: this.$t('pageTemplates.label.status'), + value: 'disabled', + align: 'center', + sortable: true, class: 'page-template-category-header', width: '120px' }, @@ -74,8 +82,12 @@ export default { }, }, created() { + this.$root.$on('page-templates-refresh', this.refreshPageTemplates); this.refreshPageTemplates(); }, + beforeDestroy() { + this.$root.$off('page-templates-refresh', this.refreshPageTemplates); + }, methods: { refreshPageTemplates() { this.loading = true;