diff options
Diffstat (limited to 'app/assets/javascripts/design_management_new/components/design_notes')
4 files changed, 0 insertions, 664 deletions
diff --git a/app/assets/javascripts/design_management_new/components/design_notes/design_discussion.vue b/app/assets/javascripts/design_management_new/components/design_notes/design_discussion.vue deleted file mode 100644 index 4aaf43e3a5b..00000000000 --- a/app/assets/javascripts/design_management_new/components/design_notes/design_discussion.vue +++ /dev/null @@ -1,297 +0,0 @@ -<script> -import { ApolloMutation } from 'vue-apollo'; -import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink } from '@gitlab/ui'; -import { s__ } from '~/locale'; -import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; -import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; -import allVersionsMixin from '../../mixins/all_versions'; -import createNoteMutation from '../../graphql/mutations/create_note.mutation.graphql'; -import toggleResolveDiscussionMutation from '../../graphql/mutations/toggle_resolve_discussion.mutation.graphql'; -import getDesignQuery from '../../graphql/queries/get_design.query.graphql'; -import activeDiscussionQuery from '../../graphql/queries/active_discussion.query.graphql'; -import DesignNote from './design_note.vue'; -import DesignReplyForm from './design_reply_form.vue'; -import { updateStoreAfterAddDiscussionComment } from '../../utils/cache_update'; -import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants'; -import ToggleRepliesWidget from './toggle_replies_widget.vue'; - -export default { - components: { - ApolloMutation, - DesignNote, - ReplyPlaceholder, - DesignReplyForm, - GlIcon, - GlLoadingIcon, - GlLink, - ToggleRepliesWidget, - TimeAgoTooltip, - }, - directives: { - GlTooltip: GlTooltipDirective, - }, - mixins: [allVersionsMixin], - props: { - discussion: { - type: Object, - required: true, - }, - noteableId: { - type: String, - required: true, - }, - designId: { - type: String, - required: true, - }, - markdownPreviewPath: { - type: String, - required: false, - default: '', - }, - resolvedDiscussionsExpanded: { - type: Boolean, - required: true, - }, - discussionWithOpenForm: { - type: String, - required: true, - }, - }, - apollo: { - activeDiscussion: { - query: activeDiscussionQuery, - result({ data }) { - const discussionId = data.activeDiscussion.id; - if (this.discussion.resolved && !this.resolvedDiscussionsExpanded) { - return; - } - // We watch any changes to the active discussion from the design pins and scroll to this discussion if it exists - // We don't want scrollIntoView to be triggered from the discussion click itself - if ( - discussionId && - data.activeDiscussion.source === ACTIVE_DISCUSSION_SOURCE_TYPES.pin && - discussionId === this.discussion.notes[0].id - ) { - this.$el.scrollIntoView({ - behavior: 'smooth', - inline: 'start', - }); - } - }, - }, - }, - data() { - return { - discussionComment: '', - isFormRendered: false, - activeDiscussion: {}, - isResolving: false, - shouldChangeResolvedStatus: false, - areRepliesCollapsed: this.discussion.resolved, - }; - }, - computed: { - mutationPayload() { - return { - noteableId: this.noteableId, - body: this.discussionComment, - discussionId: this.discussion.id, - }; - }, - designVariables() { - return { - fullPath: this.projectPath, - iid: this.issueIid, - filenames: [this.$route.params.id], - atVersion: this.designsVersion, - }; - }, - isDiscussionHighlighted() { - return this.discussion.notes[0].id === this.activeDiscussion.id; - }, - resolveCheckboxText() { - return this.discussion.resolved - ? s__('DesignManagement|Unresolve thread') - : s__('DesignManagement|Resolve thread'); - }, - firstNote() { - return this.discussion.notes[0]; - }, - discussionReplies() { - return this.discussion.notes.slice(1); - }, - areRepliesShown() { - return !this.discussion.resolved || !this.areRepliesCollapsed; - }, - resolveIconName() { - return this.discussion.resolved ? 'check-circle-filled' : 'check-circle'; - }, - isRepliesWidgetVisible() { - return this.discussion.resolved && this.discussionReplies.length > 0; - }, - isReplyPlaceholderVisible() { - return this.areRepliesShown || !this.discussionReplies.length; - }, - isFormVisible() { - return this.isFormRendered && this.discussionWithOpenForm === this.discussion.id; - }, - }, - methods: { - addDiscussionComment( - store, - { - data: { createNote }, - }, - ) { - updateStoreAfterAddDiscussionComment( - store, - createNote, - getDesignQuery, - this.designVariables, - this.discussion.id, - ); - }, - onDone() { - this.discussionComment = ''; - this.hideForm(); - if (this.shouldChangeResolvedStatus) { - this.toggleResolvedStatus(); - } - }, - onCreateNoteError(err) { - this.$emit('createNoteError', err); - }, - hideForm() { - this.isFormRendered = false; - this.discussionComment = ''; - }, - showForm() { - this.$emit('openForm', this.discussion.id); - this.isFormRendered = true; - }, - toggleResolvedStatus() { - this.isResolving = true; - this.$apollo - .mutate({ - mutation: toggleResolveDiscussionMutation, - variables: { id: this.discussion.id, resolve: !this.discussion.resolved }, - }) - .then(({ data }) => { - if (data.errors?.length > 0) { - this.$emit('resolveDiscussionError', data.errors[0]); - } - }) - .catch(err => { - this.$emit('resolveDiscussionError', err); - }) - .finally(() => { - this.isResolving = false; - }); - }, - }, - createNoteMutation, -}; -</script> - -<template> - <div class="design-discussion-wrapper"> - <div - class="badge badge-pill gl-display-flex gl-align-items-center gl-justify-content-center" - :class="{ resolved: discussion.resolved }" - type="button" - > - {{ discussion.index }} - </div> - <ul - class="design-discussion bordered-box gl-relative gl-p-0 gl-list-style-none" - data-qa-selector="design_discussion_content" - > - <design-note - :note="firstNote" - :markdown-preview-path="markdownPreviewPath" - :is-resolving="isResolving" - :class="{ 'gl-bg-blue-50': isDiscussionHighlighted }" - @error="$emit('updateNoteError', $event)" - > - <template v-if="discussion.resolvable" #resolveDiscussion> - <button - v-gl-tooltip - :class="{ 'is-active': discussion.resolved }" - :title="resolveCheckboxText" - :aria-label="resolveCheckboxText" - type="button" - class="line-resolve-btn note-action-button gl-mr-3" - data-testid="resolve-button" - @click.stop="toggleResolvedStatus" - > - <gl-icon v-if="!isResolving" :name="resolveIconName" data-testid="resolve-icon" /> - <gl-loading-icon v-else inline /> - </button> - </template> - <template v-if="discussion.resolved" #resolvedStatus> - <p class="gl-text-gray-700 gl-font-sm gl-m-0 gl-mt-5" data-testid="resolved-message"> - {{ __('Resolved by') }} - <gl-link - class="gl-text-gray-700 gl-text-decoration-none gl-font-sm link-inherit-color" - :href="discussion.resolvedBy.webUrl" - target="_blank" - >{{ discussion.resolvedBy.name }}</gl-link - > - <time-ago-tooltip :time="discussion.resolvedAt" tooltip-placement="bottom" /> - </p> - </template> - </design-note> - <toggle-replies-widget - v-if="isRepliesWidgetVisible" - :collapsed="areRepliesCollapsed" - :replies="discussionReplies" - @toggle="areRepliesCollapsed = !areRepliesCollapsed" - /> - <design-note - v-for="note in discussionReplies" - v-show="areRepliesShown" - :key="note.id" - :note="note" - :markdown-preview-path="markdownPreviewPath" - :is-resolving="isResolving" - :class="{ 'gl-bg-blue-50': isDiscussionHighlighted }" - @error="$emit('updateNoteError', $event)" - /> - <li v-show="isReplyPlaceholderVisible" class="reply-wrapper"> - <reply-placeholder - v-if="!isFormVisible" - class="qa-discussion-reply" - :button-text="__('Reply...')" - @onClick="showForm" - /> - <apollo-mutation - v-else - #default="{ mutate, loading }" - :mutation="$options.createNoteMutation" - :variables="{ - input: mutationPayload, - }" - :update="addDiscussionComment" - @done="onDone" - @error="onCreateNoteError" - > - <design-reply-form - v-model="discussionComment" - :is-saving="loading" - :markdown-preview-path="markdownPreviewPath" - @submitForm="mutate" - @cancelForm="hideForm" - > - <template v-if="discussion.resolvable" #resolveCheckbox> - <label data-testid="resolve-checkbox"> - <input v-model="shouldChangeResolvedStatus" type="checkbox" /> - {{ resolveCheckboxText }} - </label> - </template> - </design-reply-form> - </apollo-mutation> - </li> - </ul> - </div> -</template> diff --git a/app/assets/javascripts/design_management_new/components/design_notes/design_note.vue b/app/assets/javascripts/design_management_new/components/design_notes/design_note.vue deleted file mode 100644 index 172e61920ef..00000000000 --- a/app/assets/javascripts/design_management_new/components/design_notes/design_note.vue +++ /dev/null @@ -1,156 +0,0 @@ -<script> -import { ApolloMutation } from 'vue-apollo'; -import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; -import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql'; -import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; -import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; -import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; -import DesignReplyForm from './design_reply_form.vue'; -import { findNoteId } from '../../utils/design_management_utils'; -import { hasErrors } from '../../utils/cache_update'; - -export default { - components: { - UserAvatarLink, - TimelineEntryItem, - TimeAgoTooltip, - DesignReplyForm, - ApolloMutation, - GlIcon, - }, - directives: { - GlTooltip: GlTooltipDirective, - }, - props: { - note: { - type: Object, - required: true, - }, - markdownPreviewPath: { - type: String, - required: false, - default: '', - }, - }, - data() { - return { - noteText: this.note.body, - isEditing: false, - }; - }, - computed: { - author() { - return this.note.author; - }, - noteAnchorId() { - return findNoteId(this.note.id); - }, - isNoteLinked() { - return this.$route.hash === `#note_${this.noteAnchorId}`; - }, - mutationPayload() { - return { - id: this.note.id, - body: this.noteText, - }; - }, - isEditButtonVisible() { - return !this.isEditing && this.note.userPermissions.adminNote; - }, - }, - mounted() { - if (this.isNoteLinked) { - this.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' }); - } - }, - methods: { - hideForm() { - this.isEditing = false; - this.noteText = this.note.body; - }, - onDone({ data }) { - this.hideForm(); - if (hasErrors(data.updateNote)) { - this.$emit('error', data.errors[0]); - } - }, - }, - updateNoteMutation, -}; -</script> - -<template> - <timeline-entry-item :id="`note_${noteAnchorId}`" class="design-note note-form"> - <user-avatar-link - :link-href="author.webUrl" - :img-src="author.avatarUrl" - :img-alt="author.username" - :img-size="40" - /> - <div class="d-flex justify-content-between"> - <div> - <a - v-once - :href="author.webUrl" - class="js-user-link" - :data-user-id="author.id" - :data-username="author.username" - > - <span class="note-header-author-name bold">{{ author.name }}</span> - <span v-if="author.status_tooltip_html" v-html="author.status_tooltip_html"></span> - <span class="note-headline-light">@{{ author.username }}</span> - </a> - <span class="note-headline-light note-headline-meta"> - <span class="system-note-message"> <slot></slot> </span> - <template v-if="note.createdAt"> - <span class="system-note-separator"></span> - <a class="note-timestamp system-note-separator" :href="`#note_${noteAnchorId}`"> - <time-ago-tooltip :time="note.createdAt" tooltip-placement="bottom" /> - </a> - </template> - </span> - </div> - <div class="gl-display-flex"> - <slot name="resolveDiscussion"></slot> - <button - v-if="isEditButtonVisible" - v-gl-tooltip - type="button" - :title="__('Edit comment')" - class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button" - @click="isEditing = true" - > - <gl-icon name="pencil" class="link-highlight" /> - </button> - </div> - </div> - <template v-if="!isEditing"> - <div - class="note-text js-note-text md" - data-qa-selector="note_content" - v-html="note.bodyHtml" - ></div> - <slot name="resolvedStatus"></slot> - </template> - <apollo-mutation - v-else - #default="{ mutate, loading }" - :mutation="$options.updateNoteMutation" - :variables="{ - input: mutationPayload, - }" - @error="$emit('error', $event)" - @done="onDone" - > - <design-reply-form - v-model="noteText" - :is-saving="loading" - :markdown-preview-path="markdownPreviewPath" - :is-new-comment="false" - class="mt-5" - @submitForm="mutate" - @cancelForm="hideForm" - /> - </apollo-mutation> - </timeline-entry-item> -</template> diff --git a/app/assets/javascripts/design_management_new/components/design_notes/design_reply_form.vue b/app/assets/javascripts/design_management_new/components/design_notes/design_reply_form.vue deleted file mode 100644 index 969034909f2..00000000000 --- a/app/assets/javascripts/design_management_new/components/design_notes/design_reply_form.vue +++ /dev/null @@ -1,141 +0,0 @@ -<script> -import { GlDeprecatedButton, GlModal } from '@gitlab/ui'; -import MarkdownField from '~/vue_shared/components/markdown/field.vue'; -import { s__ } from '~/locale'; - -export default { - name: 'DesignReplyForm', - components: { - MarkdownField, - GlDeprecatedButton, - GlModal, - }, - props: { - markdownPreviewPath: { - type: String, - required: false, - default: '', - }, - value: { - type: String, - required: true, - }, - isSaving: { - type: Boolean, - required: true, - }, - isNewComment: { - type: Boolean, - required: false, - default: true, - }, - }, - data() { - return { - formText: this.value, - }; - }, - computed: { - hasValue() { - return this.value.trim().length > 0; - }, - modalSettings() { - if (this.isNewComment) { - return { - title: s__('DesignManagement|Cancel comment confirmation'), - okTitle: s__('DesignManagement|Discard comment'), - cancelTitle: s__('DesignManagement|Keep comment'), - content: s__('DesignManagement|Are you sure you want to cancel creating this comment?'), - }; - } - return { - title: s__('DesignManagement|Cancel comment update confirmation'), - okTitle: s__('DesignManagement|Cancel changes'), - cancelTitle: s__('DesignManagement|Keep changes'), - content: s__('DesignManagement|Are you sure you want to cancel changes to this comment?'), - }; - }, - buttonText() { - return this.isNewComment - ? s__('DesignManagement|Comment') - : s__('DesignManagement|Save comment'); - }, - }, - mounted() { - this.focusInput(); - }, - methods: { - submitForm() { - if (this.hasValue) this.$emit('submitForm'); - }, - cancelComment() { - if (this.hasValue && this.formText !== this.value) { - this.$refs.cancelCommentModal.show(); - } else { - this.$emit('cancelForm'); - } - }, - focusInput() { - this.$refs.textarea.focus(); - }, - }, -}; -</script> - -<template> - <form class="new-note common-note-form" @submit.prevent> - <markdown-field - :markdown-preview-path="markdownPreviewPath" - :can-attach-file="false" - :enable-autocomplete="true" - :textarea-value="value" - markdown-docs-path="/help/user/markdown" - class="bordered-box" - > - <template #textarea> - <textarea - ref="textarea" - :value="value" - class="note-textarea js-gfm-input js-autosize markdown-area" - dir="auto" - data-supports-quick-actions="false" - data-qa-selector="note_textarea" - :aria-label="__('Description')" - :placeholder="__('Write a comment…')" - @input="$emit('input', $event.target.value)" - @keydown.meta.enter="submitForm" - @keydown.ctrl.enter="submitForm" - @keyup.esc.stop="cancelComment" - > - </textarea> - </template> - </markdown-field> - <slot name="resolveCheckbox"></slot> - <div class="note-form-actions gl-display-flex gl-justify-content-space-between"> - <gl-deprecated-button - ref="submitButton" - :disabled="!hasValue || isSaving" - variant="success" - type="submit" - data-track-event="click_button" - data-qa-selector="save_comment_button" - @click="$emit('submitForm')" - > - {{ buttonText }} - </gl-deprecated-button> - <gl-deprecated-button ref="cancelButton" @click="cancelComment">{{ - __('Cancel') - }}</gl-deprecated-button> - </div> - <gl-modal - ref="cancelCommentModal" - ok-variant="danger" - :title="modalSettings.title" - :ok-title="modalSettings.okTitle" - :cancel-title="modalSettings.cancelTitle" - modal-id="cancel-comment-modal" - @ok="$emit('cancelForm')" - >{{ modalSettings.content }} - </gl-modal> - </form> -</template> diff --git a/app/assets/javascripts/design_management_new/components/design_notes/toggle_replies_widget.vue b/app/assets/javascripts/design_management_new/components/design_notes/toggle_replies_widget.vue deleted file mode 100644 index 46c73e3eea8..00000000000 --- a/app/assets/javascripts/design_management_new/components/design_notes/toggle_replies_widget.vue +++ /dev/null @@ -1,70 +0,0 @@ -<script> -import { GlIcon, GlButton, GlLink } from '@gitlab/ui'; -import { __, n__ } from '~/locale'; -import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; - -export default { - name: 'ToggleNotesWidget', - components: { - GlIcon, - GlButton, - GlLink, - TimeAgoTooltip, - }, - props: { - collapsed: { - type: Boolean, - required: true, - }, - replies: { - type: Array, - required: true, - }, - }, - computed: { - lastReply() { - return this.replies[this.replies.length - 1]; - }, - iconName() { - return this.collapsed ? 'chevron-right' : 'chevron-down'; - }, - toggleText() { - return this.collapsed - ? `${this.replies.length} ${n__('reply', 'replies', this.replies.length)}` - : __('Collapse replies'); - }, - }, -}; -</script> - -<template> - <li - class="toggle-comments gl-bg-gray-50 gl-display-flex gl-align-items-center gl-py-3" - :class="{ expanded: !collapsed }" - data-testid="toggle-comments-wrapper" - > - <gl-icon :name="iconName" class="gl-ml-3" @click.stop="$emit('toggle')" /> - <gl-button - variant="link" - class="toggle-comments-button gl-ml-2 gl-mr-2" - @click.stop="$emit('toggle')" - > - {{ toggleText }} - </gl-button> - <template v-if="collapsed"> - <span class="gl-text-gray-700">{{ __('Last reply by') }}</span> - <gl-link - :href="lastReply.author.webUrl" - target="_blank" - class="link-inherit-color gl-text-black-normal gl-text-decoration-none gl-font-weight-bold gl-ml-2 gl-mr-2" - > - {{ lastReply.author.name }} - </gl-link> - <time-ago-tooltip - :time="lastReply.createdAt" - tooltip-placement="bottom" - class="gl-text-gray-700" - /> - </template> - </li> -</template> |