Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 15:26:25 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 15:26:25 +0300
commita09983ae35713f5a2bbb100981116d31ce99826e (patch)
tree2ee2af7bd104d57086db360a7e6d8c9d5d43667a /app/assets/javascripts/static_site_editor
parent18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff)
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'app/assets/javascripts/static_site_editor')
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_area.vue51
-rw-r--r--app/assets/javascripts/static_site_editor/constants.js2
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql2
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/queries/app_data.query.graphql2
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql2
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js4
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/typedefs.graphql2
-rw-r--r--app/assets/javascripts/static_site_editor/image_repository.js20
-rw-r--r--app/assets/javascripts/static_site_editor/pages/home.vue7
-rw-r--r--app/assets/javascripts/static_site_editor/services/image_service.js9
-rw-r--r--app/assets/javascripts/static_site_editor/services/parse_source_file.js40
-rw-r--r--app/assets/javascripts/static_site_editor/services/submit_content_changes.js32
12 files changed, 124 insertions, 49 deletions
diff --git a/app/assets/javascripts/static_site_editor/components/edit_area.vue b/app/assets/javascripts/static_site_editor/components/edit_area.vue
index e9efef40632..84a16f327d9 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_area.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_area.vue
@@ -5,6 +5,8 @@ import EditHeader from './edit_header.vue';
import UnsavedChangesConfirmDialog from './unsaved_changes_confirm_dialog.vue';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
+import { DEFAULT_IMAGE_UPLOAD_PATH } from '../constants';
+import imageRepository from '../image_repository';
export default {
components: {
@@ -31,46 +33,47 @@ export default {
required: false,
default: '',
},
+ imageRoot: {
+ type: String,
+ required: false,
+ default: DEFAULT_IMAGE_UPLOAD_PATH,
+ validator: prop => prop.endsWith('/'),
+ },
},
data() {
return {
saveable: false,
parsedSource: parseSourceFile(this.content),
editorMode: EDITOR_TYPES.wysiwyg,
+ isModified: false,
};
},
+ imageRepository: imageRepository(),
computed: {
editableContent() {
- return this.parsedSource.editable;
- },
- editableKey() {
- return this.isWysiwygMode ? 'body' : 'raw';
+ return this.parsedSource.content(this.isWysiwygMode);
},
isWysiwygMode() {
return this.editorMode === EDITOR_TYPES.wysiwyg;
},
- modified() {
- return this.isWysiwygMode
- ? this.parsedSource.isModifiedBody()
- : this.parsedSource.isModifiedRaw();
- },
},
methods: {
- syncSource() {
- if (this.isWysiwygMode) {
- this.parsedSource.syncBody();
- return;
- }
-
- this.parsedSource.syncRaw();
+ onInputChange(newVal) {
+ this.parsedSource.sync(newVal, this.isWysiwygMode);
+ this.isModified = this.parsedSource.isModified();
},
onModeChange(mode) {
this.editorMode = mode;
- this.syncSource();
+ this.$refs.editor.resetInitialValue(this.editableContent);
+ },
+ onUploadImage({ file, imageUrl }) {
+ this.$options.imageRepository.add(file, imageUrl);
},
onSubmit() {
- this.syncSource();
- this.$emit('submit', { content: this.editableContent.raw });
+ this.$emit('submit', {
+ content: this.parsedSource.content(),
+ images: this.$options.imageRepository.getAll(),
+ });
},
},
};
@@ -79,16 +82,20 @@ export default {
<div class="d-flex flex-grow-1 flex-column h-100">
<edit-header class="py-2" :title="title" />
<rich-content-editor
- v-model="editableContent[editableKey]"
+ ref="editor"
+ :content="editableContent"
:initial-edit-type="editorMode"
+ :image-root="imageRoot"
class="mb-9 h-100"
@modeChange="onModeChange"
+ @input="onInputChange"
+ @uploadImage="onUploadImage"
/>
- <unsaved-changes-confirm-dialog :modified="modified" />
+ <unsaved-changes-confirm-dialog :modified="isModified" />
<publish-toolbar
class="gl-fixed gl-left-0 gl-bottom-0 gl-w-full"
:return-url="returnUrl"
- :saveable="modified"
+ :saveable="isModified"
:saving-changes="savingChanges"
@submit="onSubmit"
/>
diff --git a/app/assets/javascripts/static_site_editor/constants.js b/app/assets/javascripts/static_site_editor/constants.js
index 947347922f2..49db9ab7ca5 100644
--- a/app/assets/javascripts/static_site_editor/constants.js
+++ b/app/assets/javascripts/static_site_editor/constants.js
@@ -19,3 +19,5 @@ export const DEFAULT_HEADING = s__('StaticSiteEditor|Static site editor');
export const TRACKING_ACTION_CREATE_COMMIT = 'create_commit';
export const TRACKING_ACTION_CREATE_MERGE_REQUEST = 'create_merge_request';
export const TRACKING_ACTION_INITIALIZE_EDITOR = 'initialize_editor';
+
+export const DEFAULT_IMAGE_UPLOAD_PATH = 'source/images/uploads/';
diff --git a/app/assets/javascripts/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql b/app/assets/javascripts/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql
index 2840d419966..cd130aa7dbb 100644
--- a/app/assets/javascripts/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql
+++ b/app/assets/javascripts/static_site_editor/graphql/mutations/submit_content_changes.mutation.graphql
@@ -1,5 +1,5 @@
mutation submitContentChanges($input: SubmitContentChangesInput) {
- submitContentChanges(input: $input) @client {
+ submitContentChanges(input: $input) @client {
branch
commit
mergeRequest
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 fdbf4459aee..946d80efff0 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
@@ -3,7 +3,7 @@ query appData {
isSupportedContent
project
sourcePath
- username,
+ username
returnUrl
}
}
diff --git a/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql b/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql
index e36d244ae57..cfe30c601ed 100644
--- a/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql
+++ b/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql
@@ -1,6 +1,6 @@
query sourceContent($project: ID!, $sourcePath: String!) {
project(fullPath: $project) {
- fullPath,
+ fullPath
file(path: $sourcePath) @client {
title
content
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 6c4e3a4d973..0cb26f88785 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
@@ -3,10 +3,10 @@ import savedContentMetaQuery from '../queries/saved_content_meta.query.graphql';
const submitContentChangesResolver = (
_,
- { input: { project: projectId, username, sourcePath, content } },
+ { input: { project: projectId, username, sourcePath, content, images } },
{ cache },
) => {
- return submitContentChanges({ projectId, username, sourcePath, content }).then(
+ return submitContentChanges({ projectId, username, sourcePath, content, images }).then(
savedContentMeta => {
cache.writeQuery({
query: savedContentMetaQuery,
diff --git a/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql b/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql
index 59da2e27144..78cc1746cdb 100644
--- a/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql
+++ b/app/assets/javascripts/static_site_editor/graphql/typedefs.graphql
@@ -22,7 +22,7 @@ type AppData {
username: String!
}
-type SubmitContentChangesInput {
+input SubmitContentChangesInput {
project: String!
sourcePath: String!
content: String!
diff --git a/app/assets/javascripts/static_site_editor/image_repository.js b/app/assets/javascripts/static_site_editor/image_repository.js
new file mode 100644
index 00000000000..541d581bda8
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/image_repository.js
@@ -0,0 +1,20 @@
+import { __ } from '~/locale';
+import Flash from '~/flash';
+import { getBinary } from './services/image_service';
+
+const imageRepository = () => {
+ const images = new Map();
+ const flash = message => new Flash(message);
+
+ const add = (file, url) => {
+ getBinary(file)
+ .then(content => images.set(url, content))
+ .catch(() => flash(__('Something went wrong while inserting your image. Please try again.')));
+ };
+
+ const getAll = () => images;
+
+ return { add, getAll };
+};
+
+export default imageRepository;
diff --git a/app/assets/javascripts/static_site_editor/pages/home.vue b/app/assets/javascripts/static_site_editor/pages/home.vue
index a1314c8a478..156b815e07a 100644
--- a/app/assets/javascripts/static_site_editor/pages/home.vue
+++ b/app/assets/javascripts/static_site_editor/pages/home.vue
@@ -67,11 +67,11 @@ export default {
onDismissError() {
this.submitChangesError = null;
},
- onSubmit({ content }) {
+ onSubmit({ content, images }) {
this.content = content;
- this.submitChanges();
+ this.submitChanges(images);
},
- submitChanges() {
+ submitChanges(images) {
this.isSavingChanges = true;
this.$apollo
@@ -83,6 +83,7 @@ export default {
username: this.appData.username,
sourcePath: this.appData.sourcePath,
content: this.content,
+ images,
},
},
})
diff --git a/app/assets/javascripts/static_site_editor/services/image_service.js b/app/assets/javascripts/static_site_editor/services/image_service.js
new file mode 100644
index 00000000000..edc69d0579a
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/services/image_service.js
@@ -0,0 +1,9 @@
+// eslint-disable-next-line import/prefer-default-export
+export const getBinary = file => {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsDataURL(file);
+ reader.onload = () => resolve(reader.result.split(',')[1]);
+ reader.onerror = error => reject(error);
+ });
+};
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 f32c693411f..126dfe81b90 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
@@ -22,33 +22,43 @@ const parseSourceFile = raw => {
return buildPayload(source, '', '', source);
};
- const computedRaw = () => `${editable.header}${editable.spacing}${editable.body}`;
-
- const syncBody = () => {
+ const syncEditable = () => {
/*
We re-parse as markdown editing could have added non-body changes (preFrontMatter, frontMatter, or spacing).
- Re-parsing additionally gets us the desired body that was extracted from the mutated editable.raw
- Additionally we intentionally mutate the existing editable's key values as opposed to reassigning the object itself so consumers of the potentially reactive property stay in sync.
+ Re-parsing additionally gets us the desired body that was extracted from the potentially mutated editable.raw
*/
- Object.assign(editable, parse(editable.raw));
+ editable = parse(editable.raw);
+ };
+
+ const syncBodyToRaw = () => {
+ editable.raw = `${editable.header}${editable.spacing}${editable.body}`;
+ };
+
+ const sync = (newVal, isBodyToRaw) => {
+ const editableKey = isBodyToRaw ? 'body' : 'raw';
+ editable[editableKey] = newVal;
+
+ if (isBodyToRaw) {
+ syncBodyToRaw();
+ }
+
+ syncEditable();
};
- const syncRaw = () => {
- editable.raw = computedRaw();
+ const content = (isBody = false) => {
+ const editableKey = isBody ? 'body' : 'raw';
+ return editable[editableKey];
};
- const isModifiedRaw = () => initial.raw !== editable.raw;
- const isModifiedBody = () => initial.raw !== computedRaw();
+ const isModified = () => initial.raw !== editable.raw;
initial = parse(raw);
editable = parse(raw);
return {
- editable,
- isModifiedRaw,
- isModifiedBody,
- syncRaw,
- syncBody,
+ content,
+ isModified,
+ sync,
};
};
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 fce7c1f918f..da62d3fa4fc 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
@@ -21,7 +21,32 @@ const createBranch = (projectId, branch) =>
throw new Error(SUBMIT_CHANGES_BRANCH_ERROR);
});
-const commitContent = (projectId, message, branch, sourcePath, content) => {
+const createImageActions = (images, markdown) => {
+ const actions = [];
+
+ if (!markdown) {
+ return actions;
+ }
+
+ images.forEach((imageContent, filePath) => {
+ const imageExistsInMarkdown = path => new RegExp(`!\\[([^[\\]\\n]*)\\](\\(${path})\\)`); // matches the image markdown syntax: ![<any-string-except-newline>](<path>)
+
+ if (imageExistsInMarkdown(filePath).test(markdown)) {
+ actions.push(
+ convertObjectPropsToSnakeCase({
+ encoding: 'base64',
+ action: 'create',
+ content: imageContent,
+ filePath,
+ }),
+ );
+ }
+ });
+
+ return actions;
+};
+
+const commitContent = (projectId, message, branch, sourcePath, content, images) => {
Tracking.event(document.body.dataset.page, TRACKING_ACTION_CREATE_COMMIT);
return Api.commitMultiple(
@@ -35,6 +60,7 @@ const commitContent = (projectId, message, branch, sourcePath, content) => {
filePath: sourcePath,
content,
}),
+ ...createImageActions(images, content),
],
}),
).catch(() => {
@@ -62,7 +88,7 @@ const createMergeRequest = (
});
};
-const submitContentChanges = ({ username, projectId, sourcePath, content }) => {
+const submitContentChanges = ({ username, projectId, sourcePath, content, images }) => {
const branch = generateBranchName(username);
const mergeRequestTitle = sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), {
sourcePath,
@@ -73,7 +99,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content }) => {
.then(({ data: { web_url: url } }) => {
Object.assign(meta, { branch: { label: branch, url } });
- return commitContent(projectId, mergeRequestTitle, branch, sourcePath, content);
+ return commitContent(projectId, mergeRequestTitle, branch, sourcePath, content, images);
})
.then(({ data: { short_id: label, web_url: url } }) => {
Object.assign(meta, { commit: { label, url } });