diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-21 02:50:22 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-21 02:50:22 +0300 |
commit | 9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch) | |
tree | 70467ae3692a0e35e5ea56bcb803eb512a10bedb /app/assets/javascripts/pages/shared/wikis | |
parent | 4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff) |
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'app/assets/javascripts/pages/shared/wikis')
3 files changed, 276 insertions, 75 deletions
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue new file mode 100644 index 00000000000..6afc33ec8a5 --- /dev/null +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -0,0 +1,253 @@ +<script> +import { GlForm, GlIcon, GlLink, GlButton, GlSprintf } from '@gitlab/ui'; +import csrf from '~/lib/utils/csrf'; +import { setUrlFragment } from '~/lib/utils/url_utility'; +import { __, s__, sprintf } from '~/locale'; +import MarkdownField from '~/vue_shared/components/markdown/field.vue'; + +const MARKDOWN_LINK_TEXT = { + markdown: '[Link Title](page-slug)', + rdoc: '{Link title}[link:page-slug]', + asciidoc: 'link:page-slug[Link title]', + org: '[[page-slug]]', +}; + +export default { + components: { + GlForm, + GlSprintf, + GlIcon, + GlLink, + GlButton, + MarkdownField, + }, + inject: ['formatOptions', 'pageInfo'], + data() { + return { + title: this.pageInfo.title?.trim() || '', + format: this.pageInfo.format || 'markdown', + content: this.pageInfo.content?.trim() || '', + commitMessage: '', + }; + }, + computed: { + csrfToken() { + return csrf.token; + }, + formAction() { + return this.pageInfo.persisted ? this.pageInfo.path : this.pageInfo.createPath; + }, + helpPath() { + return setUrlFragment( + this.pageInfo.helpPath, + this.pageInfo.persisted ? 'move-a-wiki-page' : 'create-a-new-wiki-page', + ); + }, + commitMessageI18n() { + return this.pageInfo.persisted + ? s__('WikiPage|Update %{pageTitle}') + : s__('WikiPage|Create %{pageTitle}'); + }, + linkExample() { + return MARKDOWN_LINK_TEXT[this.format]; + }, + submitButtonText() { + if (this.pageInfo.persisted) return __('Save changes'); + return s__('WikiPage|Create page'); + }, + cancelFormPath() { + if (this.pageInfo.persisted) return this.pageInfo.path; + return this.pageInfo.wikiPath; + }, + wikiSpecificMarkdownHelpPath() { + return setUrlFragment(this.pageInfo.markdownHelpPath, 'wiki-specific-markdown'); + }, + }, + mounted() { + this.updateCommitMessage(); + }, + methods: { + handleFormSubmit() { + window.removeEventListener('beforeunload', this.onBeforeUnload); + }, + + handleContentChange() { + window.addEventListener('beforeunload', this.onBeforeUnload); + }, + + onBeforeUnload() { + return ''; + }, + + updateCommitMessage() { + if (!this.title) return; + + // Replace hyphens with spaces + const newTitle = this.title.replace(/-+/g, ' '); + + const newCommitMessage = sprintf(this.commitMessageI18n, { pageTitle: newTitle }, false); + this.commitMessage = newCommitMessage; + }, + }, +}; +</script> + +<template> + <gl-form + :action="formAction" + method="post" + class="wiki-form common-note-form gl-mt-3 js-quick-submit" + @submit="handleFormSubmit" + > + <input :value="csrfToken" type="hidden" name="authenticity_token" /> + <input v-if="pageInfo.persisted" type="hidden" name="_method" value="put" /> + <input + :v-if="pageInfo.persisted" + type="hidden" + name="wiki[last_commit_sha]" + :value="pageInfo.lastCommitSha" + /> + <div class="form-group row"> + <div class="col-sm-2 col-form-label"> + <label class="control-label-full-width" for="wiki_title">{{ s__('WikiPage|Title') }}</label> + </div> + <div class="col-sm-10"> + <input + id="wiki_title" + v-model.trim="title" + name="wiki[title]" + type="text" + class="form-control" + data-qa-selector="wiki_title_textbox" + :required="true" + :autofocus="!pageInfo.persisted" + :placeholder="s__('WikiPage|Page title')" + @input="updateCommitMessage" + /> + <span class="gl-display-inline-block gl-max-w-full gl-mt-2 gl-text-gray-600"> + <gl-icon class="gl-mr-n1" name="bulb" /> + {{ + pageInfo.persisted + ? s__( + 'WikiPage|Tip: You can move this page by adding the path to the beginning of the title.', + ) + : s__( + 'WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories.', + ) + }} + <gl-link :href="helpPath" target="_blank" data-testid="wiki-title-help-link" + ><gl-icon name="question-o" /> {{ __('More Information.') }}</gl-link + > + </span> + </div> + </div> + <div class="form-group row"> + <div class="col-sm-2 col-form-label"> + <label class="control-label-full-width" for="wiki_format">{{ + s__('WikiPage|Format') + }}</label> + </div> + <div class="col-sm-10"> + <select id="wiki_format" v-model="format" class="form-control" name="wiki[format]"> + <option v-for="(key, label) of formatOptions" :key="key" :value="key"> + {{ label }} + </option> + </select> + </div> + </div> + <div class="form-group row"> + <div class="col-sm-2 col-form-label"> + <label class="control-label-full-width" for="wiki_content">{{ + s__('WikiPage|Content') + }}</label> + </div> + <div class="col-sm-10"> + <markdown-field + :markdown-preview-path="pageInfo.markdownPreviewPath" + :can-attach-file="true" + :enable-autocomplete="true" + :textarea-value="content" + :markdown-docs-path="pageInfo.markdownHelpPath" + :uploads-path="pageInfo.uploadsPath" + class="bordered-box" + > + <template #textarea> + <textarea + id="wiki_content" + ref="textarea" + v-model.trim="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="s__('WikiPage|Content')" + :placeholder="s__('WikiPage|Write your content or drag files hereā¦')" + @input="handleContentChange" + > + </textarea> + </template> + </markdown-field> + <div class="clearfix"></div> + <div class="error-alert"></div> + + <div class="form-text gl-text-gray-600"> + <gl-sprintf + :message=" + s__( + 'WikiPage|To link to a (new) page, simply type %{linkExample}. More examples are in the %{linkStart}documentation%{linkEnd}.', + ) + " + > + <template #linkExample + ><code>{{ linkExample }}</code></template + > + <template + #link="// eslint-disable-next-line vue/no-template-shadow + { content }" + ><gl-link + :href="wikiSpecificMarkdownHelpPath" + target="_blank" + data-testid="wiki-markdown-help-link" + >{{ content }}</gl-link + ></template + > + </gl-sprintf> + </div> + </div> + </div> + <div class="form-group row"> + <div class="col-sm-2 col-form-label"> + <label class="control-label-full-width" for="wiki_message">{{ + s__('WikiPage|Commit message') + }}</label> + </div> + <div class="col-sm-10"> + <input + id="wiki_message" + v-model.trim="commitMessage" + name="wiki[message]" + type="text" + class="form-control" + data-qa-selector="wiki_message_textbox" + :placeholder="s__('WikiPage|Commit message')" + /> + </div> + </div> + <div class="form-actions"> + <gl-button + category="primary" + variant="confirm" + type="submit" + data-qa-selector="wiki_submit_button" + data-testid="wiki-submit-button" + :disabled="!content || !title" + >{{ submitButtonText }}</gl-button + > + <gl-button :href="cancelFormPath" class="float-right" data-testid="wiki-cancel-button">{{ + __('Cancel') + }}</gl-button> + </div> + </gl-form> +</template> diff --git a/app/assets/javascripts/pages/shared/wikis/index.js b/app/assets/javascripts/pages/shared/wikis/index.js index c382a372260..c04cd0b3fa4 100644 --- a/app/assets/javascripts/pages/shared/wikis/index.js +++ b/app/assets/javascripts/pages/shared/wikis/index.js @@ -1,12 +1,14 @@ import $ from 'jquery'; import Vue from 'vue'; import ShortcutsWiki from '~/behaviors/shortcuts/shortcuts_wiki'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import csrf from '~/lib/utils/csrf'; import Translate from '~/vue_shared/translate'; import GLForm from '../../../gl_form'; import ZenMode from '../../../zen_mode'; import deleteWikiModal from './components/delete_wiki_modal.vue'; import wikiAlert from './components/wiki_alert.vue'; +import wikiForm from './components/wiki_form.vue'; import Wikis from './wikis'; const createModalVueApp = () => { @@ -61,7 +63,28 @@ const createAlertVueApp = () => { } }; +const createWikiFormApp = () => { + const el = document.getElementById('js-wiki-form'); + + if (el) { + const { pageInfo, formatOptions } = el.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el, + provide: { + formatOptions: JSON.parse(formatOptions), + pageInfo: convertObjectPropsToCamelCase(JSON.parse(pageInfo)), + }, + render(createElement) { + return createElement(wikiForm); + }, + }); + } +}; + export default () => { createModalVueApp(); createAlertVueApp(); + createWikiFormApp(); }; diff --git a/app/assets/javascripts/pages/shared/wikis/wikis.js b/app/assets/javascripts/pages/shared/wikis/wikis.js index 4b4d2f7d238..7d0b0c90c8d 100644 --- a/app/assets/javascripts/pages/shared/wikis/wikis.js +++ b/app/assets/javascripts/pages/shared/wikis/wikis.js @@ -1,15 +1,7 @@ import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; -import { s__, sprintf } from '~/locale'; import Tracking from '~/tracking'; import showToast from '~/vue_shared/plugins/global_toast'; -const MARKDOWN_LINK_TEXT = { - markdown: '[Link Title](page-slug)', - rdoc: '{Link title}[link:page-slug]', - asciidoc: 'link:page-slug[Link title]', - org: '[[page-slug]]', -}; - const TRACKING_EVENT_NAME = 'view_wiki_page'; const TRACKING_CONTEXT_SCHEMA = 'iglu:com.gitlab/wiki_page_context/jsonschema/1-0-1'; @@ -23,78 +15,11 @@ export default class Wikis { sidebarToggles[i].addEventListener('click', (e) => this.handleToggleSidebar(e)); } - this.isNewWikiPage = Boolean(document.querySelector('.js-new-wiki-page')); - this.editTitleInput = document.querySelector('form.wiki-form #wiki_title'); - this.commitMessageInput = document.querySelector('form.wiki-form #wiki_message'); - this.submitButton = document.querySelector('.js-wiki-btn-submit'); - this.commitMessageI18n = this.isNewWikiPage - ? s__('WikiPageCreate|Create %{pageTitle}') - : s__('WikiPageEdit|Update %{pageTitle}'); - - if (this.editTitleInput) { - // Initialize the commit message on load - if (this.editTitleInput.value) this.setWikiCommitMessage(this.editTitleInput.value); - - // Set the commit message as the page title is changed - this.editTitleInput.addEventListener('keyup', (e) => this.handleWikiTitleChange(e)); - } - window.addEventListener('resize', () => this.renderSidebar()); this.renderSidebar(); - const changeFormatSelect = document.querySelector('#wiki_format'); - const linkExample = document.querySelector('.js-markup-link-example'); - - if (changeFormatSelect) { - changeFormatSelect.addEventListener('change', (e) => { - linkExample.innerHTML = MARKDOWN_LINK_TEXT[e.target.value]; - }); - } - - this.wikiTextarea = document.querySelector('form.wiki-form #wiki_content'); - const wikiForm = document.querySelector('form.wiki-form'); - - if (this.wikiTextarea) { - this.wikiTextarea.addEventListener('input', () => this.handleWikiContentChange()); - - wikiForm.addEventListener('submit', () => { - window.onbeforeunload = null; - }); - } - Wikis.trackPageView(); Wikis.showToasts(); - - this.updateSubmitButton(); - } - - handleWikiContentChange() { - this.updateSubmitButton(); - - window.onbeforeunload = () => ''; - } - - handleWikiTitleChange(e) { - this.updateSubmitButton(); - this.setWikiCommitMessage(e.target.value); - } - - updateSubmitButton() { - if (!this.wikiTextarea) return; - - const isEnabled = Boolean(this.wikiTextarea.value.trim() && this.editTitleInput.value.trim()); - if (isEnabled) this.submitButton.removeAttribute('disabled'); - else this.submitButton.setAttribute('disabled', 'true'); - } - - setWikiCommitMessage(rawTitle) { - let title = rawTitle; - - // Replace hyphens with spaces - if (title) title = title.replace(/-+/g, ' '); - - const newCommitMessage = sprintf(this.commitMessageI18n, { pageTitle: title }, false); - this.commitMessageInput.value = newCommitMessage; } handleToggleSidebar(e) { |