diff options
Diffstat (limited to 'app/assets/javascripts/static_site_editor')
16 files changed, 447 insertions, 77 deletions
diff --git a/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue b/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue new file mode 100644 index 00000000000..9f75c65a316 --- /dev/null +++ b/app/assets/javascripts/static_site_editor/components/edit_meta_controls.vue @@ -0,0 +1,104 @@ +<script> +import { GlForm, GlFormGroup, GlFormInput, GlFormTextarea } from '@gitlab/ui'; +import AccessorUtilities from '~/lib/utils/accessor'; + +export default { + components: { + GlForm, + GlFormGroup, + GlFormInput, + GlFormTextarea, + }, + props: { + title: { + type: String, + required: true, + }, + description: { + type: String, + required: true, + }, + }, + data() { + return { + editable: { + title: this.title, + description: this.description, + }, + }; + }, + computed: { + editableStorageKey() { + return this.getId('local-storage', 'editable'); + }, + hasLocalStorage() { + return AccessorUtilities.isLocalStorageAccessSafe(); + }, + }, + mounted() { + this.initCachedEditable(); + this.preSelect(); + }, + methods: { + getId(type, key) { + return `sse-merge-request-meta-${type}-${key}`; + }, + initCachedEditable() { + if (this.hasLocalStorage) { + const cachedEditable = JSON.parse(localStorage.getItem(this.editableStorageKey)); + if (cachedEditable) { + this.editable = cachedEditable; + } + } + }, + preSelect() { + this.$nextTick(() => { + this.$refs.title.$el.select(); + }); + }, + resetCachedEditable() { + if (this.hasLocalStorage) { + window.localStorage.removeItem(this.editableStorageKey); + } + }, + onUpdate() { + const payload = { ...this.editable }; + this.$emit('updateSettings', payload); + + if (this.hasLocalStorage) { + window.localStorage.setItem(this.editableStorageKey, JSON.stringify(payload)); + } + }, + }, +}; +</script> + +<template> + <gl-form> + <gl-form-group + key="title" + :label="__('Brief title about the change')" + :label-for="getId('control', 'title')" + > + <gl-form-input + :id="getId('control', 'title')" + ref="title" + v-model.lazy="editable.title" + type="text" + @input="onUpdate" + /> + </gl-form-group> + + <gl-form-group + key="description" + :label="__('Goal of the changes and what reviewers should be aware of')" + :label-for="getId('control', 'description')" + > + <gl-form-textarea + :id="getId('control', 'description')" + v-model.lazy="editable.description" + @input="onUpdate" + /> + </gl-form-group> + </gl-form> +</template> diff --git a/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue b/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue new file mode 100644 index 00000000000..4e5245bd892 --- /dev/null +++ b/app/assets/javascripts/static_site_editor/components/edit_meta_modal.vue @@ -0,0 +1,85 @@ +<script> +import { GlModal } from '@gitlab/ui'; +import { __, s__, sprintf } from '~/locale'; + +import EditMetaControls from './edit_meta_controls.vue'; + +export default { + components: { + GlModal, + EditMetaControls, + }, + props: { + sourcePath: { + type: String, + required: true, + }, + }, + data() { + return { + mergeRequestMeta: { + title: sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), { + sourcePath: this.sourcePath, + }), + description: s__('StaticSiteEditor|Copy update'), + }, + }; + }, + computed: { + disabled() { + return this.mergeRequestMeta.title === ''; + }, + primaryProps() { + return { + text: __('Submit changes'), + attributes: [{ variant: 'success' }, { disabled: this.disabled }], + }; + }, + secondaryProps() { + return { + text: __('Keep editing'), + attributes: [{ variant: 'default' }], + }; + }, + }, + methods: { + hide() { + this.$refs.modal.hide(); + }, + show() { + this.$refs.modal.show(); + }, + onPrimary() { + this.$emit('primary', this.mergeRequestMeta); + this.$refs.editMetaControls.resetCachedEditable(); + }, + onSecondary() { + this.hide(); + }, + onUpdateSettings(mergeRequestMeta) { + this.mergeRequestMeta = { ...mergeRequestMeta }; + }, + }, +}; +</script> + +<template> + <gl-modal + ref="modal" + modal-id="edit-meta-modal" + :title="__('Submit your changes')" + :action-primary="primaryProps" + :action-secondary="secondaryProps" + size="sm" + @primary="onPrimary" + @secondary="onSecondary" + @hide="() => $emit('hide')" + > + <edit-meta-controls + ref="editMetaControls" + :title="mergeRequestMeta.title" + :description="mergeRequestMeta.description" + @updateSettings="onUpdateSettings" + /> + </gl-modal> +</template> diff --git a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue index 2d62964cb3b..3bb5a0b8fd5 100644 --- a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue +++ b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue @@ -41,7 +41,7 @@ export default { :disabled="savingChanges" @click="$emit('editSettings')" > - {{ __('Settings') }} + {{ __('Page settings') }} </gl-button> <gl-button ref="submit" @@ -50,7 +50,7 @@ export default { :loading="savingChanges" @click="$emit('submit')" > - {{ __('Submit changes') }} + {{ __('Submit changes...') }} </gl-button> </div> </div> diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js index 0a5d8c07ad9..cc68bc57bb0 100644 --- a/app/assets/javascripts/static_site_editor/graphql/index.js +++ b/app/assets/javascripts/static_site_editor/graphql/index.js @@ -4,6 +4,7 @@ import createDefaultClient from '~/lib/graphql'; import typeDefs from './typedefs.graphql'; import fileResolver from './resolvers/file'; import submitContentChangesResolver from './resolvers/submit_content_changes'; +import hasSubmittedChangesResolver from './resolvers/has_submitted_changes'; Vue.use(VueApollo); @@ -15,10 +16,12 @@ const createApolloProvider = appData => { }, Mutation: { submitContentChanges: submitContentChangesResolver, + hasSubmittedChanges: hasSubmittedChangesResolver, }, }, { typeDefs, + assumeImmutableResults: true, }, ); diff --git a/app/assets/javascripts/static_site_editor/graphql/mutations/has_submitted_changes.mutation.graphql b/app/assets/javascripts/static_site_editor/graphql/mutations/has_submitted_changes.mutation.graphql new file mode 100644 index 00000000000..1f47929556a --- /dev/null +++ b/app/assets/javascripts/static_site_editor/graphql/mutations/has_submitted_changes.mutation.graphql @@ -0,0 +1,5 @@ +mutation hasSubmittedChanges($input: HasSubmittedChangesInput) { + hasSubmittedChanges(input: $input) @client { + hasSubmittedChanges + } +} diff --git a/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql b/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql index 946d80efff0..9f4b0afe55f 100644 --- a/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql +++ b/app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql @@ -1,6 +1,7 @@ query appData { appData @client { isSupportedContent + hasSubmittedChanges project sourcePath username diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js new file mode 100644 index 00000000000..ea49b21eb0d --- /dev/null +++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js @@ -0,0 +1,25 @@ +import { produce } from 'immer'; +import query from '../queries/app_data.query.graphql'; + +const hasSubmittedChangesResolver = (_, { input: { hasSubmittedChanges } }, { cache }) => { + const oldData = cache.readQuery({ query }); + + const data = produce(oldData, draftState => { + // punctually modifying draftState as per immer docs upsets our linters + return { + ...draftState, + appData: { + __typename: 'AppData', + ...draftState.appData, + hasSubmittedChanges, + }, + }; + }); + + cache.writeQuery({ + query, + data, + }); +}; + +export default hasSubmittedChangesResolver; diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js index 0cb26f88785..4137ede49c6 100644 --- a/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js +++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js @@ -1,24 +1,34 @@ +import { produce } from 'immer'; import submitContentChanges from '../../services/submit_content_changes'; import savedContentMetaQuery from '../queries/saved_content_meta.query.graphql'; const submitContentChangesResolver = ( _, - { input: { project: projectId, username, sourcePath, content, images } }, + { input: { project: projectId, username, sourcePath, content, images, mergeRequestMeta } }, { cache }, ) => { - return submitContentChanges({ projectId, username, sourcePath, content, images }).then( - savedContentMeta => { - cache.writeQuery({ - query: savedContentMetaQuery, - data: { - savedContentMeta: { - __typename: 'SavedContentMeta', - ...savedContentMeta, - }, + return submitContentChanges({ + projectId, + username, + sourcePath, + content, + images, + mergeRequestMeta, + }).then(savedContentMeta => { + const data = produce(savedContentMeta, draftState => { + return { + savedContentMeta: { + __typename: 'SavedContentMeta', + ...draftState, }, - }); - }, - ); + }; + }); + + cache.writeQuery({ + query: savedContentMetaQuery, + data, + }); + }); }; export default submitContentChangesResolver; diff --git a/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql b/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql index 78cc1746cdb..0ded1722d26 100644 --- a/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql +++ b/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql @@ -16,12 +16,17 @@ type SavedContentMeta { type AppData { isSupportedContent: Boolean! + hasSubmittedChanges: Boolean! project: String! returnUrl: String sourcePath: String! username: String! } +input HasSubmittedChangesInput { + hasSubmittedChanges: Boolean! +} + input SubmitContentChangesInput { project: String! sourcePath: String! @@ -40,4 +45,5 @@ extend type Query { extend type Mutation { submitContentChanges(input: SubmitContentChangesInput!): SavedContentMeta + hasSubmittedChanges(input: HasSubmittedChangesInput!): AppData } diff --git a/app/assets/javascripts/static_site_editor/index.js b/app/assets/javascripts/static_site_editor/index.js index b7e5ea4eee3..fceef8f9084 100644 --- a/app/assets/javascripts/static_site_editor/index.js +++ b/app/assets/javascripts/static_site_editor/index.js @@ -12,13 +12,23 @@ const initStaticSiteEditor = el => { namespace, project, mergeRequestsIllustrationPath, + // NOTE: The following variables are not yet used, but are supported by the config file, + // so we are adding them here as a convenience for future use. + // eslint-disable-next-line no-unused-vars + staticSiteGenerator, + // eslint-disable-next-line no-unused-vars + imageUploadPath, + mounts, } = el.dataset; + // NOTE that the object in 'mounts' is a JSON string from the data attribute, so it must be parsed into an object. + // eslint-disable-next-line no-unused-vars + const mountsObject = JSON.parse(mounts); const { current_username: username } = window.gon; const returnUrl = el.dataset.returnUrl || null; - const router = createRouter(baseUrl); const apolloProvider = createApolloProvider({ isSupportedContent: parseBoolean(isSupportedContent), + hasSubmittedChanges: false, project: `${namespace}/${project}`, returnUrl, sourcePath, diff --git a/app/assets/javascripts/static_site_editor/pages/home.vue b/app/assets/javascripts/static_site_editor/pages/home.vue index eef2bd88f0e..27bd1c99ae2 100644 --- a/app/assets/javascripts/static_site_editor/pages/home.vue +++ b/app/assets/javascripts/static_site_editor/pages/home.vue @@ -1,13 +1,16 @@ <script> +import { deprecatedCreateFlash as createFlash } from '~/flash'; +import Tracking from '~/tracking'; + import SkeletonLoader from '../components/skeleton_loader.vue'; import EditArea from '../components/edit_area.vue'; +import EditMetaModal from '../components/edit_meta_modal.vue'; import InvalidContentMessage from '../components/invalid_content_message.vue'; import SubmitChangesError from '../components/submit_changes_error.vue'; import appDataQuery from '../graphql/queries/app_data.query.graphql'; import sourceContentQuery from '../graphql/queries/source_content.query.graphql'; +import hasSubmittedChangesMutation from '../graphql/mutations/has_submitted_changes.mutation.graphql'; import submitContentChangesMutation from '../graphql/mutations/submit_content_changes.mutation.graphql'; -import { deprecatedCreateFlash as createFlash } from '~/flash'; -import Tracking from '~/tracking'; import { LOAD_CONTENT_ERROR, TRACKING_ACTION_INITIALIZE_EDITOR } from '../constants'; import { SUCCESS_ROUTE } from '../router/constants'; @@ -15,6 +18,7 @@ export default { components: { SkeletonLoader, EditArea, + EditMetaModal, InvalidContentMessage, SubmitChangesError, }, @@ -48,6 +52,7 @@ export default { data() { return { content: null, + images: null, submitChangesError: null, isSavingChanges: false, }; @@ -64,15 +69,34 @@ export default { Tracking.event(document.body.dataset.page, TRACKING_ACTION_INITIALIZE_EDITOR); }, methods: { + onHideModal() { + this.isSavingChanges = false; + this.$refs.editMetaModal.hide(); + }, onDismissError() { this.submitChangesError = null; }, - onSubmit({ content, images }) { + onPrepareSubmit({ content, images }) { this.content = content; - this.submitChanges(images); - }, - submitChanges(images) { + this.images = images; + this.isSavingChanges = true; + this.$refs.editMetaModal.show(); + }, + onSubmit(mergeRequestMeta) { + // eslint-disable-next-line promise/catch-or-return + this.$apollo + .mutate({ + mutation: hasSubmittedChangesMutation, + variables: { + input: { + hasSubmittedChanges: true, + }, + }, + }) + .finally(() => { + this.$router.push(SUCCESS_ROUTE); + }); this.$apollo .mutate({ @@ -83,13 +107,11 @@ export default { username: this.appData.username, sourcePath: this.appData.sourcePath, content: this.content, - images, + images: this.images, + mergeRequestMeta, }, }, }) - .then(() => { - this.$router.push(SUCCESS_ROUTE); - }) .catch(e => { this.submitChangesError = e.message; }) @@ -107,7 +129,7 @@ export default { <submit-changes-error v-if="submitChangesError" :error="submitChangesError" - @retry="submitChanges" + @retry="onSubmit" @dismiss="onDismissError" /> <edit-area @@ -116,7 +138,13 @@ export default { :content="sourceContent.content" :saving-changes="isSavingChanges" :return-url="appData.returnUrl" - @submit="onSubmit" + @submit="onPrepareSubmit" + /> + <edit-meta-modal + ref="editMetaModal" + :source-path="appData.sourcePath" + @primary="onSubmit" + @hide="onHideModal" /> </template> diff --git a/app/assets/javascripts/static_site_editor/pages/success.vue b/app/assets/javascripts/static_site_editor/pages/success.vue index f0d597d7c9b..1ee1a3b0edf 100644 --- a/app/assets/javascripts/static_site_editor/pages/success.vue +++ b/app/assets/javascripts/static_site_editor/pages/success.vue @@ -1,5 +1,5 @@ <script> -import { GlEmptyState, GlButton } from '@gitlab/ui'; +import { GlButton, GlEmptyState, GlLoadingIcon } from '@gitlab/ui'; import { s__, __, sprintf } from '~/locale'; import savedContentMetaQuery from '../graphql/queries/saved_content_meta.query.graphql'; @@ -8,8 +8,9 @@ import { HOME_ROUTE } from '../router/constants'; export default { components: { - GlEmptyState, GlButton, + GlEmptyState, + GlLoadingIcon, }, props: { mergeRequestsIllustrationPath: { @@ -33,7 +34,7 @@ export default { }, }, created() { - if (!this.savedContentMeta) { + if (!this.appData.hasSubmittedChanges) { this.$router.push(HOME_ROUTE); } }, @@ -50,40 +51,56 @@ export default { assignMergeRequestInstruction: s__( 'StaticSiteEditor|3. Assign a person to review and accept the merge request.', ), + submittingTitle: s__('StaticSiteEditor|Creating your merge request'), + submittingNotePrimary: s__( + 'StaticSiteEditor|You can set an assignee to get your changes reviewed and deployed once your merge request is created.', + ), + submittingNoteSecondary: s__( + 'StaticSiteEditor|A link to view the merge request will appear once ready.', + ), }; </script> <template> - <div - v-if="savedContentMeta" - class="container gl-flex-grow-1 gl-display-flex gl-flex-direction-column" - > - <div class="gl-fixed gl-left-0 gl-right-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-100"> + <div> + <div class="gl-border-b-solid gl-border-b-1 gl-border-b-gray-100"> <div class="container gl-py-4"> - <gl-button - v-if="appData.returnUrl" - ref="returnToSiteButton" - class="gl-mr-5" - :href="appData.returnUrl" - >{{ $options.returnToSiteBtnText }}</gl-button - > - <strong> - {{ updatedFileDescription }} - </strong> + <div class="gl-display-flex"> + <gl-button + v-if="appData.returnUrl" + ref="returnToSiteButton" + class="gl-mr-5 gl-align-self-start" + :href="appData.returnUrl" + >{{ $options.returnToSiteBtnText }}</gl-button + > + <strong class="gl-mt-2"> + {{ updatedFileDescription }} + </strong> + </div> </div> </div> - <gl-empty-state - class="gl-my-9" - :primary-button-text="$options.primaryButtonText" - :title="$options.title" - :primary-button-link="savedContentMeta.mergeRequest.url" - :svg-path="mergeRequestsIllustrationPath" - > - <template #description> - <p>{{ $options.mergeRequestInstructionsHeading }}</p> - <p>{{ $options.addTitleInstruction }}</p> - <p>{{ $options.addDescriptionInstruction }}</p> - <p>{{ $options.assignMergeRequestInstruction }}</p> - </template> - </gl-empty-state> + <div class="container"> + <gl-empty-state + class="gl-my-7" + :title="savedContentMeta ? $options.title : $options.submittingTitle" + :primary-button-text="savedContentMeta && $options.primaryButtonText" + :primary-button-link="savedContentMeta && savedContentMeta.mergeRequest.url" + :svg-path="mergeRequestsIllustrationPath" + :svg-height="146" + > + <template #description> + <div v-if="savedContentMeta"> + <p>{{ $options.mergeRequestInstructionsHeading }}</p> + <p>{{ $options.addTitleInstruction }}</p> + <p>{{ $options.addDescriptionInstruction }}</p> + <p>{{ $options.assignMergeRequestInstruction }}</p> + </div> + <div v-else> + <p>{{ $options.submittingNotePrimary }}</p> + <p>{{ $options.submittingNoteSecondary }}</p> + <gl-loading-icon size="xl" /> + </div> + </template> + </gl-empty-state> + </div> </div> </template> diff --git a/app/assets/javascripts/static_site_editor/services/front_matterify.js b/app/assets/javascripts/static_site_editor/services/front_matterify.js new file mode 100644 index 00000000000..cbf0fffd515 --- /dev/null +++ b/app/assets/javascripts/static_site_editor/services/front_matterify.js @@ -0,0 +1,73 @@ +import jsYaml from 'js-yaml'; + +const NEW_LINE = '\n'; + +const hasMatter = (firstThreeChars, fourthChar) => { + const isYamlDelimiter = firstThreeChars === '---'; + const isFourthCharNewline = fourthChar === NEW_LINE; + return isYamlDelimiter && isFourthCharNewline; +}; + +export const frontMatterify = source => { + let index = 3; + let offset; + const delimiter = source.slice(0, index); + const type = 'yaml'; + const NO_FRONTMATTER = { + source, + matter: null, + spacing: null, + content: source, + delimiter: null, + type: null, + }; + + if (!hasMatter(delimiter, source.charAt(index))) { + return NO_FRONTMATTER; + } + + offset = source.indexOf(delimiter, index); + + // Finds the end delimiter that starts at a new line + while (offset !== -1 && source.charAt(offset - 1) !== NEW_LINE) { + index = offset + delimiter.length; + offset = source.indexOf(delimiter, index); + } + + if (offset === -1) { + return NO_FRONTMATTER; + } + + const matterStr = source.slice(index, offset); + const matter = jsYaml.safeLoad(matterStr); + + let content = source.slice(offset + delimiter.length); + let spacing = ''; + let idx = 0; + while (content.charAt(idx).match(/(\s|\n)/)) { + spacing += content.charAt(idx); + idx += 1; + } + content = content.replace(spacing, ''); + + return { + source, + matter, + spacing, + content, + delimiter, + type, + }; +}; + +export const stringify = ({ matter, spacing, content, delimiter }, newMatter) => { + const matterObj = newMatter || matter; + + if (!matterObj) { + return content; + } + + const header = `${delimiter}${NEW_LINE}${jsYaml.safeDump(matterObj)}${delimiter}`; + const body = `${spacing}${content}`; + return `${header}${body}`; +}; diff --git a/app/assets/javascripts/static_site_editor/services/parse_source_file.js b/app/assets/javascripts/static_site_editor/services/parse_source_file.js index 640186ee1d0..d4fc8b2edb6 100644 --- a/app/assets/javascripts/static_site_editor/services/parse_source_file.js +++ b/app/assets/javascripts/static_site_editor/services/parse_source_file.js @@ -1,7 +1,7 @@ -import grayMatter from 'gray-matter'; +import { frontMatterify, stringify } from './front_matterify'; const parseSourceFile = raw => { - const remake = source => grayMatter(source, {}); + const remake = source => frontMatterify(source); let editable = remake(raw); @@ -13,20 +13,17 @@ const parseSourceFile = raw => { } }; - const trimmedEditable = () => grayMatter.stringify(editable).trim(); + const content = (isBody = false) => (isBody ? editable.content : stringify(editable)); - const content = (isBody = false) => (isBody ? editable.content.trim() : trimmedEditable()); // gray-matter internally adds an eof newline so we trim to bypass, open issue: https://github.com/jonschlinkert/gray-matter/issues/96 - - const matter = () => editable.data; + const matter = () => editable.matter; const syncMatter = settings => { - const source = grayMatter.stringify(editable.content, settings); - syncContent(source); + editable.matter = settings; }; - const isModified = () => trimmedEditable() !== raw; + const isModified = () => stringify(editable) !== raw; - const hasMatter = () => editable.matter.length > 0; + const hasMatter = () => Boolean(editable.matter); return { matter, diff --git a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js index da62d3fa4fc..8623a671a7d 100644 --- a/app/assets/javascripts/static_site_editor/services/submit_content_changes.js +++ b/app/assets/javascripts/static_site_editor/services/submit_content_changes.js @@ -1,6 +1,5 @@ import Api from '~/api'; import Tracking from '~/tracking'; -import { s__, sprintf } from '~/locale'; import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils'; import generateBranchName from '~/static_site_editor/services/generate_branch_name'; @@ -71,6 +70,7 @@ const commitContent = (projectId, message, branch, sourcePath, content, images) const createMergeRequest = ( projectId, title, + description, sourceBranch, targetBranch = DEFAULT_TARGET_BRANCH, ) => { @@ -80,6 +80,7 @@ const createMergeRequest = ( projectId, convertObjectPropsToSnakeCase({ title, + description, sourceBranch, targetBranch, }), @@ -88,11 +89,16 @@ const createMergeRequest = ( }); }; -const submitContentChanges = ({ username, projectId, sourcePath, content, images }) => { +const submitContentChanges = ({ + username, + projectId, + sourcePath, + content, + images, + mergeRequestMeta, +}) => { const branch = generateBranchName(username); - const mergeRequestTitle = sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), { - sourcePath, - }); + const { title: mergeRequestTitle, description: mergeRequestDescription } = mergeRequestMeta; const meta = {}; return createBranch(projectId, branch) @@ -104,7 +110,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content, images .then(({ data: { short_id: label, web_url: url } }) => { Object.assign(meta, { commit: { label, url } }); - return createMergeRequest(projectId, mergeRequestTitle, branch); + return createMergeRequest(projectId, mergeRequestTitle, mergeRequestDescription, branch); }) .then(({ data: { iid: label, web_url: url } }) => { Object.assign(meta, { mergeRequest: { label: label.toString(), url } }); diff --git a/app/assets/javascripts/static_site_editor/services/templater.js b/app/assets/javascripts/static_site_editor/services/templater.js index a1c1bb6b8d6..d302aea78a3 100644 --- a/app/assets/javascripts/static_site_editor/services/templater.js +++ b/app/assets/javascripts/static_site_editor/services/templater.js @@ -15,7 +15,7 @@ const markPrefix = `${marker}-${Date.now()}`; const reHelpers = { template: `.| |\\t|\\n(?!(\\n|${markPrefix}))`, - openTag: '<[a-zA-Z]+.*?>', + openTag: '<(?!figure|iframe)[a-zA-Z]+.*?>', closeTag: '</.+>', }; const reTemplated = new RegExp(`(^${wrapPrefix}(${reHelpers.template})+?${wrapPostfix}$)`, 'gm'); |