summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/notes
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/notes')
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue8
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue25
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue8
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue8
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue1
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue14
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue22
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue13
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js7
-rw-r--r--app/assets/javascripts/notes/stores/actions.js84
-rw-r--r--app/assets/javascripts/notes/stores/getters.js2
-rw-r--r--app/assets/javascripts/notes/utils.js7
12 files changed, 133 insertions, 66 deletions
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 7213658bdf2..9504ed78778 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -14,7 +14,7 @@ import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex';
import Autosave from '~/autosave';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import { deprecatedCreateFlash as Flash } from '~/flash';
+import createFlash from '~/flash';
import { statusBoxState } from '~/issuable/components/status_box.vue';
import httpStatusCodes from '~/lib/utils/http_status';
import {
@@ -293,7 +293,11 @@ export default {
toggleState()
.then(() => statusBoxState.updateStatus && statusBoxState.updateStatus())
.then(refreshUserMergeRequestCounts)
- .catch(() => Flash(constants.toggleStateErrorMessage[this.noteableType][this.openState]));
+ .catch(() =>
+ createFlash({
+ message: constants.toggleStateErrorMessage[this.noteableType][this.openState],
+ }),
+ );
},
discard(shouldClear = true) {
// `blur` is needed to clear slash commands autocomplete cache if event fired.
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index dfe2763d8bd..0892276ff3b 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -130,15 +130,18 @@ export default {
@handleDeleteNote="$emit('deleteNote')"
@startReplying="$emit('startReplying')"
>
- <note-edited-text
- v-if="discussion.resolved"
- slot="discussion-resolved-text"
- :edited-at="discussion.resolved_at"
- :edited-by="discussion.resolved_by"
- :action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
- />
- <slot slot="avatar-badge" name="avatar-badge"></slot>
+ <template #discussion-resolved-text>
+ <note-edited-text
+ v-if="discussion.resolved"
+ :edited-at="discussion.resolved_at"
+ :edited-by="discussion.resolved_by"
+ :action-text="resolvedText"
+ class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
+ />
+ </template>
+ <template #avatar-badge>
+ <slot name="avatar-badge"></slot>
+ </template>
</component>
<discussion-notes-replies-wrapper :is-diff-discussion="discussion.diff_discussion">
<toggle-replies-widget
@@ -175,7 +178,9 @@ export default {
:discussion-resolve-path="discussion.resolve_path"
@handleDeleteNote="$emit('deleteNote')"
>
- <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot>
+ <template #avatar-badge>
+ <slot v-if="index === 0" name="avatar-badge"></slot>
+ </template>
</component>
<slot :show-replies="isExpanded || !hasReplies" name="footer"></slot>
</template>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index 0f72b4f2dba..44d0c741d5a 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -3,7 +3,7 @@ import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui
import { mapActions, mapGetters } from 'vuex';
import Api from '~/api';
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
-import { deprecatedCreateFlash as flash } from '~/flash';
+import createFlash from '~/flash';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import eventHub from '~/sidebar/event_hub';
@@ -234,7 +234,11 @@ export default {
assignee_ids: assignees.map((assignee) => assignee.id),
})
.then(() => this.handleAssigneeUpdate(assignees))
- .catch(() => flash(__('Something went wrong while updating assignees')));
+ .catch(() =>
+ createFlash({
+ message: __('Something went wrong while updating assignees'),
+ }),
+ );
}
},
setAwardEmoji(awardName) {
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index 9eb7b928ea4..835750cc137 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -1,8 +1,8 @@
<script>
import { mapActions, mapGetters } from 'vuex';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import AwardsList from '~/vue_shared/components/awards_list.vue';
-import { deprecatedCreateFlash as Flash } from '../../flash';
export default {
components: {
@@ -48,7 +48,11 @@ export default {
awardName,
};
- this.toggleAwardRequest(data).catch(() => Flash(__('Something went wrong on our end.')));
+ this.toggleAwardRequest(data).catch(() =>
+ createFlash({
+ message: __('Something went wrong on our end.'),
+ }),
+ );
},
},
};
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 6932af61c69..1a4a6c137a6 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -216,6 +216,7 @@ export default {
<gl-loading-icon
v-if="showSpinner"
ref="spinner"
+ size="sm"
class="editing-spinner"
:label="__('Comment is being updated')"
/>
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 1af9e4be373..b99579fb9a7 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -2,11 +2,12 @@
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import DraftNote from '~/batch_comments/components/draft_note.vue';
+import createFlash from '~/flash';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
+import { isLoggedIn } from '~/lib/utils/common_utils';
import { s__, __ } from '~/locale';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import { deprecatedCreateFlash as Flash } from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
@@ -85,7 +86,7 @@ export default {
return this.getUserData;
},
isLoggedIn() {
- return Boolean(gon.current_user_id);
+ return isLoggedIn();
},
autosaveKey() {
return getDiscussionReplyKey(this.firstNote.noteable_type, this.discussion.id);
@@ -220,7 +221,10 @@ export default {
const msg = __(
'Your comment could not be submitted! Please check your network connection and try again.',
);
- Flash(msg, 'alert', this.$el);
+ createFlash({
+ message: msg,
+ parent: this.$el,
+ });
this.$refs.noteForm.note = noteText;
callback(err);
});
@@ -262,7 +266,9 @@ export default {
@startReplying="showReplyForm"
@deleteNote="deleteNoteHandler"
>
- <slot slot="avatar-badge" name="avatar-badge"></slot>
+ <template #avatar-badge>
+ <slot name="avatar-badge"></slot>
+ </template>
<template #footer="{ showReplies }">
<draft-note
v-if="showDraft(discussion.reply_id)"
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 0feb77be653..5ea431224ce 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -4,15 +4,16 @@ import $ from 'jquery';
import { escape, isEmpty } from 'lodash';
import { mapGetters, mapActions } from 'vuex';
import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
+import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import { deprecatedCreateFlash as Flash } from '../../flash';
import { __, s__, sprintf } from '../../locale';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../event_hub';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
+import { renderMarkdown } from '../utils';
import {
getStartLineNumber,
getEndLineNumber,
@@ -247,7 +248,9 @@ export default {
this.isDeleting = false;
})
.catch(() => {
- Flash(__('Something went wrong while deleting your note. Please try again.'));
+ createFlash({
+ message: __('Something went wrong while deleting your note. Please try again.'),
+ });
this.isDeleting = false;
});
}
@@ -298,7 +301,7 @@ export default {
this.isRequesting = true;
this.oldContent = this.note.note_html;
// eslint-disable-next-line vue/no-mutating-props
- this.note.note_html = escape(noteText);
+ this.note.note_html = renderMarkdown(noteText);
this.updateNote(data)
.then(() => {
@@ -316,7 +319,10 @@ export default {
this.setSelectedCommentPositionHover();
this.$nextTick(() => {
const msg = __('Something went wrong while editing your comment. Please try again.');
- Flash(msg, 'alert', this.$el);
+ createFlash({
+ message: msg,
+ parent: this.$el,
+ });
this.recoverNoteContent(noteText);
callback();
});
@@ -387,7 +393,9 @@ export default {
:img-alt="author.name"
:img-size="40"
>
- <slot slot="avatar-badge" name="avatar-badge"></slot>
+ <template #avatar-badge>
+ <slot name="avatar-badge"></slot>
+ </template>
</user-avatar-link>
</div>
<div class="timeline-content">
@@ -398,7 +406,9 @@ export default {
:note-id="note.id"
:is-confidential="note.confidential"
>
- <slot slot="note-header-info" name="note-header-info"></slot>
+ <template #note-header-info>
+ <slot name="note-header-info"></slot>
+ </template>
<span v-if="commit" v-safe-html="actionText"></span>
<span v-else-if="note.created_at" class="d-none d-sm-inline">&middot;</span>
</note-header>
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 433f75a752d..29c60b96d8a 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -1,13 +1,13 @@
<script>
import { mapGetters, mapActions } from 'vuex';
import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
+import createFlash from '~/flash';
import { __ } from '~/locale';
import initUserPopovers from '~/user_popovers';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import draftNote from '../../batch_comments/components/draft_note.vue';
-import { deprecatedCreateFlash as Flash } from '../../flash';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
@@ -66,6 +66,7 @@ export default {
data() {
return {
currentFilter: null,
+ renderSkeleton: !this.shouldShow,
};
},
computed: {
@@ -93,7 +94,7 @@ export default {
return this.noteableData.noteableType;
},
allDiscussions() {
- if (this.isLoading) {
+ if (this.renderSkeleton || this.isLoading) {
const prerenderedNotesCount = parseInt(this.notesData.prerenderedNotesCount, 10) || 0;
return new Array(prerenderedNotesCount).fill({
@@ -122,6 +123,10 @@ export default {
if (!this.isNotesFetched) {
this.fetchNotes();
}
+
+ setTimeout(() => {
+ this.renderSkeleton = !this.shouldShow;
+ });
},
discussionTabCounterText(val) {
if (this.discussionsCount) {
@@ -216,7 +221,9 @@ export default {
.catch(() => {
this.setLoadingState(false);
this.setNotesFetchedState(true);
- Flash(__('Something went wrong while fetching comments. Please try again.'));
+ createFlash({
+ message: __('Something went wrong while fetching comments. Please try again.'),
+ });
});
},
initPolling() {
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index 27ed8e203b0..9783def1b46 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -1,4 +1,4 @@
-import { deprecatedCreateFlash as Flash } from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
export default {
@@ -46,7 +46,10 @@ export default {
this.isResolving = false;
const msg = __('Something went wrong while resolving this discussion. Please try again.');
- Flash(msg, 'alert', this.$el);
+ createFlash({
+ message: msg,
+ parent: this.$el,
+ });
});
},
},
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 086e9122c60..6a4a3263e4a 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import Visibility from 'visibilityjs';
import Vue from 'vue';
import Api from '~/api';
+import createFlash from '~/flash';
import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
@@ -9,7 +10,6 @@ import { confidentialWidget } from '~/sidebar/components/confidential/sidebar_co
import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql';
import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql';
import loadAwardsHandler from '../../awards_handler';
-import { deprecatedCreateFlash as Flash } from '../../flash';
import { isInViewport, scrollToElement, isInMRPage } from '../../lib/utils/common_utils';
import Poll from '../../lib/utils/poll';
import { create } from '../../lib/utils/recurrence';
@@ -312,25 +312,23 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
$('.notes-form .flash-container').hide(); // hide previous flash notification
commit(types.REMOVE_PLACEHOLDER_NOTES); // remove previous placeholders
- if (replyId) {
- if (hasQuickActions) {
- placeholderText = utils.stripQuickActions(placeholderText);
- }
+ if (hasQuickActions) {
+ placeholderText = utils.stripQuickActions(placeholderText);
+ }
- if (placeholderText.length) {
- commit(types.SHOW_PLACEHOLDER_NOTE, {
- noteBody: placeholderText,
- replyId,
- });
- }
+ if (placeholderText.length) {
+ commit(types.SHOW_PLACEHOLDER_NOTE, {
+ noteBody: placeholderText,
+ replyId,
+ });
+ }
- if (hasQuickActions) {
- commit(types.SHOW_PLACEHOLDER_NOTE, {
- isSystemNote: true,
- noteBody: utils.getQuickActionText(note),
- replyId,
- });
- }
+ if (hasQuickActions) {
+ commit(types.SHOW_PLACEHOLDER_NOTE, {
+ isSystemNote: true,
+ noteBody: utils.getQuickActionText(note),
+ replyId,
+ });
}
const processQuickActions = (res) => {
@@ -354,7 +352,11 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
$('.js-gfm-input').trigger('clear-commands-cache.atwho');
- Flash(message || __('Commands applied'), 'notice', noteData.flashContainer);
+ createFlash({
+ message: message || __('Commands applied'),
+ type: 'notice',
+ parent: noteData.flashContainer,
+ });
}
return res;
@@ -375,11 +377,10 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
awardsHandler.scrollToAwards();
})
.catch(() => {
- Flash(
- __('Something went wrong while adding your award. Please try again.'),
- 'alert',
- noteData.flashContainer,
- );
+ createFlash({
+ message: __('Something went wrong while adding your award. Please try again.'),
+ parent: noteData.flashContainer,
+ });
})
.then(() => res);
};
@@ -397,9 +398,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
};
const removePlaceholder = (res) => {
- if (replyId) {
- commit(types.REMOVE_PLACEHOLDER_NOTES);
- }
+ commit(types.REMOVE_PLACEHOLDER_NOTES);
return res;
};
@@ -417,7 +416,10 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
const errorMsg = sprintf(__('Your comment could not be submitted because %{error}'), {
error: base[0].toLowerCase(),
});
- Flash(errorMsg, 'alert', noteData.flashContainer);
+ createFlash({
+ message: errorMsg,
+ parent: noteData.flashContainer,
+ });
return { ...data, hasFlash: true };
}
}
@@ -480,7 +482,9 @@ export const poll = ({ commit, state, getters, dispatch }) => {
});
notePollOccurrenceTracking.handle(2, () => {
// On the second failure in a row, show the alert and try one more time (hoping to succeed and clear the error)
- flashContainer = Flash(__('Something went wrong while fetching latest comments.'));
+ flashContainer = createFlash({
+ message: __('Something went wrong while fetching latest comments.'),
+ });
setTimeout(() => eTagPoll.restart(), NOTES_POLLING_INTERVAL);
});
@@ -570,7 +574,9 @@ export const filterDiscussion = ({ dispatch }, { path, filter, persistFilter })
.catch(() => {
dispatch('setLoadingState', false);
dispatch('setNotesFetchedState', true);
- Flash(__('Something went wrong while fetching comments. Please try again.'));
+ createFlash({
+ message: __('Something went wrong while fetching comments. Please try again.'),
+ });
});
};
@@ -613,7 +619,10 @@ export const submitSuggestion = (
const flashMessage = errorMessage || defaultMessage;
- Flash(__(flashMessage), 'alert', flashContainer);
+ createFlash({
+ message: __(flashMessage),
+ parent: flashContainer,
+ });
})
.finally(() => {
commit(types.SET_RESOLVING_DISCUSSION, false);
@@ -646,7 +655,10 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { flashContai
const flashMessage = errorMessage || defaultMessage;
- Flash(__(flashMessage), 'alert', flashContainer);
+ createFlash({
+ message: __(flashMessage),
+ parent: flashContainer,
+ });
})
.finally(() => {
commit(types.SET_APPLYING_BATCH_STATE, false);
@@ -685,7 +697,9 @@ export const fetchDescriptionVersion = ({ dispatch }, { endpoint, startingVersio
})
.catch((error) => {
dispatch('receiveDescriptionVersionError', error);
- Flash(__('Something went wrong while fetching description changes. Please try again.'));
+ createFlash({
+ message: __('Something went wrong while fetching description changes. Please try again.'),
+ });
});
};
@@ -717,7 +731,9 @@ export const softDeleteDescriptionVersion = (
})
.catch((error) => {
dispatch('receiveDeleteDescriptionVersionError', error);
- Flash(__('Something went wrong while deleting description changes. Please try again.'));
+ createFlash({
+ message: __('Something went wrong while deleting description changes. Please try again.'),
+ });
// Throw an error here because a component like SystemNote -
// needs to know if the request failed to reset its internal state.
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index b04b1d28ffa..956221d69ae 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -279,7 +279,7 @@ export const getDiscussion = (state) => (discussionId) =>
export const commentsDisabled = (state) => state.commentsDisabled;
export const suggestionsCount = (state, getters) =>
- Object.values(getters.notesById).filter((n) => n.suggestions.length).length;
+ Object.values(getters.notesById).filter((n) => n.suggestions?.length).length;
export const hasDrafts = (state, getters, rootState, rootGetters) =>
Boolean(rootGetters['batchComments/hasDrafts']);
diff --git a/app/assets/javascripts/notes/utils.js b/app/assets/javascripts/notes/utils.js
index 7966a884eab..ec18a570960 100644
--- a/app/assets/javascripts/notes/utils.js
+++ b/app/assets/javascripts/notes/utils.js
@@ -1,4 +1,7 @@
/* eslint-disable @gitlab/require-i18n-strings */
+import marked from 'marked';
+import { sanitize } from '~/lib/dompurify';
+import { markdownConfig } from '~/lib/utils/text_utility';
/**
* Tracks snowplow event when User toggles timeline view
@@ -10,3 +13,7 @@ export const trackToggleTimelineView = (enabled) => ({
label: 'Status',
property: enabled,
});
+
+export const renderMarkdown = (rawMarkdown) => {
+ return sanitize(marked(rawMarkdown), markdownConfig);
+};