Commit c6a47799 authored by Jacques Erasmus's avatar Jacques Erasmus

Merge branch '216861-custom-mr-title-description' into 'master'

Initial SSE merge request title/description meta

See merge request gitlab-org/gitlab!43909
parents 8a147445 a965b809
...@@ -3,22 +3,27 @@ import savedContentMetaQuery from '../queries/saved_content_meta.query.graphql'; ...@@ -3,22 +3,27 @@ import savedContentMetaQuery from '../queries/saved_content_meta.query.graphql';
const submitContentChangesResolver = ( const submitContentChangesResolver = (
_, _,
{ input: { project: projectId, username, sourcePath, content, images } }, { input: { project: projectId, username, sourcePath, content, images, mergeRequestMeta } },
{ cache }, { cache },
) => { ) => {
return submitContentChanges({ projectId, username, sourcePath, content, images }).then( return submitContentChanges({
savedContentMeta => { projectId,
cache.writeQuery({ username,
query: savedContentMetaQuery, sourcePath,
data: { content,
savedContentMeta: { images,
__typename: 'SavedContentMeta', mergeRequestMeta,
...savedContentMeta, }).then(savedContentMeta => {
}, cache.writeQuery({
query: savedContentMetaQuery,
data: {
savedContentMeta: {
__typename: 'SavedContentMeta',
...savedContentMeta,
}, },
}); },
}, });
); });
}; };
export default submitContentChangesResolver; export default submitContentChangesResolver;
<script> <script>
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
import Tracking from '~/tracking';
import SkeletonLoader from '../components/skeleton_loader.vue'; import SkeletonLoader from '../components/skeleton_loader.vue';
import EditArea from '../components/edit_area.vue'; import EditArea from '../components/edit_area.vue';
import InvalidContentMessage from '../components/invalid_content_message.vue'; import InvalidContentMessage from '../components/invalid_content_message.vue';
...@@ -7,8 +11,6 @@ import appDataQuery from '../graphql/queries/app_data.query.graphql'; ...@@ -7,8 +11,6 @@ import appDataQuery from '../graphql/queries/app_data.query.graphql';
import sourceContentQuery from '../graphql/queries/source_content.query.graphql'; import sourceContentQuery from '../graphql/queries/source_content.query.graphql';
import hasSubmittedChangesMutation from '../graphql/mutations/has_submitted_changes.mutation.graphql'; import hasSubmittedChangesMutation from '../graphql/mutations/has_submitted_changes.mutation.graphql';
import submitContentChangesMutation from '../graphql/mutations/submit_content_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 { LOAD_CONTENT_ERROR, TRACKING_ACTION_INITIALIZE_EDITOR } from '../constants';
import { SUCCESS_ROUTE } from '../router/constants'; import { SUCCESS_ROUTE } from '../router/constants';
...@@ -99,6 +101,12 @@ export default { ...@@ -99,6 +101,12 @@ export default {
sourcePath: this.appData.sourcePath, sourcePath: this.appData.sourcePath,
content: this.content, content: this.content,
images, images,
mergeRequestMeta: {
title: sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), {
sourcePath: this.appData.sourcePath,
}),
description: s__('StaticSiteEditor|Copy update'),
},
}, },
}, },
}) })
......
import Api from '~/api'; import Api from '~/api';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { s__, sprintf } from '~/locale';
import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
import generateBranchName from '~/static_site_editor/services/generate_branch_name'; import generateBranchName from '~/static_site_editor/services/generate_branch_name';
...@@ -71,6 +70,7 @@ const commitContent = (projectId, message, branch, sourcePath, content, images) ...@@ -71,6 +70,7 @@ const commitContent = (projectId, message, branch, sourcePath, content, images)
const createMergeRequest = ( const createMergeRequest = (
projectId, projectId,
title, title,
description,
sourceBranch, sourceBranch,
targetBranch = DEFAULT_TARGET_BRANCH, targetBranch = DEFAULT_TARGET_BRANCH,
) => { ) => {
...@@ -80,6 +80,7 @@ const createMergeRequest = ( ...@@ -80,6 +80,7 @@ const createMergeRequest = (
projectId, projectId,
convertObjectPropsToSnakeCase({ convertObjectPropsToSnakeCase({
title, title,
description,
sourceBranch, sourceBranch,
targetBranch, targetBranch,
}), }),
...@@ -88,11 +89,16 @@ const createMergeRequest = ( ...@@ -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 branch = generateBranchName(username);
const mergeRequestTitle = sprintf(s__(`StaticSiteEditor|Update %{sourcePath} file`), { const { title: mergeRequestTitle, description: mergeRequestDescription } = mergeRequestMeta;
sourcePath,
});
const meta = {}; const meta = {};
return createBranch(projectId, branch) return createBranch(projectId, branch)
...@@ -104,7 +110,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content, images ...@@ -104,7 +110,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content, images
.then(({ data: { short_id: label, web_url: url } }) => { .then(({ data: { short_id: label, web_url: url } }) => {
Object.assign(meta, { commit: { label, 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 } }) => { .then(({ data: { iid: label, web_url: url } }) => {
Object.assign(meta, { mergeRequest: { label: label.toString(), url } }); Object.assign(meta, { mergeRequest: { label: label.toString(), url } });
......
...@@ -24540,6 +24540,9 @@ msgstr "" ...@@ -24540,6 +24540,9 @@ msgstr ""
msgid "StaticSiteEditor|Branch could not be created." msgid "StaticSiteEditor|Branch could not be created."
msgstr "" msgstr ""
msgid "StaticSiteEditor|Copy update"
msgstr ""
msgid "StaticSiteEditor|Could not commit the content changes." msgid "StaticSiteEditor|Could not commit the content changes."
msgstr "" msgstr ""
......
...@@ -23,7 +23,10 @@ export const username = 'gitlabuser'; ...@@ -23,7 +23,10 @@ export const username = 'gitlabuser';
export const projectId = '123456'; export const projectId = '123456';
export const returnUrl = 'https://www.gitlab.com'; export const returnUrl = 'https://www.gitlab.com';
export const sourcePath = 'foobar.md.html'; export const sourcePath = 'foobar.md.html';
export const mergeRequestMeta = {
title: `Update ${sourcePath} file`,
description: 'Copy update',
};
export const savedContentMeta = { export const savedContentMeta = {
branch: { branch: {
label: 'foobar', label: 'foobar',
......
...@@ -17,6 +17,7 @@ import { ...@@ -17,6 +17,7 @@ import {
sourceContentTitle as title, sourceContentTitle as title,
sourcePath, sourcePath,
username, username,
mergeRequestMeta,
savedContentMeta, savedContentMeta,
submitChangesError, submitChangesError,
trackingCategory, trackingCategory,
...@@ -241,6 +242,8 @@ describe('static_site_editor/pages/home', () => { ...@@ -241,6 +242,8 @@ describe('static_site_editor/pages/home', () => {
project, project,
sourcePath, sourcePath,
username, username,
images: undefined,
mergeRequestMeta,
}, },
}, },
}); });
......
...@@ -19,6 +19,7 @@ import { ...@@ -19,6 +19,7 @@ import {
commitBranchResponse, commitBranchResponse,
commitMultipleResponse, commitMultipleResponse,
createMergeRequestResponse, createMergeRequestResponse,
mergeRequestMeta,
sourcePath, sourcePath,
sourceContentYAML as content, sourceContentYAML as content,
trackingCategory, trackingCategory,
...@@ -28,11 +29,20 @@ import { ...@@ -28,11 +29,20 @@ import {
jest.mock('~/static_site_editor/services/generate_branch_name'); jest.mock('~/static_site_editor/services/generate_branch_name');
describe('submitContentChanges', () => { describe('submitContentChanges', () => {
const mergeRequestTitle = `Update ${sourcePath} file`;
const branch = 'branch-name'; const branch = 'branch-name';
let trackingSpy; let trackingSpy;
let origPage; let origPage;
const buildPayload = (overrides = {}) => ({
username,
projectId,
sourcePath,
content,
images,
mergeRequestMeta,
...overrides,
});
beforeEach(() => { beforeEach(() => {
jest.spyOn(Api, 'createBranch').mockResolvedValue({ data: commitBranchResponse }); jest.spyOn(Api, 'createBranch').mockResolvedValue({ data: commitBranchResponse });
jest.spyOn(Api, 'commitMultiple').mockResolvedValue({ data: commitMultipleResponse }); jest.spyOn(Api, 'commitMultiple').mockResolvedValue({ data: commitMultipleResponse });
...@@ -53,7 +63,7 @@ describe('submitContentChanges', () => { ...@@ -53,7 +63,7 @@ describe('submitContentChanges', () => {
}); });
it('creates a branch named after the username and target branch', () => { it('creates a branch named after the username and target branch', () => {
return submitContentChanges({ username, projectId }).then(() => { return submitContentChanges(buildPayload()).then(() => {
expect(Api.createBranch).toHaveBeenCalledWith(projectId, { expect(Api.createBranch).toHaveBeenCalledWith(projectId, {
ref: DEFAULT_TARGET_BRANCH, ref: DEFAULT_TARGET_BRANCH,
branch, branch,
...@@ -64,16 +74,16 @@ describe('submitContentChanges', () => { ...@@ -64,16 +74,16 @@ describe('submitContentChanges', () => {
it('notifies error when branch could not be created', () => { it('notifies error when branch could not be created', () => {
Api.createBranch.mockRejectedValueOnce(); Api.createBranch.mockRejectedValueOnce();
return expect(submitContentChanges({ username, projectId })).rejects.toThrow( return expect(submitContentChanges(buildPayload())).rejects.toThrow(
SUBMIT_CHANGES_BRANCH_ERROR, SUBMIT_CHANGES_BRANCH_ERROR,
); );
}); });
it('commits the content changes to the branch when creating branch succeeds', () => { it('commits the content changes to the branch when creating branch succeeds', () => {
return submitContentChanges({ username, projectId, sourcePath, content, images }).then(() => { return submitContentChanges(buildPayload()).then(() => {
expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, { expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, {
branch, branch,
commit_message: mergeRequestTitle, commit_message: mergeRequestMeta.title,
actions: [ actions: [
{ {
action: 'update', action: 'update',
...@@ -93,16 +103,11 @@ describe('submitContentChanges', () => { ...@@ -93,16 +103,11 @@ describe('submitContentChanges', () => {
it('does not commit an image if it has been removed from the content', () => { it('does not commit an image if it has been removed from the content', () => {
const contentWithoutImages = '## Content without images'; const contentWithoutImages = '## Content without images';
return submitContentChanges({ const payload = buildPayload({ content: contentWithoutImages });
username, return submitContentChanges(payload).then(() => {
projectId,
sourcePath,
content: contentWithoutImages,
images,
}).then(() => {
expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, { expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, {
branch, branch,
commit_message: mergeRequestTitle, commit_message: mergeRequestMeta.title,
actions: [ actions: [
{ {
action: 'update', action: 'update',
...@@ -117,17 +122,19 @@ describe('submitContentChanges', () => { ...@@ -117,17 +122,19 @@ describe('submitContentChanges', () => {
it('notifies error when content could not be committed', () => { it('notifies error when content could not be committed', () => {
Api.commitMultiple.mockRejectedValueOnce(); Api.commitMultiple.mockRejectedValueOnce();
return expect(submitContentChanges({ username, projectId, images })).rejects.toThrow( return expect(submitContentChanges(buildPayload())).rejects.toThrow(
SUBMIT_CHANGES_COMMIT_ERROR, SUBMIT_CHANGES_COMMIT_ERROR,
); );
}); });
it('creates a merge request when commiting changes succeeds', () => { it('creates a merge request when committing changes succeeds', () => {
return submitContentChanges({ username, projectId, sourcePath, content, images }).then(() => { return submitContentChanges(buildPayload()).then(() => {
const { title, description } = mergeRequestMeta;
expect(Api.createProjectMergeRequest).toHaveBeenCalledWith( expect(Api.createProjectMergeRequest).toHaveBeenCalledWith(
projectId, projectId,
convertObjectPropsToSnakeCase({ convertObjectPropsToSnakeCase({
title: mergeRequestTitle, title,
description,
targetBranch: DEFAULT_TARGET_BRANCH, targetBranch: DEFAULT_TARGET_BRANCH,
sourceBranch: branch, sourceBranch: branch,
}), }),
...@@ -138,7 +145,7 @@ describe('submitContentChanges', () => { ...@@ -138,7 +145,7 @@ describe('submitContentChanges', () => {
it('notifies error when merge request could not be created', () => { it('notifies error when merge request could not be created', () => {
Api.createProjectMergeRequest.mockRejectedValueOnce(); Api.createProjectMergeRequest.mockRejectedValueOnce();
return expect(submitContentChanges({ username, projectId, images })).rejects.toThrow( return expect(submitContentChanges(buildPayload())).rejects.toThrow(
SUBMIT_CHANGES_MERGE_REQUEST_ERROR, SUBMIT_CHANGES_MERGE_REQUEST_ERROR,
); );
}); });
...@@ -147,11 +154,9 @@ describe('submitContentChanges', () => { ...@@ -147,11 +154,9 @@ describe('submitContentChanges', () => {
let result; let result;
beforeEach(() => { beforeEach(() => {
return submitContentChanges({ username, projectId, sourcePath, content, images }).then( return submitContentChanges(buildPayload()).then(_result => {
_result => { result = _result;
result = _result; });
},
);
}); });
it('returns the branch name', () => { it('returns the branch name', () => {
...@@ -179,7 +184,7 @@ describe('submitContentChanges', () => { ...@@ -179,7 +184,7 @@ describe('submitContentChanges', () => {
describe('sends the correct tracking event', () => { describe('sends the correct tracking event', () => {
beforeEach(() => { beforeEach(() => {
return submitContentChanges({ username, projectId, sourcePath, content, images }); return submitContentChanges(buildPayload());
}); });
it('for committing changes', () => { it('for committing changes', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment