From 0661a6a28aa519d1cf16b129cf82dde7e1d9c43b Mon Sep 17 00:00:00 2001 From: Helmi Akermi Date: Thu, 3 Oct 2024 11:09:11 +0100 Subject: [PATCH] feat: Implement notes publication drawer - EXO-72738 feat: Implement note publication drawer - EXO-72738 - Meeds-io/MIPs#161 Implement note publication drawer --- .../wiki/service/rest/NotesRestService.java | 8 +- .../portlet/notes/notesPortlet_en.properties | 7 + .../portlet/notes/notesPortlet_fr.properties | 5 + .../webapp/WEB-INF/conf/configuration.xml | 1 + .../conf/wiki/feature-flags-configuration.xml | 52 +++ .../webui/workspace/UINotesHeadTemplate.gtmpl | 10 + .../main/webapp/skin/less/notes/notes.less | 2 +- .../components/NotesEditorDashboard.vue | 2 +- .../components/NoteEditorMetadataDrawer.vue | 310 ------------------ .../components/NoteFullRichEditor.vue | 77 ++++- .../NoteEditorFeaturedImageDrawer.vue | 0 .../NoteEditorMetadataDrawer.vue | 160 +++++++++ .../NoteMetadataPropertiesForm.vue | 272 +++++++++++++++ .../NotePublicationDrawer.vue | 238 ++++++++++++++ .../notes-rich-editor/initComponents.js | 10 +- 15 files changed, 819 insertions(+), 335 deletions(-) create mode 100644 notes-webapp/src/main/webapp/WEB-INF/conf/wiki/feature-flags-configuration.xml create mode 100644 notes-webapp/src/main/webapp/groovy/webui/workspace/UINotesHeadTemplate.gtmpl delete mode 100644 notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteEditorMetadataDrawer.vue rename notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/{ => note-properties}/NoteEditorFeaturedImageDrawer.vue (100%) create mode 100644 notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteEditorMetadataDrawer.vue create mode 100644 notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteMetadataPropertiesForm.vue create mode 100644 notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-publication/NotePublicationDrawer.vue diff --git a/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java b/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java index 10f9630f41..c4e81abaab 100644 --- a/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java +++ b/notes-service/src/main/java/org/exoplatform/wiki/service/rest/NotesRestService.java @@ -761,8 +761,8 @@ public Response updateNoteById(@Parameter(description = "Note id", required = tr } note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_CONTENT_AND_TITLE, identity); } else { - note_.setLang(note.getLang()); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_CONTENT_AND_TITLE, identity); + note_.setLang(note.getLang()); note_.setTitle(note.getTitle()); note_.setContent(note.getContent()); note_.setProperties(notePageProperties); @@ -783,8 +783,8 @@ public Response updateNoteById(@Parameter(description = "Note id", required = tr note_.setProperties(notePageProperties); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_TITLE, identity); } else { - note_.setLang(note.getLang()); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_TITLE, identity); + note_.setLang(note.getLang()); note_.setTitle(note.getTitle()); note_.setProperties(notePageProperties); } @@ -799,8 +799,8 @@ public Response updateNoteById(@Parameter(description = "Note id", required = tr note_.setProperties(notePageProperties); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_CONTENT, identity); } else { - note_.setLang(note.getLang()); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_CONTENT, identity); + note_.setLang(note.getLang()); note_.setContent(note.getContent()); note_.setProperties(notePageProperties); } @@ -815,8 +815,8 @@ public Response updateNoteById(@Parameter(description = "Note id", required = tr note_.setProperties(notePageProperties); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_PROPERTIES, identity); } else { - note_.setLang(note.getLang()); note_ = noteService.updateNote(note_, PageUpdateType.EDIT_PAGE_PROPERTIES, identity); + note_.setLang(note.getLang()); note_.setProperties(notePageProperties); } noteService.createVersionOfNote(note_, identity.getUserId()); diff --git a/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_en.properties b/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_en.properties index 07685c50a0..52dcd44da0 100644 --- a/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_en.properties +++ b/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_en.properties @@ -65,6 +65,13 @@ notes.featuredImage.remove.error.message=Error while removing featured image notes.featuredImage.remove.success.message=Featured image removed successfully notes.featuredImage.size.error.message=Featured image size should be less or equals to 20MB +notes.publication.publish.label=Publish +notes.publication.label=Choose your publication options +notes.publication.check.properties.label=Check the teaser +notes.publication.publish.next.label=Next + + + popup.confirm=Confirm popup.msg.confirmation=Confirmation popup.confirmation.delete=Delete the note diff --git a/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_fr.properties b/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_fr.properties index 1fddf24dba..69324a364d 100644 --- a/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_fr.properties +++ b/notes-webapp/src/main/resources/locale/portlet/notes/notesPortlet_fr.properties @@ -64,6 +64,11 @@ notes.featuredImage.remove.error.message=Erreur lors de la suppression de l'illu notes.featuredImage.remove.success.message=Illustration supprimée avec succès notes.featuredImage.size.error.message=La taille de l'illustration doit être inférieure ou égale à 20Mo +notes.publication.publish.label=Publier +notes.publication.label=Choisir les options de publication +notes.publication.check.properties.label=Vérifier l'accroche +notes.publication.publish.next.label=Suivant + popup.confirm=Confirmer popup.msg.confirmation=Confirmation popup.confirmation.delete=Delete the note diff --git a/notes-webapp/src/main/webapp/WEB-INF/conf/configuration.xml b/notes-webapp/src/main/webapp/WEB-INF/conf/configuration.xml index e5c8abd60f..2190a629d8 100644 --- a/notes-webapp/src/main/webapp/WEB-INF/conf/configuration.xml +++ b/notes-webapp/src/main/webapp/WEB-INF/conf/configuration.xml @@ -33,5 +33,6 @@ war:/conf/wiki/ckeditor-configuration.xml war:/conf/wiki/metadata-configuration.xml war:/conf/wiki/notification-configuration.xml + war:/conf/wiki/feature-flags-configuration.xml diff --git a/notes-webapp/src/main/webapp/WEB-INF/conf/wiki/feature-flags-configuration.xml b/notes-webapp/src/main/webapp/WEB-INF/conf/wiki/feature-flags-configuration.xml new file mode 100644 index 0000000000..112f9b2bba --- /dev/null +++ b/notes-webapp/src/main/webapp/WEB-INF/conf/wiki/feature-flags-configuration.xml @@ -0,0 +1,52 @@ + + + + + NotesEditorPublicationDrawerFeatureProperties + org.exoplatform.container.ExtendedPropertyConfigurator + + + NotesEditorPublicationDrawerFeatureProperties + Publication drawer Feature enablement flag + + + + + + + org.exoplatform.groovyscript.text.TemplateService + + UIPortalApplication-head + addTemplateExtension + org.exoplatform.groovyscript.text.TemplateExtensionPlugin + + + templates + The list of templates to include in HTML Page Header with UIPortalApplication.gtmpl + war:/groovy/webui/workspace/UINotesHeadTemplate.gtmpl + + + + + diff --git a/notes-webapp/src/main/webapp/groovy/webui/workspace/UINotesHeadTemplate.gtmpl b/notes-webapp/src/main/webapp/groovy/webui/workspace/UINotesHeadTemplate.gtmpl new file mode 100644 index 0000000000..9d7999e631 --- /dev/null +++ b/notes-webapp/src/main/webapp/groovy/webui/workspace/UINotesHeadTemplate.gtmpl @@ -0,0 +1,10 @@ +<% + import org.exoplatform.commons.api.settings.ExoFeatureService; + def rcontext = _ctx.getRequestContext(); + ExoFeatureService featureService = uicomponent.getApplicationComponent(ExoFeatureService.class); + def userName = rcontext.getRemoteUser(); +%> + + diff --git a/notes-webapp/src/main/webapp/skin/less/notes/notes.less b/notes-webapp/src/main/webapp/skin/less/notes/notes.less index ca30c2f91a..eb15d3f0eb 100644 --- a/notes-webapp/src/main/webapp/skin/less/notes/notes.less +++ b/notes-webapp/src/main/webapp/skin/less/notes/notes.less @@ -212,7 +212,7 @@ } } -#editorMetadataDrawer { +#editorMetadataDrawer, #editorPublicationDrawer { .add-image-area, .image-preview { background-color: @primaryBackground !important; diff --git a/notes-webapp/src/main/webapp/vue-app/notes-editor/components/NotesEditorDashboard.vue b/notes-webapp/src/main/webapp/vue-app/notes-editor/components/NotesEditorDashboard.vue index 2e3bf4cc0b..412a52e4a2 100644 --- a/notes-webapp/src/main/webapp/vue-app/notes-editor/components/NotesEditorDashboard.vue +++ b/notes-webapp/src/main/webapp/vue-app/notes-editor/components/NotesEditorDashboard.vue @@ -550,7 +550,7 @@ export default { if (draftNote.properties) { draftNote.properties.draft = true; if (this.newTranslation && !this.featuredImageUpdated) { - draftNote.properties.featuredImage = null; + draftNote.properties.featuredImage = {}; } } this.$notesService.saveDraftNote(draftNote, this.parentPageId).then(savedDraftNote => { diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteEditorMetadataDrawer.vue b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteEditorMetadataDrawer.vue deleted file mode 100644 index 970319b5bb..0000000000 --- a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteEditorMetadataDrawer.vue +++ /dev/null @@ -1,310 +0,0 @@ - - - - - diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteFullRichEditor.vue b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteFullRichEditor.vue index 7a5b434f8a..7b894e9ddf 100644 --- a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteFullRichEditor.vue +++ b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteFullRichEditor.vue @@ -30,7 +30,7 @@ :selected-language="selectedLanguage" :translations="translations" :is-mobile="isMobile" - :post-key="postKey" + :post-key="postKey + enablePostKeys" :draft-saving-status="draftSavingStatus" :publish-button-text="publishButtonText" :lang-button-tooltip-text="langButtonTooltipText" @@ -78,6 +78,13 @@ ref="featuredImageDrawer" :note="noteObject" :has-featured-image="hasFeaturedImage" /> + @@ -90,7 +97,9 @@ export default { initialized: false, instanceReady: false, noteTitleMaxLength: 500, - updatingProperties: null + updatingProperties: false, + enablePostKeys: 0, + isPublishing: false }; }, props: { @@ -189,14 +198,15 @@ export default { imagesDownloadFolder: { type: String, default: 'DRIVE_ROOT_NODE/notes/images' + }, + publicationEnabled: { + type: Boolean, + default: false } }, watch: { 'noteObject.title': function(newVal, oldVal) { - if (newVal.length > this.noteTitleMaxLength) { - this.displayNoteTitleMaxLengthCheckAlert(); - this.noteObject.title = oldVal; - } + this.displayNoteTitleMaxLengthCheckAlert(newVal, oldVal); this.updateData(); }, 'noteObject.content': function () { @@ -228,6 +238,18 @@ export default { }, saveNoteButtonDisabled() { return this.updatingProperties || this.saveButtonDisabled; + }, + newPageDraft() { + return !this.noteObject?.id || (this.noteObject?.draftPage && !this.noteObject?.targetPageId); + }, + editMode() { + return this.noteObject?.id && !this.newPageDraft; + }, + isTranslation() { + return !!this.noteObject?.lang; + }, + newPublicationDrawerEnabled() { + return eXo?.env?.portal?.newPublicationDrawerEnabled; } }, created() { @@ -241,6 +263,9 @@ export default { document.addEventListener('note-custom-plugins', this.openCustomPluginsDrawer); }, methods: { + setPublishing(publishing) { + this.isPublishing = publishing; + }, metadataUpdated(properties) { this.updatingProperties = true; this.noteObject.properties = properties; @@ -249,7 +274,7 @@ export default { this.autoSave(); this.waitForNoteMetadataUpdate(); } else { - this.updatingProperties = null; + this.updatingProperties = false; } }, editorClosed(){ @@ -335,8 +360,20 @@ export default { }, 200); } }, - postNote(toPublish) { - this.$emit('post-note', toPublish); + postNote() { + if (this.newPublicationDrawerEnabled && this.publicationEnabled + && !this.isTranslation && !this.editMode) { + this.openPublicationDrawer(this.noteObject); + return; + } + this.postAndPublishNote(); + }, + postAndPublishNote(note) { + if (this.newPublicationDrawerEnabled) { + this.noteObject = note; + this.updateData(); + } + this.$emit('post-note', false); }, resetEditorData() { this.noteObject.title = null; @@ -508,6 +545,12 @@ export default { isImageDrawerClosed() { return this.$refs.featuredImageDrawer.isClosed(); }, + openPublicationDrawer() { + this.$refs.editorPublicationDrawer.open(this.noteObject); + }, + publicationDrawerClosed() { + this.enablePostKeys ++; + }, openMetadataDrawer() { this.$refs.editorMetadataDrawer.open(this.noteObject); }, @@ -517,16 +560,18 @@ export default { alertMessage: detail?.message, }})); }, - displayNoteTitleMaxLengthCheckAlert(){ - const messageObject = { - type: 'warning', - message: this.$t('notes.title.max.length.warning.message', {0: this.noteTitleMaxLength}) - }; - this.displayAlert(messageObject); + displayNoteTitleMaxLengthCheckAlert(newTitle, oldTitle) { + if (newTitle?.length > this.noteTitleMaxLength) { + this.noteObject.title = oldTitle; + this.displayAlert({ + type: 'warning', + message: this.$t('notes.title.max.length.warning.message', {0: this.noteTitleMaxLength}) + }); + } }, waitForNoteMetadataUpdate() { setTimeout(() => { - this.updatingProperties = null; + this.updatingProperties = false; }, 1000); } } diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteEditorFeaturedImageDrawer.vue b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteEditorFeaturedImageDrawer.vue similarity index 100% rename from notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/NoteEditorFeaturedImageDrawer.vue rename to notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteEditorFeaturedImageDrawer.vue diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteEditorMetadataDrawer.vue b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteEditorMetadataDrawer.vue new file mode 100644 index 0000000000..89fd086cb0 --- /dev/null +++ b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteEditorMetadataDrawer.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteMetadataPropertiesForm.vue b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteMetadataPropertiesForm.vue new file mode 100644 index 0000000000..498ab83a11 --- /dev/null +++ b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-properties/NoteMetadataPropertiesForm.vue @@ -0,0 +1,272 @@ + + + + diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-publication/NotePublicationDrawer.vue b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-publication/NotePublicationDrawer.vue new file mode 100644 index 0000000000..56b03f06b7 --- /dev/null +++ b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/components/note-publication/NotePublicationDrawer.vue @@ -0,0 +1,238 @@ + + + + + diff --git a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/initComponents.js b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/initComponents.js index 91112ea135..55c0e4f829 100644 --- a/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/initComponents.js +++ b/notes-webapp/src/main/webapp/vue-app/notes-rich-editor/initComponents.js @@ -3,8 +3,10 @@ import TranslationsEditBar from '../notes-rich-editor/components/TranslationsEdi import NoteTreeviewDrawer from '../notes/components/NoteTreeviewDrawer.vue'; import NoteEditorTopBar from '../notes-rich-editor/components/NoteEditorTopBar.vue'; import NoteFullRichEditor from './components/NoteFullRichEditor.vue'; -import NoteEditorMetadataDrawer from './components/NoteEditorMetadataDrawer.vue'; -import NoteEditorFeaturedImageDrawer from './components/NoteEditorFeaturedImageDrawer.vue'; +import NoteEditorMetadataDrawer from './components/note-properties/NoteEditorMetadataDrawer.vue'; +import NoteEditorFeaturedImageDrawer from './components/note-properties/NoteEditorFeaturedImageDrawer.vue'; +import NotePublicationDrawer from './components/note-publication/NotePublicationDrawer.vue'; +import NoteMetadataPropertiesForm from './components/note-properties/NoteMetadataPropertiesForm.vue'; const components = { 'note-custom-plugins': NoteCustomPlugins, @@ -13,7 +15,9 @@ const components = { 'note-editor-top-bar': NoteEditorTopBar, 'note-full-rich-editor': NoteFullRichEditor, 'note-editor-metadata-drawer': NoteEditorMetadataDrawer, - 'note-editor-featured-image-drawer': NoteEditorFeaturedImageDrawer + 'note-editor-featured-image-drawer': NoteEditorFeaturedImageDrawer, + 'note-publication-drawer': NotePublicationDrawer, + 'note-metadata-properties-form': NoteMetadataPropertiesForm }; for (const key in components) {