diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-20 12:40:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-20 12:40:42 +0300 |
commit | ee664acb356f8123f4f6b00b73c1e1cf0866c7fb (patch) | |
tree | f8479f94a28f66654c6a4f6fb99bad6b4e86a40e /app/assets/javascripts/pages/shared/wikis | |
parent | 62f7d5c5b69180e82ae8196b7b429eeffc8e7b4f (diff) |
Add latest changes from gitlab-org/gitlab@15-5-stable-eev15.5.0-rc42
Diffstat (limited to 'app/assets/javascripts/pages/shared/wikis')
-rw-r--r-- | app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue | 4 | ||||
-rw-r--r-- | app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue | 221 |
2 files changed, 93 insertions, 132 deletions
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue index 10b95fd6f3c..b72579276e8 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_content.vue @@ -1,6 +1,6 @@ <script> import { GlSkeletonLoader, GlSafeHtmlDirective, GlAlert } from '@gitlab/ui'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { __ } from '~/locale'; import axios from '~/lib/utils/axios_utils'; import { handleLocationHash } from '~/lib/utils/common_utils'; @@ -47,7 +47,7 @@ export default { handleLocationHash(); }) .catch(() => - createFlash({ + createAlert({ message: this.$options.i18n.renderingContentFailed, }), ); diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue index 9acc1cb62a1..7b9656de362 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -8,21 +8,19 @@ import { GlFormGroup, GlFormInput, GlFormSelect, - GlSegmentedControl, } from '@gitlab/ui'; -import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; -import axios from '~/lib/utils/axios_utils'; +import { getDraft, clearDraft, updateDraft } from '~/lib/utils/autosave'; import csrf from '~/lib/utils/csrf'; import { setUrlFragment } from '~/lib/utils/url_utility'; import { s__, sprintf } from '~/locale'; import Tracking from '~/tracking'; -import MarkdownField from '~/vue_shared/components/markdown/field.vue'; +import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue'; import { - CONTENT_EDITOR_LOADED_ACTION, SAVED_USING_CONTENT_EDITOR_ACTION, WIKI_CONTENT_EDITOR_TRACKING_LABEL, WIKI_FORMAT_LABEL, WIKI_FORMAT_UPDATED_ACTION, + CONTENT_EDITOR_LOADED_ACTION, } from '../constants'; const trackingMixin = Tracking.mixin({ @@ -36,6 +34,29 @@ const MARKDOWN_LINK_TEXT = { org: '[[page-slug]]', }; +function getPagePath(pageInfo) { + return pageInfo.persisted ? pageInfo.path : pageInfo.createPath; +} + +const autosaveKey = (pageInfo, field) => { + const path = pageInfo.persisted ? pageInfo.path : pageInfo.createPath; + + return `${path}/${field}`; +}; + +const titleAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'title'); +const formatAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'format'); +const contentAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'content'); +const commitAutosaveKey = (pageInfo) => autosaveKey(pageInfo, 'commit'); + +const getTitle = (pageInfo) => getDraft(titleAutosaveKey(pageInfo)) || pageInfo.title?.trim() || ''; +const getFormat = (pageInfo) => + getDraft(formatAutosaveKey(pageInfo)) || pageInfo.format || 'markdown'; +const getContent = (pageInfo) => getDraft(contentAutosaveKey(pageInfo)) || pageInfo.content || ''; +const getCommitMessage = (pageInfo) => + getDraft(commitAutosaveKey(pageInfo)) || pageInfo.commitMessage || ''; +const getIsFormDirty = (pageInfo) => Boolean(getDraft(titleAutosaveKey(pageInfo))); + export default { i18n: { title: { @@ -74,10 +95,6 @@ export default { }, cancel: s__('WikiPage|Cancel'), }, - switchEditingControlOptions: [ - { text: s__('Wiki Page|Source'), value: 'source' }, - { text: s__('Wiki Page|Rich text'), value: 'richText' }, - ], components: { GlIcon, GlForm, @@ -87,26 +104,21 @@ export default { GlSprintf, GlLink, GlButton, - GlSegmentedControl, - MarkdownField, - LocalStorageSync, - ContentEditor: () => - import( - /* webpackChunkName: 'content_editor' */ '~/content_editor/components/content_editor.vue' - ), + MarkdownEditor, }, mixins: [trackingMixin], inject: ['formatOptions', 'pageInfo'], data() { return { editingMode: 'source', - title: this.pageInfo.title?.trim() || '', - format: this.pageInfo.format || 'markdown', - content: this.pageInfo.content || '', - commitMessage: '', - isDirty: false, + title: getTitle(this.pageInfo), + format: getFormat(this.pageInfo), + content: getContent(this.pageInfo), + commitMessage: getCommitMessage(this.pageInfo), contentEditorEmpty: false, + isContentEditorActive: false, switchEditingControlDisabled: false, + isFormDirty: getIsFormDirty(this.pageInfo), }; }, computed: { @@ -117,7 +129,7 @@ export default { return csrf.token; }, formAction() { - return this.pageInfo.persisted ? this.pageInfo.path : this.pageInfo.createPath; + return getPagePath(this.pageInfo); }, helpPath() { return setUrlFragment( @@ -162,15 +174,9 @@ export default { disableSubmitButton() { return this.noContent || !this.title; }, - isContentEditorActive() { - return this.isMarkdownFormat && this.useContentEditor; - }, - useContentEditor() { - return this.editingMode === 'richText'; - }, }, mounted() { - this.updateCommitMessage(); + if (!this.commitMessage) this.updateCommitMessage(); window.addEventListener('beforeunload', this.onPageUnload); }, @@ -178,51 +184,45 @@ export default { window.removeEventListener('beforeunload', this.onPageUnload); }, methods: { - renderMarkdown(content) { - return axios - .post(this.pageInfo.markdownPreviewPath, { text: content }) - .then(({ data }) => data.body); - }, - - setEditingMode(editingMode) { - this.editingMode = editingMode; - }, - async handleFormSubmit(e) { - e.preventDefault(); + this.isFormDirty = false; - if (this.useContentEditor) { - this.trackFormSubmit(); - } + e.preventDefault(); + this.trackFormSubmit(); this.trackWikiFormat(); // Wait until form field values are refreshed await this.$nextTick(); e.target.submit(); + }, - this.isDirty = false; + updateDrafts() { + updateDraft(titleAutosaveKey(this.pageInfo), this.title); + updateDraft(formatAutosaveKey(this.pageInfo), this.format); + updateDraft(contentAutosaveKey(this.pageInfo), this.content); + updateDraft(commitAutosaveKey(this.pageInfo), this.commitMessage); }, - handleContentChange() { - this.isDirty = true; + clearDrafts() { + clearDraft(titleAutosaveKey(this.pageInfo)); + clearDraft(formatAutosaveKey(this.pageInfo)); + clearDraft(contentAutosaveKey(this.pageInfo)); + clearDraft(commitAutosaveKey(this.pageInfo)); }, - handleContentEditorChange({ empty, markdown, changed }) { + handleContentEditorChange({ empty, markdown }) { this.contentEditorEmpty = empty; - this.isDirty = changed; this.content = markdown; }, - onPageUnload(event) { - if (!this.isDirty) return undefined; - - event.preventDefault(); - - // eslint-disable-next-line no-param-reassign - event.returnValue = ''; - return ''; + onPageUnload() { + if (this.isFormDirty) { + this.updateDrafts(); + } else { + this.clearDrafts(); + } }, updateCommitMessage() { @@ -235,8 +235,13 @@ export default { this.commitMessage = newCommitMessage; }, - trackContentEditorLoaded() { - this.track(CONTENT_EDITOR_LOADED_ACTION); + notifyContentEditorActive() { + this.isContentEditorActive = true; + this.trackContentEditorLoaded(); + }, + + notifyContentEditorInactive() { + this.isContentEditorActive = false; }, trackFormSubmit() { @@ -256,12 +261,12 @@ export default { }); }, - enableSwitchEditingControl() { - this.switchEditingControlDisabled = false; + trackContentEditorLoaded() { + this.track(CONTENT_EDITOR_LOADED_ACTION); }, - disableSwitchEditingControl() { - this.switchEditingControlDisabled = true; + submitFormWithShortcut() { + this.$refs.form.submit(); }, }, }; @@ -269,10 +274,12 @@ export default { <template> <gl-form + ref="form" :action="formAction" method="post" class="wiki-form common-note-form gl-mt-3 js-quick-submit" @submit="handleFormSubmit" + @input="isFormDirty = true" > <input :value="csrfToken" type="hidden" name="authenticity_token" /> <input v-if="pageInfo.persisted" type="hidden" name="_method" value="put" /> @@ -329,74 +336,23 @@ export default { <div class="row" data-testid="wiki-form-content-fieldset"> <div class="col-sm-12 row-sm-5"> <gl-form-group> - <div v-if="isMarkdownFormat" class="gl-display-flex gl-justify-content-start gl-mb-3"> - <gl-segmented-control - data-testid="toggle-editing-mode-button" - data-qa-selector="editing_mode_button" - class="gl-display-flex" - :checked="editingMode" - :options="$options.switchEditingControlOptions" - :disabled="switchEditingControlDisabled" - @input="setEditingMode" - /> - </div> - <local-storage-sync - storage-key="gl-wiki-content-editor-enabled" - :value="editingMode" - @input="setEditingMode" - /> - <markdown-field - v-if="!isContentEditorActive" - :markdown-preview-path="pageInfo.markdownPreviewPath" - :can-attach-file="true" - :enable-autocomplete="true" - :textarea-value="content" + <markdown-editor + v-model="content" + :render-markdown-path="pageInfo.markdownPreviewPath" :markdown-docs-path="pageInfo.markdownHelpPath" :uploads-path="pageInfo.uploadsPath" + :enable-content-editor="isMarkdownFormat" :enable-preview="isMarkdownFormat" - class="bordered-box" - > - <template #textarea> - <textarea - id="wiki_content" - ref="textarea" - v-model="content" - name="wiki[content]" - class="note-textarea js-gfm-input js-autosize markdown-area" - dir="auto" - data-supports-quick-actions="false" - data-qa-selector="wiki_content_textarea" - :autofocus="pageInfo.persisted" - :aria-label="$options.i18n.content.label" - :placeholder="$options.i18n.content.placeholder" - @input="handleContentChange" - > - </textarea> - </template> - </markdown-field> - <div v-if="isContentEditorActive"> - <content-editor - :render-markdown="renderMarkdown" - :uploads-path="pageInfo.uploadsPath" - :markdown="content" - @initialized="trackContentEditorLoaded" - @change="handleContentEditorChange" - @loading="disableSwitchEditingControl" - @loadingSuccess="enableSwitchEditingControl" - @loadingError="enableSwitchEditingControl" - /> - <input - id="wiki_content" - v-model.trim="content" - type="hidden" - name="wiki[content]" - data-qa-selector="wiki_hidden_content" - /> - </div> - - <div class="clearfix"></div> - <div class="error-alert"></div> - + :init-on-autofocus="pageInfo.persisted" + :form-field-placeholder="$options.i18n.content.placeholder" + :form-field-aria-label="$options.i18n.content.label" + form-field-id="wiki_content" + form-field-name="wiki[content]" + @contentEditor="notifyContentEditorActive" + @markdownField="notifyContentEditorInactive" + @keydown.ctrl.enter="submitFormShortcut" + @keydown.meta.enter="submitFormShortcut" + /> <div class="form-text gl-text-gray-600"> <gl-sprintf v-if="displayWikiSpecificMarkdownHelp" @@ -447,9 +403,14 @@ export default { :disabled="disableSubmitButton" >{{ submitButtonText }}</gl-button > - <gl-button data-testid="wiki-cancel-button" :href="cancelFormPath" class="float-right">{{ - $options.i18n.cancel - }}</gl-button> + <gl-button + data-testid="wiki-cancel-button" + :href="cancelFormPath" + class="float-right" + @click="isFormDirty = false" + > + {{ $options.i18n.cancel }}</gl-button + > </div> </gl-form> </template> |