diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 13:49:51 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 13:49:51 +0000 |
commit | 71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e (patch) | |
tree | 6a2d93ef3fb2d353bb7739e4b57e6541f51cdd71 /app/assets/javascripts/notes | |
parent | a7253423e3403b8c08f8a161e5937e1488f5f407 (diff) | |
download | gitlab-ce-71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e.tar.gz |
Add latest changes from gitlab-org/gitlab@15-9-stable-eev15.9.0-rc42
Diffstat (limited to 'app/assets/javascripts/notes')
11 files changed, 104 insertions, 23 deletions
diff --git a/app/assets/javascripts/notes/components/attachments_warning.vue b/app/assets/javascripts/notes/components/attachments_warning.vue new file mode 100644 index 00000000000..aaa4b0d92b9 --- /dev/null +++ b/app/assets/javascripts/notes/components/attachments_warning.vue @@ -0,0 +1,18 @@ +<script> +import { COMMENT_FORM } from '../i18n'; + +export default { + i18n: COMMENT_FORM.attachmentMsg, + data() { + return { + message: this.$options.i18n, + }; + }, +}; +</script> + +<template> + <div class="issuable-note-warning" data-testid="attachment-warning"> + {{ message }} + </div> +</template> diff --git a/app/assets/javascripts/notes/components/comment_field_layout.vue b/app/assets/javascripts/notes/components/comment_field_layout.vue index 84bda1b0b5c..cc372520c70 100644 --- a/app/assets/javascripts/notes/components/comment_field_layout.vue +++ b/app/assets/javascripts/notes/components/comment_field_layout.vue @@ -1,14 +1,18 @@ <script> +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue'; import EmailParticipantsWarning from './email_participants_warning.vue'; +import AttachmentsWarning from './attachments_warning.vue'; const DEFAULT_NOTEABLE_TYPE = 'Issue'; export default { components: { + AttachmentsWarning, EmailParticipantsWarning, NoteableWarning, }, + mixins: [glFeatureFlagsMixin()], props: { noteableData: { type: Object, @@ -29,6 +33,11 @@ export default { required: false, default: false, }, + containsLink: { + type: Boolean, + required: false, + default: false, + }, }, computed: { isLocked() { @@ -46,6 +55,13 @@ export default { showEmailParticipantsWarning() { return this.emailParticipants.length && !this.isInternalNote; }, + showAttachmentWarning() { + return ( + this.glFeatures.serviceDeskNewNoteEmailNativeAttachments && + this.showEmailParticipantsWarning && + this.containsLink + ); + }, }, }; </script> @@ -68,6 +84,7 @@ export default { :confidential-noteable-docs-path="noteableData.confidential_issues_docs_path" /> <slot></slot> + <attachments-warning v-if="showAttachmentWarning" /> <email-participants-warning v-if="showEmailParticipantsWarning" class="gl-border-t-1 gl-border-t-solid gl-border-t-gray-100 gl-rounded-base gl-rounded-top-left-none! gl-rounded-top-right-none!" diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index c6e7117cf2e..4f7256d0b0e 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -28,6 +28,7 @@ import CommentTypeDropdown from './comment_type_dropdown.vue'; import DiscussionLockedWidget from './discussion_locked_widget.vue'; import NoteSignedOutWidget from './note_signed_out_widget.vue'; +const ATTACHMENT_REGEXP = /!?\[.*?\]\(\/uploads\/[0-9a-f]{32}\/.*?\)/; export default { name: 'CommentForm', i18n: COMMENT_FORM, @@ -176,6 +177,9 @@ export default { disableSubmitButton() { return this.note.length === 0 || this.isSubmitting; }, + containsLink() { + return ATTACHMENT_REGEXP.test(this.note); + }, }, mounted() { // jQuery is needed here because it is a custom event being dispatched with jQuery. @@ -356,6 +360,7 @@ export default { :noteable-data="getNoteableData" :is-internal-note="noteIsInternal" :noteable-type="noteableType" + :contains-link="containsLink" > <markdown-field ref="markdownField" diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index c15c11ed9db..abed95a9706 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -4,12 +4,14 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import Api from '~/api'; import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status'; import { createAlert } from '~/flash'; +import { TYPE_ISSUE } from '~/issues/constants'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { __, sprintf } from '~/locale'; import eventHub from '~/sidebar/event_hub'; import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { splitCamelCase } from '~/lib/utils/text_utility'; +import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue'; import ReplyButton from './note_actions/reply_button.vue'; import TimelineEventButton from './note_actions/timeline_event_button.vue'; @@ -30,6 +32,7 @@ export default { GlDropdownItem, UserAccessRoleBadge, EmojiPicker: () => import('~/emoji/components/picker.vue'), + AbuseCategorySelector, }, directives: { GlTooltip: GlTooltipDirective, @@ -58,11 +61,6 @@ export default { required: false, default: '', }, - reportAbusePath: { - type: String, - required: false, - default: null, - }, isAuthor: { type: Boolean, required: false, @@ -135,11 +133,16 @@ export default { default: '', }, }, + data() { + return { + isReportAbuseDrawerOpen: false, + }; + }, computed: { ...mapState(['isPromoteCommentToTimelineEventInProgress']), ...mapGetters(['getUserDataByProp', 'getNoteableData', 'canUserAddIncidentTimelineEvents']), shouldShowActionsDropdown() { - return this.currentUserId && (this.canEdit || this.canReportAsAbuse); + return this.currentUserId; }, showDeleteAction() { return this.canDelete && !this.canReportAsAbuse && !this.noteUrl; @@ -171,7 +174,7 @@ export default { return this.getNoteableData.assignees || []; }, isIssue() { - return this.targetType === 'issue'; + return this.targetType === TYPE_ISSUE; }, canAssign() { return this.getNoteableData.current_user?.can_set_issue_metadata && this.isIssue; @@ -233,7 +236,7 @@ export default { assignees.push({ id: this.author.id }); } - if (this.targetType === 'issue') { + if (this.targetType === TYPE_ISSUE) { Api.updateIssue(project_id, iid, { assignee_ids: assignees.map((assignee) => assignee.id), }) @@ -252,6 +255,9 @@ export default { awardName, }); }, + toggleReportAbuseDrawer(isOpen) { + this.isReportAbuseDrawerOpen = isOpen; + }, }, }; </script> @@ -261,7 +267,7 @@ export default { <user-access-role-badge v-if="isAuthor" v-gl-tooltip - class="gl-mr-3 d-none d-md-inline-block" + class="gl-mr-3 gl-display-none gl-sm-display-block" :title="displayAuthorBadgeText" > {{ __('Author') }} @@ -269,7 +275,7 @@ export default { <user-access-role-badge v-if="accessLevel" v-gl-tooltip - class="gl-mr-3" + class="gl-mr-3 gl-display-none gl-sm-display-block" :title="displayMemberBadgeText" > {{ accessLevel }} @@ -277,7 +283,7 @@ export default { <user-access-role-badge v-else-if="isContributor" v-gl-tooltip - class="gl-mr-3" + class="gl-mr-3 gl-display-none gl-sm-display-block" :title="displayContributorBadgeText" > {{ __('Contributor') }} @@ -334,7 +340,7 @@ export default { :aria-label="$options.i18n.editCommentLabel" icon="pencil" category="tertiary" - class="note-action-button js-note-edit" + class="note-action-button js-note-edit gl-display-none gl-sm-display-block" data-qa-selector="note_edit_button" @click="onEdit" /> @@ -362,7 +368,18 @@ export default { /> <!-- eslint-enable @gitlab/vue-no-data-toggle --> <ul class="dropdown-menu more-actions-dropdown dropdown-open-left"> - <gl-dropdown-item v-if="canReportAsAbuse" :href="reportAbusePath"> + <gl-dropdown-item + v-if="canEdit" + class="js-note-edit gl-sm-display-none!" + @click.prevent="onEdit" + > + {{ __('Edit comment') }} + </gl-dropdown-item> + <gl-dropdown-item + v-if="canReportAsAbuse" + data-testid="report-abuse-button" + @click="toggleReportAbuseDrawer(true)" + > {{ $options.i18n.reportAbuse }} </gl-dropdown-item> <gl-dropdown-item @@ -380,5 +397,14 @@ export default { </gl-dropdown-item> </ul> </div> + <!-- IMPORTANT: show this component lazily because it causes layout thrashing --> + <!-- https://gitlab.com/gitlab-org/gitlab/-/issues/331172#note_1269378396 --> + <abuse-category-selector + v-if="canReportAsAbuse && isReportAbuseDrawerOpen" + :reported-user-id="authorId" + :reported-from-url="noteUrl" + :show-drawer="isReportAbuseDrawerOpen" + @close-drawer="toggleReportAbuseDrawer(false)" + /> </div> </template> diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue index 79b6139d4b1..c83b3d870d7 100644 --- a/app/assets/javascripts/notes/components/note_header.vue +++ b/app/assets/javascripts/notes/components/note_header.vue @@ -96,6 +96,8 @@ export default { 'text-underline': this.isUsernameLinkHovered, 'author-name-link': true, 'js-user-link': true, + 'gl-overflow-hidden': true, + 'gl-overflow-wrap-break': true, }; }, authorName() { diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 826e7e5a3d0..93575ad57ff 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -43,6 +43,11 @@ export default { SafeHtml, }, mixins: [noteable, resolvable], + inject: { + reportAbusePath: { + default: '', + }, + }, props: { note: { type: Object, @@ -129,7 +134,7 @@ export default { }; }, canReportAsAbuse() { - return Boolean(this.note.report_abuse_path) && this.author.id !== this.getUserData.id; + return Boolean(this.reportAbusePath) && this.author.id !== this.getUserData.id; }, noteAnchorId() { return `note_${this.note.id}`; @@ -488,7 +493,6 @@ export default { :can-delete="note.current_user.can_edit" :can-report-as-abuse="canReportAsAbuse" :can-resolve="canResolve" - :report-abuse-path="note.report_abuse_path" :resolvable="note.resolvable || note.isDraft" :is-resolved="note.resolved || note.resolve_discussion" :is-resolving="isResolving" diff --git a/app/assets/javascripts/notes/components/sidebar_subscription.vue b/app/assets/javascripts/notes/components/sidebar_subscription.vue index 9fc11ff65d5..2a0a3d5414f 100644 --- a/app/assets/javascripts/notes/components/sidebar_subscription.vue +++ b/app/assets/javascripts/notes/components/sidebar_subscription.vue @@ -1,6 +1,6 @@ <script> import { mapActions } from 'vuex'; -import { IssuableType } from '~/issues/constants'; +import { TYPE_EPIC, TYPE_ISSUE } from '~/issues/constants'; import { fetchPolicies } from '~/lib/graphql'; import { confidentialityQueries } from '~/sidebar/constants'; import { defaultClient as gqlClient } from '~/graphql_shared/issuable_client'; @@ -28,7 +28,7 @@ export default { }, }, created() { - if (this.issuableType !== IssuableType.Issue && this.issuableType !== IssuableType.Epic) { + if (this.issuableType !== TYPE_ISSUE && this.issuableType !== TYPE_EPIC) { return; } diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue index 734e08dd586..4437d461308 100644 --- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue +++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue @@ -79,7 +79,7 @@ export default { :link-href="author.path" :img-alt="author.name" img-css-classes="gl-mr-0!" - :img-src="author.avatar_url" + :img-src="author.avatar_url || author.avatarUrl" :img-size="24" :tooltip-text="author.name" tooltip-placement="bottom" @@ -102,7 +102,10 @@ export default { </gl-link> </template> </gl-sprintf> - <time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" /> + <time-ago-tooltip + :time="lastReply.created_at || lastReply.createdAt" + tooltip-placement="bottom" + /> </template> <gl-button v-else diff --git a/app/assets/javascripts/notes/i18n.js b/app/assets/javascripts/notes/i18n.js index 9b5fd69f816..a758a55014a 100644 --- a/app/assets/javascripts/notes/i18n.js +++ b/app/assets/javascripts/notes/i18n.js @@ -45,4 +45,7 @@ export const COMMENT_FORM = { commentHelp: __('Add a general comment to this %{noteableDisplayName}.'), internalCommentHelp: __('Add a confidential internal note to this %{noteableDisplayName}.'), }, + attachmentMsg: s__( + 'Notes|Attachments are sent by email. Attachments over 10 MB are sent as links to your GitLab instance, and only accessible to project members.', + ), }; diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js index 95263e666b2..2e09c9f2288 100644 --- a/app/assets/javascripts/notes/index.js +++ b/app/assets/javascripts/notes/index.js @@ -52,6 +52,7 @@ export default () => { store, provide: { showTimelineViewToggle, + reportAbusePath: notesDataset.reportAbusePath, }, data() { return { diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 5cad091ce2c..f6b9be6ee9b 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -4,6 +4,7 @@ import Vue from 'vue'; import Api from '~/api'; import { createAlert, VARIANT_INFO } from '~/flash'; import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants'; +import { TYPE_ISSUE } from '~/issues/constants'; import axios from '~/lib/utils/axios_utils'; import { __, sprintf } from '~/locale'; import toast from '~/vue_shared/plugins/global_toast'; @@ -20,7 +21,7 @@ import TaskList from '~/task_list'; import mrWidgetEventHub from '~/vue_merge_request_widget/event_hub'; import SidebarStore from '~/sidebar/stores/sidebar_store'; import { convertToGraphQLId } from '~/graphql_shared/utils'; -import { TYPE_NOTE } from '~/graphql_shared/constants'; +import { TYPENAME_NOTE } from '~/graphql_shared/constants'; import notesEventHub from '../event_hub'; import promoteTimelineEvent from '../graphql/promote_timeline_event.mutation.graphql'; @@ -37,7 +38,8 @@ export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) return utils.gqClient .mutate({ - mutation: targetType === 'issue' ? updateIssueLockMutation : updateMergeRequestLockMutation, + mutation: + targetType === TYPE_ISSUE ? updateIssueLockMutation : updateMergeRequestLockMutation, variables: { input: { projectPath: fullPath, @@ -48,7 +50,7 @@ export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) }) .then(({ data }) => { const discussionLocked = - targetType === 'issue' + targetType === TYPE_ISSUE ? data.issueSetLocked.issue.discussionLocked : data.mergeRequestSetLocked.mergeRequest.discussionLocked; @@ -276,7 +278,7 @@ export const promoteCommentToTimelineEvent = ( mutation: promoteTimelineEvent, variables: { input: { - noteId: convertToGraphQLId(TYPE_NOTE, noteId), + noteId: convertToGraphQLId(TYPENAME_NOTE, noteId), }, }, }) |