summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-09 09:41:26 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-09 09:41:26 +0000
commit684921fd9ea9ae521ed736b155c0d01599a94e84 (patch)
treefb587bb318f8c52ed5d314c2c96c8aeed656c5bd
parent9922b38ff03500d311dd7de771961154f50ea8f4 (diff)
downloadgitlab-ce-684921fd9ea9ae521ed736b155c0d01599a94e84.tar.gz
Add latest changes from gitlab-org/gitlab@15-11-stable-ee
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/eventhub.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js20
-rw-r--r--app/assets/javascripts/vue_shared/constants.js1
-rw-r--r--app/views/shared/issuable/_form.html.haml4
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb16
-rw-r--r--spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js39
7 files changed, 94 insertions, 5 deletions
diff --git a/app/assets/javascripts/vue_shared/components/markdown/eventhub.js b/app/assets/javascripts/vue_shared/components/markdown/eventhub.js
new file mode 100644
index 00000000000..e31806ad199
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/markdown/eventhub.js
@@ -0,0 +1,3 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
diff --git a/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue b/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue
index 52d8aab30d5..6ffebc51ef8 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/markdown_editor.vue
@@ -3,8 +3,13 @@ import Autosize from 'autosize';
import axios from '~/lib/utils/axios_utils';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { updateDraft, clearDraft, getDraft } from '~/lib/utils/autosave';
-import { EDITING_MODE_MARKDOWN_FIELD, EDITING_MODE_CONTENT_EDITOR } from '../../constants';
+import {
+ EDITING_MODE_MARKDOWN_FIELD,
+ EDITING_MODE_CONTENT_EDITOR,
+ CLEAR_AUTOSAVE_ENTRY_EVENT,
+} from '../../constants';
import MarkdownField from './field.vue';
+import eventHub from './eventhub';
export default {
components: {
@@ -124,6 +129,11 @@ export default {
getValue: () => this.getValue(),
setValue: (val) => this.setValue(val),
});
+
+ eventHub.$on(CLEAR_AUTOSAVE_ENTRY_EVENT, this.clearDraft);
+ },
+ beforeDestroy() {
+ eventHub.$off(CLEAR_AUTOSAVE_ENTRY_EVENT, this.clearDraft);
},
methods: {
getValue() {
@@ -183,6 +193,10 @@ export default {
if (this.markdown) updateDraft(this.autosaveKey, this.markdown);
else clearDraft(this.autosaveKey);
},
+ clearDraft(key) {
+ if (!this.autosaveKey || key !== this.autosaveKey) return;
+ clearDraft(this.autosaveKey);
+ },
togglePreview(value) {
if (this.editingMode === EDITING_MODE_MARKDOWN_FIELD) {
this.$refs.markdownField.previewMarkdown = value;
diff --git a/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js b/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js
index 0f2a46f78f7..b0e609e2433 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js
+++ b/app/assets/javascripts/vue_shared/components/markdown/mount_markdown_editor.js
@@ -1,6 +1,8 @@
import Vue from 'vue';
import { queryToObject, objectToQuery } from '~/lib/utils/url_utility';
+import { CLEAR_AUTOSAVE_ENTRY_EVENT } from '../../constants';
import MarkdownEditor from './markdown_editor.vue';
+import eventHub from './eventhub';
const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
const MR_TARGET_BRANCH = 'merge_request[target_branch]';
@@ -35,6 +37,19 @@ function getSearchTerm(newIssuePath) {
return newIssuePath === pathname ? '' : format(search);
}
+function mountAutosaveClearOnSubmit(autosaveKey) {
+ const resetAutosaveButtons = document.querySelectorAll('.js-reset-autosave');
+ if (resetAutosaveButtons.length === 0) {
+ return;
+ }
+
+ for (const resetAutosaveButton of resetAutosaveButtons) {
+ resetAutosaveButton.addEventListener('click', () => {
+ eventHub.$emit(CLEAR_AUTOSAVE_ENTRY_EVENT, autosaveKey);
+ });
+ }
+}
+
export function mountMarkdownEditor() {
const el = document.querySelector('.js-markdown-editor');
@@ -65,6 +80,7 @@ export function mountMarkdownEditor() {
};
const setFacade = (props) => Object.assign(facade, props);
+ const autosaveKey = `autosave/${document.location.pathname}/${searchTerm}/description`;
// eslint-disable-next-line no-new
new Vue({
@@ -85,7 +101,7 @@ export function mountMarkdownEditor() {
class: formFieldClasses,
'data-qa-selector': qaSelector,
},
- autosaveKey: `autosave/${document.location.pathname}/${searchTerm}/description`,
+ autosaveKey,
enableAutocomplete: true,
autocompleteDataSources: gl.GfmAutoComplete?.dataSources,
supportsQuickActions: true,
@@ -95,5 +111,7 @@ export function mountMarkdownEditor() {
},
});
+ mountAutosaveClearOnSubmit(autosaveKey);
+
return facade;
}
diff --git a/app/assets/javascripts/vue_shared/constants.js b/app/assets/javascripts/vue_shared/constants.js
index 29a31503840..3896e963a53 100644
--- a/app/assets/javascripts/vue_shared/constants.js
+++ b/app/assets/javascripts/vue_shared/constants.js
@@ -96,3 +96,4 @@ export const confidentialityInfoText = (workspaceType, issuableType) =>
export const EDITING_MODE_MARKDOWN_FIELD = 'markdownField';
export const EDITING_MODE_CONTENT_EDITOR = 'contentEditor';
+export const CLEAR_AUTOSAVE_ENTRY_EVENT = 'markdown_clear_autosave_entry';
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 5ba92676f89..58d0a39578a 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -62,9 +62,9 @@
= sanitize(html_escape(_('Please review the %{linkStart}contribution guidelines%{linkEnd} for this project.')) % { linkStart: contribution_guidelines_start, linkEnd: contribution_guidelines_end })
- if issuable.new_record?
- = form.submit "#{_('Create')} #{issuable.class.model_name.human.downcase}", pajamas_button: true, class: 'gl-mr-2 js-issuable-submit-button', data: { qa_selector: 'issuable_create_button', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
+ = form.submit "#{_('Create')} #{issuable.class.model_name.human.downcase}", pajamas_button: true, class: 'gl-mr-2 js-issuable-submit-button js-reset-autosave', data: { qa_selector: 'issuable_create_button', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
- else
- = form.submit _('Save changes'), pajamas_button: true, class: 'gl-mr-2 js-issuable-submit-button', data: { track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
+ = form.submit _('Save changes'), pajamas_button: true, class: 'gl-mr-2 js-issuable-submit-button js-reset-autosave', data: { track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
- if issuable.new_record?
= link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'btn gl-button btn-default js-reset-autosave'
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 4e3968230b4..42c66f0c40d 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -233,6 +233,7 @@ RSpec.describe "User creates issue", feature_category: :team_planning do
wait_for_requests
expect(page).to have_field('Title', with: '')
+ expect(page).to have_field('Description', with: '')
fill_in 'issue_title', with: 'bug 345'
fill_in 'issue_description', with: 'bug description'
@@ -240,6 +241,21 @@ RSpec.describe "User creates issue", feature_category: :team_planning do
click_button 'Create issue'
end
end
+
+ it 'clears local storage after cancelling a new issue creation', :js do
+ 2.times do
+ visit new_project_issue_path(project)
+ wait_for_requests
+
+ expect(page).to have_field('Title', with: '')
+ expect(page).to have_field('Description', with: '')
+
+ fill_in 'issue_title', with: 'bug 345'
+ fill_in 'issue_description', with: 'bug description'
+
+ click_link 'Cancel'
+ end
+ end
end
context 'when signed in as reporter', :js do
diff --git a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
index 69dedd6b68a..fe95ad56f8c 100644
--- a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js
@@ -3,7 +3,12 @@ import Autosize from 'autosize';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
-import { EDITING_MODE_MARKDOWN_FIELD, EDITING_MODE_CONTENT_EDITOR } from '~/vue_shared/constants';
+import {
+ EDITING_MODE_MARKDOWN_FIELD,
+ EDITING_MODE_CONTENT_EDITOR,
+ CLEAR_AUTOSAVE_ENTRY_EVENT,
+} from '~/vue_shared/constants';
+import markdownEditorEventHub from '~/vue_shared/components/markdown/eventhub';
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import ContentEditor from '~/content_editor/components/content_editor.vue';
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
@@ -229,6 +234,38 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
expect(localStorage.setItem).not.toHaveBeenCalled();
});
+
+ describe('clear local storage event handler', () => {
+ it('does not clear the local storage if the autosave key is not defined', async () => {
+ buildWrapper();
+
+ await waitForPromises();
+
+ markdownEditorEventHub.$emit(CLEAR_AUTOSAVE_ENTRY_EVENT, 'issue/1234');
+
+ expect(localStorage.removeItem).not.toHaveBeenCalled();
+ });
+
+ it('does not clear the local storage if the event autosave key does not match', async () => {
+ buildWrapper({ propsData: { autosaveKey: 'issue/1234' } });
+
+ await waitForPromises();
+
+ markdownEditorEventHub.$emit(CLEAR_AUTOSAVE_ENTRY_EVENT, 'issue/1235');
+
+ expect(localStorage.removeItem).not.toHaveBeenCalled();
+ });
+
+ it('clears the local storage if the event autosave key matches', async () => {
+ buildWrapper({ propsData: { autosaveKey: 'issue/1234' } });
+
+ await waitForPromises();
+
+ markdownEditorEventHub.$emit(CLEAR_AUTOSAVE_ENTRY_EVENT, 'issue/1234');
+
+ expect(localStorage.removeItem).toHaveBeenCalledWith('autosave/issue/1234');
+ });
+ });
});
it('renders markdown field textarea', () => {