Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/design_management_legacy')
-rw-r--r--app/assets/javascripts/design_management_legacy/components/app.vue3
-rw-r--r--app/assets/javascripts/design_management_legacy/components/delete_button.vue64
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_destroyer.vue66
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_note_pin.vue61
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue297
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue156
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_reply_form.vue141
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/toggle_replies_widget.vue70
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_overlay.vue287
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_presentation.vue322
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_scaler.vue65
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_sidebar.vue178
-rw-r--r--app/assets/javascripts/design_management_legacy/components/image.vue110
-rw-r--r--app/assets/javascripts/design_management_legacy/components/list/item.vue174
-rw-r--r--app/assets/javascripts/design_management_legacy/components/toolbar/index.vue126
-rw-r--r--app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue83
-rw-r--r--app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue48
-rw-r--r--app/assets/javascripts/design_management_legacy/components/upload/button.vue58
-rw-r--r--app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue134
-rw-r--r--app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue76
-rw-r--r--app/assets/javascripts/design_management_legacy/constants.js16
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql.js45
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql24
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql8
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql29
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql5
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql9
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql3
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql4
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql21
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql17
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql3
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql21
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql6
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql4
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql31
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql26
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql12
-rw-r--r--app/assets/javascripts/design_management_legacy/index.js61
-rw-r--r--app/assets/javascripts/design_management_legacy/mixins/all_designs.js49
-rw-r--r--app/assets/javascripts/design_management_legacy/mixins/all_versions.js62
-rw-r--r--app/assets/javascripts/design_management_legacy/pages/design/index.vue378
-rw-r--r--app/assets/javascripts/design_management_legacy/pages/index.vue323
-rw-r--r--app/assets/javascripts/design_management_legacy/router/constants.js3
-rw-r--r--app/assets/javascripts/design_management_legacy/router/index.js35
-rw-r--r--app/assets/javascripts/design_management_legacy/router/routes.js44
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/cache_update.js276
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/design_management_utils.js128
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/error_messages.js95
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/tracking.js27
55 files changed, 0 insertions, 4334 deletions
diff --git a/app/assets/javascripts/design_management_legacy/components/app.vue b/app/assets/javascripts/design_management_legacy/components/app.vue
deleted file mode 100644
index 98240aef810..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/app.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-<template>
- <router-view />
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/delete_button.vue b/app/assets/javascripts/design_management_legacy/components/delete_button.vue
deleted file mode 100644
index 1fd902c9ed7..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/delete_button.vue
+++ /dev/null
@@ -1,64 +0,0 @@
-<script>
-import { GlDeprecatedButton, GlModal, GlModalDirective } from '@gitlab/ui';
-import { uniqueId } from 'lodash';
-
-export default {
- name: 'DeleteButton',
- components: {
- GlDeprecatedButton,
- GlModal,
- },
- directives: {
- GlModalDirective,
- },
- props: {
- isDeleting: {
- type: Boolean,
- required: false,
- default: false,
- },
- buttonClass: {
- type: String,
- required: false,
- default: '',
- },
- buttonVariant: {
- type: String,
- required: false,
- default: '',
- },
- hasSelectedDesigns: {
- type: Boolean,
- required: false,
- default: true,
- },
- },
- data() {
- return {
- modalId: uniqueId('design-deletion-confirmation-'),
- };
- },
-};
-</script>
-
-<template>
- <div>
- <gl-modal
- :modal-id="modalId"
- :title="s__('DesignManagement|Delete designs confirmation')"
- :ok-title="s__('DesignManagement|Delete')"
- ok-variant="danger"
- @ok="$emit('deleteSelectedDesigns')"
- >
- <p>{{ s__('DesignManagement|Are you sure you want to delete the selected designs?') }}</p>
- </gl-modal>
- <gl-deprecated-button
- v-gl-modal-directive="modalId"
- :variant="buttonVariant"
- :disabled="isDeleting || !hasSelectedDesigns"
- :class="buttonClass"
- >
- <slot></slot>
- </gl-deprecated-button>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_destroyer.vue b/app/assets/javascripts/design_management_legacy/components/design_destroyer.vue
deleted file mode 100644
index 62460ca551c..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_destroyer.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-<script>
-import { ApolloMutation } from 'vue-apollo';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import destroyDesignMutation from '../graphql/mutations/destroy_design.mutation.graphql';
-import { updateStoreAfterDesignsDelete } from '../utils/cache_update';
-
-export default {
- components: {
- ApolloMutation,
- },
- props: {
- filenames: {
- type: Array,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- iid: {
- type: String,
- required: true,
- },
- },
- computed: {
- projectQueryBody() {
- return {
- query: getDesignListQuery,
- variables: { fullPath: this.projectPath, iid: this.iid, atVersion: null },
- };
- },
- },
- methods: {
- updateStoreAfterDelete(
- store,
- {
- data: { designManagementDelete },
- },
- ) {
- updateStoreAfterDesignsDelete(
- store,
- designManagementDelete,
- this.projectQueryBody,
- this.filenames,
- );
- },
- },
- destroyDesignMutation,
-};
-</script>
-
-<template>
- <apollo-mutation
- #default="{ mutate, loading, error }"
- :mutation="$options.destroyDesignMutation"
- :variables="{
- filenames,
- projectPath,
- iid,
- }"
- :update="updateStoreAfterDelete"
- v-on="$listeners"
- >
- <slot v-bind="{ mutate, loading, error }"></slot>
- </apollo-mutation>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_note_pin.vue b/app/assets/javascripts/design_management_legacy/components/design_note_pin.vue
deleted file mode 100644
index 2b5e62c2870..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_note_pin.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-
-export default {
- name: 'DesignNotePin',
- components: {
- GlIcon,
- },
- props: {
- position: {
- type: Object,
- required: true,
- },
- label: {
- type: Number,
- required: false,
- default: null,
- },
- repositioning: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- isNewNote() {
- return this.label === null;
- },
- pinStyle() {
- return this.repositioning ? { ...this.position, cursor: 'move' } : this.position;
- },
- pinLabel() {
- return this.isNewNote
- ? __('Comment form position')
- : sprintf(__("Comment '%{label}' position"), { label: this.label });
- },
- },
-};
-</script>
-
-<template>
- <button
- :style="pinStyle"
- :aria-label="pinLabel"
- :class="{
- 'btn-transparent comment-indicator': isNewNote,
- 'js-image-badge badge badge-pill': !isNewNote,
- }"
- class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0"
- type="button"
- @mousedown="$emit('mousedown', $event)"
- @mouseup="$emit('mouseup', $event)"
- @click="$emit('click', $event)"
- >
- <gl-icon v-if="isNewNote" name="image-comment-dark" :size="24" />
- <template v-else>
- {{ label }}
- </template>
- </button>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue
deleted file mode 100644
index 6a20517eed7..00000000000
--- a/app/assets/javascripts/design_management_legacy/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-500 gl-font-sm gl-m-0 gl-mt-5" data-testid="resolved-message">
- {{ __('Resolved by') }}
- <gl-link
- class="gl-text-gray-500 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_legacy/components/design_notes/design_note.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue
deleted file mode 100644
index b1f3a43a66d..00000000000
--- a/app/assets/javascripts/design_management_legacy/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.$refs.anchor.$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}`" ref="anchor" 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_legacy/components/design_notes/design_reply_form.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_reply_form.vue
deleted file mode 100644
index 969034909f2..00000000000
--- a/app/assets/javascripts/design_management_legacy/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_legacy/components/design_notes/toggle_replies_widget.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/toggle_replies_widget.vue
deleted file mode 100644
index 2e366282de3..00000000000
--- a/app/assets/javascripts/design_management_legacy/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-500">{{ __('Last reply by') }}</span>
- <gl-link
- :href="lastReply.author.webUrl"
- target="_blank"
- class="link-inherit-color gl-text-body 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-500"
- />
- </template>
- </li>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_overlay.vue b/app/assets/javascripts/design_management_legacy/components/design_overlay.vue
deleted file mode 100644
index 926e7c74802..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_overlay.vue
+++ /dev/null
@@ -1,287 +0,0 @@
-<script>
-import activeDiscussionQuery from '../graphql/queries/active_discussion.query.graphql';
-import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
-import DesignNotePin from './design_note_pin.vue';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
-
-export default {
- name: 'DesignOverlay',
- components: {
- DesignNotePin,
- },
- props: {
- dimensions: {
- type: Object,
- required: true,
- },
- position: {
- type: Object,
- required: true,
- },
- notes: {
- type: Array,
- required: false,
- default: () => [],
- },
- currentCommentForm: {
- type: Object,
- required: false,
- default: null,
- },
- disableCommenting: {
- type: Boolean,
- required: false,
- default: false,
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- },
- apollo: {
- activeDiscussion: {
- query: activeDiscussionQuery,
- },
- },
- data() {
- return {
- movingNoteNewPosition: null,
- movingNoteStartPosition: null,
- activeDiscussion: {},
- };
- },
- computed: {
- overlayStyle() {
- const cursor = this.disableCommenting ? 'unset' : undefined;
-
- return {
- cursor,
- width: `${this.dimensions.width}px`,
- height: `${this.dimensions.height}px`,
- ...this.position,
- };
- },
- isMovingCurrentComment() {
- return Boolean(this.movingNoteStartPosition && !this.movingNoteStartPosition.noteId);
- },
- currentCommentPositionStyle() {
- return this.isMovingCurrentComment && this.movingNoteNewPosition
- ? this.getNotePositionStyle(this.movingNoteNewPosition)
- : this.getNotePositionStyle(this.currentCommentForm);
- },
- },
- methods: {
- setNewNoteCoordinates({ x, y }) {
- this.$emit('openCommentForm', { x, y });
- },
- getNoteRelativePosition(position) {
- const { x, y, width, height } = position;
- const widthRatio = this.dimensions.width / width;
- const heightRatio = this.dimensions.height / height;
- return {
- left: Math.round(x * widthRatio),
- top: Math.round(y * heightRatio),
- };
- },
- getNotePositionStyle(position) {
- const { left, top } = this.getNoteRelativePosition(position);
- return {
- left: `${left}px`,
- top: `${top}px`,
- };
- },
- getMovingNotePositionDelta(e) {
- let deltaX = 0;
- let deltaY = 0;
-
- if (this.movingNoteStartPosition) {
- const { clientX, clientY } = this.movingNoteStartPosition;
- deltaX = e.clientX - clientX;
- deltaY = e.clientY - clientY;
- }
-
- return {
- deltaX,
- deltaY,
- };
- },
- isMovingNote(noteId) {
- const movingNoteId = this.movingNoteStartPosition?.noteId;
- return Boolean(movingNoteId && movingNoteId === noteId);
- },
- canMoveNote(note) {
- const { userPermissions } = note;
- const { adminNote } = userPermissions || {};
-
- return Boolean(adminNote);
- },
- isPositionInOverlay(position) {
- const { top, left } = this.getNoteRelativePosition(position);
- const { height, width } = this.dimensions;
-
- return top >= 0 && top <= height && left >= 0 && left <= width;
- },
- onNewNoteMove(e) {
- if (!this.isMovingCurrentComment) return;
-
- const { deltaX, deltaY } = this.getMovingNotePositionDelta(e);
- const x = this.currentCommentForm.x + deltaX;
- const y = this.currentCommentForm.y + deltaY;
-
- const movingNoteNewPosition = {
- x,
- y,
- width: this.dimensions.width,
- height: this.dimensions.height,
- };
-
- if (!this.isPositionInOverlay(movingNoteNewPosition)) {
- this.onNewNoteMouseup();
- return;
- }
-
- this.movingNoteNewPosition = movingNoteNewPosition;
- },
- onExistingNoteMove(e) {
- const note = this.notes.find(({ id }) => id === this.movingNoteStartPosition.noteId);
- if (!note || !this.canMoveNote(note)) return;
-
- const { position } = note;
- const { width, height } = position;
- const widthRatio = this.dimensions.width / width;
- const heightRatio = this.dimensions.height / height;
-
- const { deltaX, deltaY } = this.getMovingNotePositionDelta(e);
- const x = position.x * widthRatio + deltaX;
- const y = position.y * heightRatio + deltaY;
-
- const movingNoteNewPosition = {
- x,
- y,
- width: this.dimensions.width,
- height: this.dimensions.height,
- };
-
- if (!this.isPositionInOverlay(movingNoteNewPosition)) {
- this.onExistingNoteMouseup();
- return;
- }
-
- this.movingNoteNewPosition = movingNoteNewPosition;
- },
- onNewNoteMouseup() {
- if (!this.movingNoteNewPosition) return;
-
- const { x, y } = this.movingNoteNewPosition;
- this.setNewNoteCoordinates({ x, y });
- },
- onExistingNoteMouseup(note) {
- if (!this.movingNoteStartPosition || !this.movingNoteNewPosition) {
- this.updateActiveDiscussion(note.id);
- this.$emit('closeCommentForm');
- return;
- }
-
- const { x, y } = this.movingNoteNewPosition;
- this.$emit('moveNote', {
- noteId: this.movingNoteStartPosition.noteId,
- discussionId: this.movingNoteStartPosition.discussionId,
- coordinates: { x, y },
- });
- },
- onNoteMousedown({ clientX, clientY }, note) {
- this.movingNoteStartPosition = {
- noteId: note?.id,
- discussionId: note?.discussion.id,
- clientX,
- clientY,
- };
- },
- onOverlayMousemove(e) {
- if (!this.movingNoteStartPosition) return;
-
- if (this.isMovingCurrentComment) {
- this.onNewNoteMove(e);
- } else {
- this.onExistingNoteMove(e);
- }
- },
- onNoteMouseup(note) {
- if (!this.movingNoteStartPosition) return;
-
- if (this.isMovingCurrentComment) {
- this.onNewNoteMouseup();
- } else {
- this.onExistingNoteMouseup(note);
- }
-
- this.movingNoteStartPosition = null;
- this.movingNoteNewPosition = null;
- },
- onAddCommentMouseup({ offsetX, offsetY }) {
- if (this.disableCommenting) return;
- if (this.activeDiscussion.id) {
- this.updateActiveDiscussion();
- }
-
- this.setNewNoteCoordinates({ x: offsetX, y: offsetY });
- },
- updateActiveDiscussion(id) {
- this.$apollo.mutate({
- mutation: updateActiveDiscussionMutation,
- variables: {
- id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.pin,
- },
- });
- },
- isNoteInactive(note) {
- return this.activeDiscussion.id && this.activeDiscussion.id !== note.id;
- },
- designPinClass(note) {
- return { inactive: this.isNoteInactive(note), resolved: note.resolved };
- },
- },
-};
-</script>
-
-<template>
- <div
- class="position-absolute image-diff-overlay frame"
- :style="overlayStyle"
- @mousemove="onOverlayMousemove"
- @mouseleave="onNoteMouseup"
- >
- <button
- v-show="!disableCommenting"
- type="button"
- class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button"
- data-qa-selector="design_image_button"
- @mouseup="onAddCommentMouseup"
- ></button>
- <template v-for="note in notes">
- <design-note-pin
- v-if="resolvedDiscussionsExpanded || !note.resolved"
- :key="note.id"
- :label="note.index"
- :repositioning="isMovingNote(note.id)"
- :position="
- isMovingNote(note.id) && movingNoteNewPosition
- ? getNotePositionStyle(movingNoteNewPosition)
- : getNotePositionStyle(note.position)
- "
- :class="designPinClass(note)"
- @mousedown.stop="onNoteMousedown($event, note)"
- @mouseup.stop="onNoteMouseup(note)"
- />
- </template>
-
- <design-note-pin
- v-if="currentCommentForm"
- :position="currentCommentPositionStyle"
- :repositioning="isMovingCurrentComment"
- @mousedown.stop="onNoteMousedown"
- @mouseup.stop="onNoteMouseup"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_presentation.vue b/app/assets/javascripts/design_management_legacy/components/design_presentation.vue
deleted file mode 100644
index 84dbb2809d9..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_presentation.vue
+++ /dev/null
@@ -1,322 +0,0 @@
-<script>
-import { throttle } from 'lodash';
-import DesignImage from './image.vue';
-import DesignOverlay from './design_overlay.vue';
-
-const CLICK_DRAG_BUFFER_PX = 2;
-
-export default {
- components: {
- DesignImage,
- DesignOverlay,
- },
- props: {
- image: {
- type: String,
- required: false,
- default: '',
- },
- imageName: {
- type: String,
- required: false,
- default: '',
- },
- discussions: {
- type: Array,
- required: true,
- },
- isAnnotating: {
- type: Boolean,
- required: false,
- default: false,
- },
- scale: {
- type: Number,
- required: false,
- default: 1,
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- overlayDimensions: null,
- overlayPosition: null,
- currentAnnotationPosition: null,
- zoomFocalPoint: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- },
- initialLoad: true,
- lastDragPosition: null,
- isDraggingDesign: false,
- };
- },
- computed: {
- discussionStartingNotes() {
- return this.discussions.map(discussion => ({
- ...discussion.notes[0],
- index: discussion.index,
- }));
- },
- currentCommentForm() {
- return (this.isAnnotating && this.currentAnnotationPosition) || null;
- },
- presentationStyle() {
- return {
- cursor: this.isDraggingDesign ? 'grabbing' : undefined,
- };
- },
- },
- beforeDestroy() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- presentationViewport.removeEventListener('scroll', this.scrollThrottled, false);
- },
- mounted() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- this.scrollThrottled = throttle(() => {
- this.shiftZoomFocalPoint();
- }, 400);
-
- presentationViewport.addEventListener('scroll', this.scrollThrottled, false);
- },
- methods: {
- syncCurrentAnnotationPosition() {
- if (!this.currentAnnotationPosition) return;
-
- const widthRatio = this.overlayDimensions.width / this.currentAnnotationPosition.width;
- const heightRatio = this.overlayDimensions.height / this.currentAnnotationPosition.height;
- const x = this.currentAnnotationPosition.x * widthRatio;
- const y = this.currentAnnotationPosition.y * heightRatio;
-
- this.currentAnnotationPosition = this.getAnnotationPositon({ x, y });
- },
- setOverlayDimensions(overlayDimensions) {
- this.overlayDimensions = overlayDimensions;
-
- // every time we set overlay dimensions, we need to
- // update the current annotation as well
- this.syncCurrentAnnotationPosition();
- },
- setOverlayPosition() {
- if (!this.overlayDimensions) {
- this.overlayPosition = {};
- }
-
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- // default to center
- this.overlayPosition = {
- left: `calc(50% - ${this.overlayDimensions.width / 2}px)`,
- top: `calc(50% - ${this.overlayDimensions.height / 2}px)`,
- };
-
- // if the overlay overflows, then don't center
- if (this.overlayDimensions.width > presentationViewport.offsetWidth) {
- this.overlayPosition.left = '0';
- }
- if (this.overlayDimensions.height > presentationViewport.offsetHeight) {
- this.overlayPosition.top = '0';
- }
- },
- /**
- * Return a point that represents the center of an
- * overflowing child element w.r.t it's parent
- */
- getViewportCenter() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return {};
-
- // get height of scroll bars (i.e. the max values for scrollTop, scrollLeft)
- const scrollBarWidth = presentationViewport.scrollWidth - presentationViewport.offsetWidth;
- const scrollBarHeight = presentationViewport.scrollHeight - presentationViewport.offsetHeight;
-
- // determine how many child pixels have been scrolled
- const xScrollRatio =
- presentationViewport.scrollLeft > 0 ? presentationViewport.scrollLeft / scrollBarWidth : 0;
- const yScrollRatio =
- presentationViewport.scrollTop > 0 ? presentationViewport.scrollTop / scrollBarHeight : 0;
- const xScrollOffset =
- (presentationViewport.scrollWidth - presentationViewport.offsetWidth - 0) * xScrollRatio;
- const yScrollOffset =
- (presentationViewport.scrollHeight - presentationViewport.offsetHeight - 0) * yScrollRatio;
-
- const viewportCenterX = presentationViewport.offsetWidth / 2;
- const viewportCenterY = presentationViewport.offsetHeight / 2;
- const focalPointX = viewportCenterX + xScrollOffset;
- const focalPointY = viewportCenterY + yScrollOffset;
-
- return {
- x: focalPointX,
- y: focalPointY,
- };
- },
- /**
- * Scroll the viewport such that the focal point is positioned centrally
- */
- scrollToFocalPoint() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- const scrollX = this.zoomFocalPoint.x - presentationViewport.offsetWidth / 2;
- const scrollY = this.zoomFocalPoint.y - presentationViewport.offsetHeight / 2;
-
- presentationViewport.scrollTo(scrollX, scrollY);
- },
- scaleZoomFocalPoint() {
- const { x, y, width, height } = this.zoomFocalPoint;
- const widthRatio = this.overlayDimensions.width / width;
- const heightRatio = this.overlayDimensions.height / height;
-
- this.zoomFocalPoint = {
- x: Math.round(x * widthRatio * 100) / 100,
- y: Math.round(y * heightRatio * 100) / 100,
- ...this.overlayDimensions,
- };
- },
- shiftZoomFocalPoint() {
- this.zoomFocalPoint = {
- ...this.getViewportCenter(),
- ...this.overlayDimensions,
- };
- },
- onImageResize(imageDimensions) {
- this.setOverlayDimensions(imageDimensions);
- this.setOverlayPosition();
-
- this.$nextTick(() => {
- if (this.initialLoad) {
- // set focal point on initial load
- this.shiftZoomFocalPoint();
- this.initialLoad = false;
- } else {
- this.scaleZoomFocalPoint();
- this.scrollToFocalPoint();
- }
- });
- },
- getAnnotationPositon(coordinates) {
- const { x, y } = coordinates;
- const { width, height } = this.overlayDimensions;
- return {
- x: Math.round(x),
- y: Math.round(y),
- width: Math.round(width),
- height: Math.round(height),
- };
- },
- openCommentForm(coordinates) {
- this.currentAnnotationPosition = this.getAnnotationPositon(coordinates);
- this.$emit('openCommentForm', this.currentAnnotationPosition);
- },
- closeCommentForm() {
- this.currentAnnotationPosition = null;
- this.$emit('closeCommentForm');
- },
- moveNote({ noteId, discussionId, coordinates }) {
- const position = this.getAnnotationPositon(coordinates);
- this.$emit('moveNote', { noteId, discussionId, position });
- },
- onPresentationMousedown({ clientX, clientY }) {
- if (!this.isDesignOverflowing()) return;
-
- this.lastDragPosition = {
- x: clientX,
- y: clientY,
- };
- },
- getDragDelta(clientX, clientY) {
- return {
- deltaX: this.lastDragPosition.x - clientX,
- deltaY: this.lastDragPosition.y - clientY,
- };
- },
- exceedsDragThreshold(clientX, clientY) {
- const { deltaX, deltaY } = this.getDragDelta(clientX, clientY);
-
- return Math.abs(deltaX) > CLICK_DRAG_BUFFER_PX || Math.abs(deltaY) > CLICK_DRAG_BUFFER_PX;
- },
- shouldDragDesign(clientX, clientY) {
- return (
- this.lastDragPosition &&
- (this.isDraggingDesign || this.exceedsDragThreshold(clientX, clientY))
- );
- },
- onPresentationMousemove({ clientX, clientY }) {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport || !this.shouldDragDesign(clientX, clientY)) return;
-
- this.isDraggingDesign = true;
-
- const { scrollLeft, scrollTop } = presentationViewport;
- const { deltaX, deltaY } = this.getDragDelta(clientX, clientY);
- presentationViewport.scrollTo(scrollLeft + deltaX, scrollTop + deltaY);
-
- this.lastDragPosition = {
- x: clientX,
- y: clientY,
- };
- },
- onPresentationMouseup() {
- this.lastDragPosition = null;
- this.isDraggingDesign = false;
- },
- isDesignOverflowing() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return false;
-
- return (
- presentationViewport.scrollWidth > presentationViewport.offsetWidth ||
- presentationViewport.scrollHeight > presentationViewport.offsetHeight
- );
- },
- },
-};
-</script>
-
-<template>
- <div
- ref="presentationViewport"
- class="h-100 w-100 p-3 overflow-auto position-relative"
- :style="presentationStyle"
- @mousedown="onPresentationMousedown"
- @mousemove="onPresentationMousemove"
- @mouseup="onPresentationMouseup"
- @mouseleave="onPresentationMouseup"
- @touchstart="onPresentationMousedown"
- @touchmove="onPresentationMousemove"
- @touchend="onPresentationMouseup"
- @touchcancel="onPresentationMouseup"
- >
- <div class="h-100 w-100 d-flex align-items-center position-relative">
- <design-image
- v-if="image"
- :image="image"
- :name="imageName"
- :scale="scale"
- @resize="onImageResize"
- />
- <design-overlay
- v-if="overlayDimensions && overlayPosition"
- :dimensions="overlayDimensions"
- :position="overlayPosition"
- :notes="discussionStartingNotes"
- :current-comment-form="currentCommentForm"
- :disable-commenting="isDraggingDesign"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- @openCommentForm="openCommentForm"
- @closeCommentForm="closeCommentForm"
- @moveNote="moveNote"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_scaler.vue b/app/assets/javascripts/design_management_legacy/components/design_scaler.vue
deleted file mode 100644
index 55dee74bef5..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_scaler.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-
-const SCALE_STEP_SIZE = 0.2;
-const DEFAULT_SCALE = 1;
-const MIN_SCALE = 1;
-const MAX_SCALE = 2;
-
-export default {
- components: {
- GlIcon,
- },
- data() {
- return {
- scale: DEFAULT_SCALE,
- };
- },
- computed: {
- disableReset() {
- return this.scale <= MIN_SCALE;
- },
- disableDecrease() {
- return this.scale === DEFAULT_SCALE;
- },
- disableIncrease() {
- return this.scale >= MAX_SCALE;
- },
- },
- methods: {
- setScale(scale) {
- if (scale < MIN_SCALE) {
- return;
- }
-
- this.scale = Math.round(scale * 100) / 100;
- this.$emit('scale', this.scale);
- },
- incrementScale() {
- this.setScale(this.scale + SCALE_STEP_SIZE);
- },
- decrementScale() {
- this.setScale(this.scale - SCALE_STEP_SIZE);
- },
- resetScale() {
- this.setScale(DEFAULT_SCALE);
- },
- },
-};
-</script>
-
-<template>
- <div class="design-scaler btn-group" role="group">
- <button class="btn" :disabled="disableDecrease" @click="decrementScale">
- <span class="d-flex-center gl-icon s16">
- –
- </span>
- </button>
- <button class="btn" :disabled="disableReset" @click="resetScale">
- <gl-icon name="redo" />
- </button>
- <button class="btn" :disabled="disableIncrease" @click="incrementScale">
- <gl-icon name="plus" />
- </button>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_sidebar.vue b/app/assets/javascripts/design_management_legacy/components/design_sidebar.vue
deleted file mode 100644
index 622120e2008..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_sidebar.vue
+++ /dev/null
@@ -1,178 +0,0 @@
-<script>
-import Cookies from 'js-cookie';
-import { GlCollapse, GlButton, GlPopover } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
-import { extractDiscussions, extractParticipants } from '../utils/design_management_utils';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
-import DesignDiscussion from './design_notes/design_discussion.vue';
-import Participants from '~/sidebar/components/participants/participants.vue';
-
-export default {
- components: {
- DesignDiscussion,
- Participants,
- GlCollapse,
- GlButton,
- GlPopover,
- },
- props: {
- design: {
- type: Object,
- required: true,
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- isResolvedCommentsPopoverHidden: parseBoolean(Cookies.get(this.$options.cookieKey)),
- discussionWithOpenForm: '',
- };
- },
- computed: {
- discussions() {
- return extractDiscussions(this.design.discussions);
- },
- issue() {
- return {
- ...this.design.issue,
- webPath: this.design.issue.webPath.substr(1),
- };
- },
- discussionParticipants() {
- return extractParticipants(this.issue.participants);
- },
- resolvedDiscussions() {
- return this.discussions.filter(discussion => discussion.resolved);
- },
- unresolvedDiscussions() {
- return this.discussions.filter(discussion => !discussion.resolved);
- },
- resolvedCommentsToggleIcon() {
- return this.resolvedDiscussionsExpanded ? 'chevron-down' : 'chevron-right';
- },
- },
- methods: {
- handleSidebarClick() {
- this.isResolvedCommentsPopoverHidden = true;
- Cookies.set(this.$options.cookieKey, 'true', { expires: 365 * 10 });
- this.updateActiveDiscussion();
- },
- updateActiveDiscussion(id) {
- this.$apollo.mutate({
- mutation: updateActiveDiscussionMutation,
- variables: {
- id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.discussion,
- },
- });
- },
- closeCommentForm() {
- this.comment = '';
- this.$emit('closeCommentForm');
- },
- updateDiscussionWithOpenForm(id) {
- this.discussionWithOpenForm = id;
- },
- },
- resolveCommentsToggleText: s__('DesignManagement|Resolved Comments'),
- cookieKey: 'hide_design_resolved_comments_popover',
-};
-</script>
-
-<template>
- <div class="image-notes" @click="handleSidebarClick">
- <h2 class="gl-font-weight-bold gl-mt-0">
- {{ issue.title }}
- </h2>
- <a
- class="gl-text-gray-400 gl-text-decoration-none gl-mb-6 gl-display-block"
- :href="issue.webUrl"
- >{{ issue.webPath }}</a
- >
- <participants
- :participants="discussionParticipants"
- :show-participant-label="false"
- class="gl-mb-4"
- />
- <h2
- v-if="unresolvedDiscussions.length === 0"
- class="new-discussion-disclaimer gl-font-base gl-m-0 gl-mb-4"
- data-testid="new-discussion-disclaimer"
- >
- {{ s__("DesignManagement|Click the image where you'd like to start a new discussion") }}
- </h2>
- <design-discussion
- v-for="discussion in unresolvedDiscussions"
- :key="discussion.id"
- :discussion="discussion"
- :design-id="$route.params.id"
- :noteable-id="design.id"
- :markdown-preview-path="markdownPreviewPath"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- :discussion-with-open-form="discussionWithOpenForm"
- data-testid="unresolved-discussion"
- @createNoteError="$emit('onDesignDiscussionError', $event)"
- @updateNoteError="$emit('updateNoteError', $event)"
- @resolveDiscussionError="$emit('resolveDiscussionError', $event)"
- @click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
- @openForm="updateDiscussionWithOpenForm"
- />
- <template v-if="resolvedDiscussions.length > 0">
- <gl-button
- id="resolved-comments"
- data-testid="resolved-comments"
- :icon="resolvedCommentsToggleIcon"
- variant="link"
- class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4"
- @click="$emit('toggleResolvedComments')"
- >{{ $options.resolveCommentsToggleText }} ({{ resolvedDiscussions.length }})
- </gl-button>
- <gl-popover
- v-if="!isResolvedCommentsPopoverHidden"
- :show="!isResolvedCommentsPopoverHidden"
- target="resolved-comments"
- container="popovercontainer"
- placement="top"
- :title="s__('DesignManagement|Resolved Comments')"
- >
- <p>
- {{
- s__(
- 'DesignManagement|Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below',
- )
- }}
- </p>
- <a href="#" rel="noopener noreferrer" target="_blank">{{
- s__('DesignManagement|Learn more about resolving comments')
- }}</a>
- </gl-popover>
- <gl-collapse :visible="resolvedDiscussionsExpanded" class="gl-mt-3">
- <design-discussion
- v-for="discussion in resolvedDiscussions"
- :key="discussion.id"
- :discussion="discussion"
- :design-id="$route.params.id"
- :noteable-id="design.id"
- :markdown-preview-path="markdownPreviewPath"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- :discussion-with-open-form="discussionWithOpenForm"
- data-testid="resolved-discussion"
- @error="$emit('onDesignDiscussionError', $event)"
- @updateNoteError="$emit('updateNoteError', $event)"
- @openForm="updateDiscussionWithOpenForm"
- @click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
- />
- </gl-collapse>
- </template>
- <slot name="replyForm"></slot>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/image.vue b/app/assets/javascripts/design_management_legacy/components/image.vue
deleted file mode 100644
index 91b7b576e0c..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/image.vue
+++ /dev/null
@@ -1,110 +0,0 @@
-<script>
-import { throttle } from 'lodash';
-import { GlIcon } from '@gitlab/ui';
-
-export default {
- components: {
- GlIcon,
- },
- props: {
- image: {
- type: String,
- required: false,
- default: '',
- },
- name: {
- type: String,
- required: false,
- default: '',
- },
- scale: {
- type: Number,
- required: false,
- default: 1,
- },
- },
- data() {
- return {
- baseImageSize: null,
- imageStyle: null,
- imageError: false,
- };
- },
- watch: {
- scale(val) {
- this.zoom(val);
- },
- },
- beforeDestroy() {
- window.removeEventListener('resize', this.resizeThrottled, false);
- },
- mounted() {
- this.onImgLoad();
-
- this.resizeThrottled = throttle(() => {
- // NOTE: if imageStyle is set, then baseImageSize
- // won't change due to resize. We must still emit a
- // `resize` event so that the parent can handle
- // resizes appropriately (e.g. for design_overlay)
- this.setBaseImageSize();
- }, 400);
- window.addEventListener('resize', this.resizeThrottled, false);
- },
- methods: {
- onImgLoad() {
- requestIdleCallback(this.setBaseImageSize, { timeout: 1000 });
- },
- onImgError() {
- this.imageError = true;
- },
- setBaseImageSize() {
- const { contentImg } = this.$refs;
- if (!contentImg || contentImg.offsetHeight === 0 || contentImg.offsetWidth === 0) return;
-
- this.baseImageSize = {
- height: contentImg.offsetHeight,
- width: contentImg.offsetWidth,
- };
- this.onResize({ width: this.baseImageSize.width, height: this.baseImageSize.height });
- },
- onResize({ width, height }) {
- this.$emit('resize', { width, height });
- },
- zoom(amount) {
- if (amount === 1) {
- this.imageStyle = null;
- this.$nextTick(() => {
- this.setBaseImageSize();
- });
- return;
- }
- const width = this.baseImageSize.width * amount;
- const height = this.baseImageSize.height * amount;
-
- this.imageStyle = {
- width: `${width}px`,
- height: `${height}px`,
- };
-
- this.onResize({ width, height });
- },
- },
-};
-</script>
-
-<template>
- <div class="m-auto js-design-image">
- <gl-icon v-if="imageError" class="text-secondary-100" name="media-broken" :size="48" />
- <img
- v-show="!imageError"
- ref="contentImg"
- class="mh-100"
- :src="image"
- :alt="name"
- :style="imageStyle"
- :class="{ 'img-fluid': !imageStyle }"
- @error="onImgError"
- @load="onImgLoad"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/list/item.vue b/app/assets/javascripts/design_management_legacy/components/list/item.vue
deleted file mode 100644
index 13c703b8a88..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/list/item.vue
+++ /dev/null
@@ -1,174 +0,0 @@
-<script>
-import { GlLoadingIcon, GlIcon, GlIntersectionObserver } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
-import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
-import { n__, __ } from '~/locale';
-import { DESIGN_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- GlLoadingIcon,
- GlIntersectionObserver,
- GlIcon,
- Icon,
- Timeago,
- },
- props: {
- id: {
- type: [Number, String],
- required: true,
- },
- event: {
- type: String,
- required: true,
- },
- notesCount: {
- type: Number,
- required: true,
- },
- image: {
- type: String,
- required: true,
- },
- filename: {
- type: String,
- required: true,
- },
- updatedAt: {
- type: String,
- required: false,
- default: null,
- },
- isUploading: {
- type: Boolean,
- required: false,
- default: true,
- },
- imageV432x230: {
- type: String,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- imageLoading: true,
- imageError: false,
- wasInView: false,
- };
- },
- computed: {
- icon() {
- const normalizedEvent = this.event.toLowerCase();
- const icons = {
- creation: {
- name: 'file-addition-solid',
- classes: 'text-success-500',
- tooltip: __('Added in this version'),
- },
- modification: {
- name: 'file-modified-solid',
- classes: 'text-primary-500',
- tooltip: __('Modified in this version'),
- },
- deletion: {
- name: 'file-deletion-solid',
- classes: 'text-danger-500',
- tooltip: __('Deleted in this version'),
- },
- };
-
- return icons[normalizedEvent] ? icons[normalizedEvent] : {};
- },
- notesLabel() {
- return n__('%d comment', '%d comments', this.notesCount);
- },
- imageLink() {
- return this.wasInView ? this.imageV432x230 || this.image : '';
- },
- showLoadingSpinner() {
- return this.imageLoading || this.isUploading;
- },
- showImageErrorIcon() {
- return this.wasInView && this.imageError;
- },
- showImage() {
- return !this.showLoadingSpinner && !this.showImageErrorIcon;
- },
- },
- methods: {
- onImageLoad() {
- this.imageLoading = false;
- this.imageError = false;
- },
- onImageError() {
- this.imageLoading = false;
- this.imageError = true;
- },
- onAppear() {
- // do nothing if image has previously
- // been in view
- if (this.wasInView) {
- return;
- }
-
- this.wasInView = true;
- this.imageLoading = true;
- },
- },
- DESIGN_ROUTE_NAME,
-};
-</script>
-
-<template>
- <router-link
- :to="{
- name: $options.DESIGN_ROUTE_NAME,
- params: { id: filename },
- query: $route.query,
- }"
- class="card cursor-pointer text-plain js-design-list-item design-list-item"
- >
- <div class="card-body p-0 d-flex-center overflow-hidden position-relative">
- <div v-if="icon.name" data-testid="designEvent" class="design-event position-absolute">
- <span :title="icon.tooltip" :aria-label="icon.tooltip">
- <icon :name="icon.name" :size="18" :class="icon.classes" />
- </span>
- </div>
- <gl-intersection-observer @appear="onAppear">
- <gl-loading-icon v-if="showLoadingSpinner" size="md" />
- <gl-icon
- v-else-if="showImageErrorIcon"
- name="media-broken"
- class="text-secondary"
- :size="32"
- />
- <img
- v-show="showImage"
- :src="imageLink"
- :alt="filename"
- class="block mx-auto mw-100 mh-100 design-img"
- data-qa-selector="design_image"
- @load="onImageLoad"
- @error="onImageError"
- />
- </gl-intersection-observer>
- </div>
- <div class="card-footer d-flex w-100">
- <div class="d-flex flex-column str-truncated-100">
- <span class="bold str-truncated-100" data-qa-selector="design_file_name">{{
- filename
- }}</span>
- <span v-if="updatedAt" class="str-truncated-100">
- {{ __('Updated') }} <timeago :time="updatedAt" tooltip-placement="bottom" />
- </span>
- </div>
- <div v-if="notesCount" class="ml-auto d-flex align-items-center text-secondary">
- <icon name="comments" class="ml-1" />
- <span :aria-label="notesLabel" class="ml-1">
- {{ notesCount }}
- </span>
- </div>
- </div>
- </router-link>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/toolbar/index.vue b/app/assets/javascripts/design_management_legacy/components/toolbar/index.vue
deleted file mode 100644
index b998dfc47b8..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/toolbar/index.vue
+++ /dev/null
@@ -1,126 +0,0 @@
-<script>
-import { GlDeprecatedButton } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import Pagination from './pagination.vue';
-import DeleteButton from '../delete_button.vue';
-import permissionsQuery from '../../graphql/queries/design_permissions.query.graphql';
-import appDataQuery from '../../graphql/queries/app_data.query.graphql';
-import { DESIGNS_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- Icon,
- Pagination,
- DeleteButton,
- GlDeprecatedButton,
- },
- mixins: [timeagoMixin],
- props: {
- id: {
- type: String,
- required: true,
- },
- isDeleting: {
- type: Boolean,
- required: true,
- },
- filename: {
- type: String,
- required: false,
- default: '',
- },
- updatedAt: {
- type: String,
- required: false,
- default: null,
- },
- updatedBy: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- isLatestVersion: {
- type: Boolean,
- required: true,
- },
- image: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- permissions: {
- createDesign: false,
- },
- projectPath: '',
- issueIid: null,
- };
- },
- apollo: {
- appData: {
- query: appDataQuery,
- manual: true,
- result({ data: { projectPath, issueIid } }) {
- this.projectPath = projectPath;
- this.issueIid = issueIid;
- },
- },
- permissions: {
- query: permissionsQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- };
- },
- update: data => data.project.issue.userPermissions,
- },
- },
- computed: {
- updatedText() {
- return sprintf(__('Updated %{updated_at} by %{updated_by}'), {
- updated_at: this.timeFormatted(this.updatedAt),
- updated_by: this.updatedBy.name,
- });
- },
- canDeleteDesign() {
- return this.permissions.createDesign;
- },
- },
- DESIGNS_ROUTE_NAME,
-};
-</script>
-
-<template>
- <header class="d-flex p-2 bg-white align-items-center js-design-header">
- <router-link
- :to="{
- name: $options.DESIGNS_ROUTE_NAME,
- query: $route.query,
- }"
- :aria-label="s__('DesignManagement|Go back to designs')"
- class="mr-3 text-plain d-flex justify-content-center align-items-center"
- >
- <icon :size="18" name="close" />
- </router-link>
- <div class="overflow-hidden d-flex align-items-center">
- <h2 class="m-0 str-truncated-100 gl-font-base">{{ filename }}</h2>
- <small v-if="updatedAt" class="text-secondary">{{ updatedText }}</small>
- </div>
- <pagination :id="id" class="ml-auto flex-shrink-0" />
- <gl-deprecated-button :href="image" class="mr-2">
- <icon :size="18" name="download" />
- </gl-deprecated-button>
- <delete-button
- v-if="isLatestVersion && canDeleteDesign"
- :is-deleting="isDeleting"
- button-variant="danger"
- @deleteSelectedDesigns="$emit('delete')"
- >
- <icon :size="18" name="remove" />
- </delete-button>
- </header>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue b/app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue
deleted file mode 100644
index bf62a8f66a6..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue
+++ /dev/null
@@ -1,83 +0,0 @@
-<script>
-/* global Mousetrap */
-import 'mousetrap';
-import { s__, sprintf } from '~/locale';
-import PaginationButton from './pagination_button.vue';
-import allDesignsMixin from '../../mixins/all_designs';
-import { DESIGN_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- PaginationButton,
- },
- mixins: [allDesignsMixin],
- props: {
- id: {
- type: String,
- required: true,
- },
- },
- computed: {
- designsCount() {
- return this.designs.length;
- },
- currentIndex() {
- return this.designs.findIndex(design => design.filename === this.id);
- },
- paginationText() {
- return sprintf(s__('DesignManagement|%{current_design} of %{designs_count}'), {
- current_design: this.currentIndex + 1,
- designs_count: this.designsCount,
- });
- },
- previousDesign() {
- if (!this.designsCount) return null;
-
- return this.designs[this.currentIndex - 1];
- },
- nextDesign() {
- if (!this.designsCount) return null;
-
- return this.designs[this.currentIndex + 1];
- },
- },
- mounted() {
- Mousetrap.bind('left', () => this.navigateToDesign(this.previousDesign));
- Mousetrap.bind('right', () => this.navigateToDesign(this.nextDesign));
- },
- beforeDestroy() {
- Mousetrap.unbind(['left', 'right'], this.navigateToDesign);
- },
- methods: {
- navigateToDesign(design) {
- if (design) {
- this.$router.push({
- name: DESIGN_ROUTE_NAME,
- params: { id: design.filename },
- query: this.$route.query,
- });
- }
- },
- },
-};
-</script>
-
-<template>
- <div v-if="designsCount" class="d-flex align-items-center">
- {{ paginationText }}
- <div class="btn-group ml-3 mr-3">
- <pagination-button
- :design="previousDesign"
- :title="s__('DesignManagement|Go to previous design')"
- icon-name="angle-left"
- class="js-previous-design"
- />
- <pagination-button
- :design="nextDesign"
- :title="s__('DesignManagement|Go to next design')"
- icon-name="angle-right"
- class="js-next-design"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue b/app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue
deleted file mode 100644
index f00ecefca01..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-<script>
-import Icon from '~/vue_shared/components/icon.vue';
-import { DESIGN_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- Icon,
- },
- props: {
- design: {
- type: Object,
- required: false,
- default: null,
- },
- title: {
- type: String,
- required: true,
- },
- iconName: {
- type: String,
- required: true,
- },
- },
- computed: {
- designLink() {
- if (!this.design) return {};
-
- return {
- name: DESIGN_ROUTE_NAME,
- params: { id: this.design.filename },
- query: this.$route.query,
- };
- },
- },
-};
-</script>
-
-<template>
- <router-link
- :to="designLink"
- :disabled="!design"
- :class="{ disabled: !design }"
- :aria-label="title"
- class="btn btn-default"
- >
- <icon :name="iconName" />
- </router-link>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/button.vue b/app/assets/javascripts/design_management_legacy/components/upload/button.vue
deleted file mode 100644
index 68555104a3c..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/upload/button.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-<script>
-import { GlDeprecatedButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import { VALID_DESIGN_FILE_MIMETYPE } from '../../constants';
-
-export default {
- components: {
- GlDeprecatedButton,
- GlLoadingIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- isSaving: {
- type: Boolean,
- required: true,
- },
- },
- methods: {
- openFileUpload() {
- this.$refs.fileUpload.click();
- },
- onFileUploadChange(e) {
- this.$emit('upload', e.target.files);
- },
- },
- VALID_DESIGN_FILE_MIMETYPE,
-};
-</script>
-
-<template>
- <div>
- <gl-deprecated-button
- v-gl-tooltip.hover
- :title="
- s__(
- 'DesignManagement|Adding a design with the same filename replaces the file in a new version.',
- )
- "
- :disabled="isSaving"
- variant="success"
- @click="openFileUpload"
- >
- {{ s__('DesignManagement|Upload designs') }}
- <gl-loading-icon v-if="isSaving" inline class="ml-1" />
- </gl-deprecated-button>
-
- <input
- ref="fileUpload"
- type="file"
- name="design_file"
- :accept="$options.VALID_DESIGN_FILE_MIMETYPE.mimetype"
- class="hide"
- multiple
- @change="onFileUploadChange"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue b/app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue
deleted file mode 100644
index e435c84c959..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue
+++ /dev/null
@@ -1,134 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import uploadDesignMutation from '../../graphql/mutations/upload_design.mutation.graphql';
-import { UPLOAD_DESIGN_INVALID_FILETYPE_ERROR } from '../../utils/error_messages';
-import { isValidDesignFile } from '../../utils/design_management_utils';
-import { VALID_DATA_TRANSFER_TYPE, VALID_DESIGN_FILE_MIMETYPE } from '../../constants';
-
-export default {
- components: {
- GlIcon,
- GlLink,
- GlSprintf,
- },
- data() {
- return {
- dragCounter: 0,
- isDragDataValid: false,
- };
- },
- computed: {
- dragging() {
- return this.dragCounter !== 0;
- },
- },
- methods: {
- isValidUpload(files) {
- return files.every(isValidDesignFile);
- },
- isValidDragDataType({ dataTransfer }) {
- return Boolean(dataTransfer && dataTransfer.types.some(t => t === VALID_DATA_TRANSFER_TYPE));
- },
- ondrop({ dataTransfer = {} }) {
- this.dragCounter = 0;
- // User already had feedback when dropzone was active, so bail here
- if (!this.isDragDataValid) {
- return;
- }
-
- const { files } = dataTransfer;
- if (!this.isValidUpload(Array.from(files))) {
- createFlash(UPLOAD_DESIGN_INVALID_FILETYPE_ERROR);
- return;
- }
-
- this.$emit('change', files);
- },
- ondragenter(e) {
- this.dragCounter += 1;
- this.isDragDataValid = this.isValidDragDataType(e);
- },
- ondragleave() {
- this.dragCounter -= 1;
- },
- openFileUpload() {
- this.$refs.fileUpload.click();
- },
- onDesignInputChange(e) {
- this.$emit('change', e.target.files);
- },
- },
- uploadDesignMutation,
- VALID_DESIGN_FILE_MIMETYPE,
-};
-</script>
-
-<template>
- <div
- class="w-100 position-relative"
- @dragstart.prevent.stop
- @dragend.prevent.stop
- @dragover.prevent.stop
- @dragenter.prevent.stop="ondragenter"
- @dragleave.prevent.stop="ondragleave"
- @drop.prevent.stop="ondrop"
- >
- <slot>
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- @click="openFileUpload"
- >
- <div class="d-flex-center flex-column text-center">
- <gl-icon name="doc-new" :size="48" class="mb-4" />
- <p>
- <gl-sprintf
- :message="
- __(
- '%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}.',
- )
- "
- >
- <template #lineOne="{ content }"
- ><span class="d-block">{{ content }}</span>
- </template>
-
- <template #link="{ content }">
- <gl-link class="h-100 w-100" @click.stop="openFileUpload">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
- </button>
-
- <input
- ref="fileUpload"
- type="file"
- name="design_file"
- :accept="$options.VALID_DESIGN_FILE_MIMETYPE.mimetype"
- class="hide"
- multiple
- @change="onDesignInputChange"
- />
- </slot>
- <transition name="design-dropzone-fade">
- <div
- v-show="dragging"
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- >
- <div v-show="!isDragDataValid" class="mw-50 text-center">
- <h3>{{ __('Oh no!') }}</h3>
- <span>{{
- __(
- 'You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.',
- )
- }}</span>
- </div>
- <div v-show="isDragDataValid" class="mw-50 text-center">
- <h3>{{ __('Incoming!') }}</h3>
- <span>{{ __('Drop your designs to start your upload.') }}</span>
- </div>
- </div>
- </transition>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue b/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
deleted file mode 100644
index 879d2523848..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
+++ /dev/null
@@ -1,76 +0,0 @@
-<script>
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import allVersionsMixin from '../../mixins/all_versions';
-import { findVersionId } from '../../utils/design_management_utils';
-
-export default {
- components: {
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- },
- mixins: [allVersionsMixin],
- computed: {
- queryVersion() {
- return this.$route.query.version;
- },
- currentVersionIdx() {
- if (!this.queryVersion) return 0;
-
- const idx = this.allVersions.findIndex(
- version => this.findVersionId(version.node.id) === this.queryVersion,
- );
-
- // if the currentVersionId isn't a valid version (i.e. not in allVersions)
- // then return the latest version (index 0)
- return idx !== -1 ? idx : 0;
- },
- currentVersionId() {
- if (this.queryVersion) return this.queryVersion;
-
- const currentVersion = this.allVersions[this.currentVersionIdx];
- return this.findVersionId(currentVersion.node.id);
- },
- dropdownText() {
- if (this.isLatestVersion) {
- return __('Showing Latest Version');
- }
- // allVersions is sorted in reverse chronological order (latest first)
- const currentVersionNumber = this.allVersions.length - this.currentVersionIdx;
-
- return sprintf(__('Showing Version #%{versionNumber}'), {
- versionNumber: currentVersionNumber,
- });
- },
- },
- methods: {
- findVersionId,
- },
-};
-</script>
-
-<template>
- <gl-deprecated-dropdown :text="dropdownText" variant="link" class="design-version-dropdown">
- <gl-deprecated-dropdown-item v-for="(version, index) in allVersions" :key="version.node.id">
- <router-link
- class="d-flex js-version-link"
- :to="{ path: $route.path, query: { version: findVersionId(version.node.id) } }"
- >
- <div class="flex-grow-1 ml-2">
- <div>
- <strong
- >{{ __('Version') }} {{ allVersions.length - index }}
- <span v-if="findVersionId(version.node.id) === latestVersionId"
- >({{ __('latest') }})</span
- >
- </strong>
- </div>
- </div>
- <i
- v-if="findVersionId(version.node.id) === currentVersionId"
- class="fa fa-check float-right gl-mr-2"
- ></i>
- </router-link>
- </gl-deprecated-dropdown-item>
- </gl-deprecated-dropdown>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/constants.js b/app/assets/javascripts/design_management_legacy/constants.js
deleted file mode 100644
index 21ff361a277..00000000000
--- a/app/assets/javascripts/design_management_legacy/constants.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// WARNING: replace this with something
-// more sensical as per https://gitlab.com/gitlab-org/gitlab/issues/118611
-export const VALID_DESIGN_FILE_MIMETYPE = {
- mimetype: 'image/*',
- regex: /image\/.+/,
-};
-
-// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
-export const VALID_DATA_TRANSFER_TYPE = 'Files';
-
-export const ACTIVE_DISCUSSION_SOURCE_TYPES = {
- pin: 'pin',
- discussion: 'discussion',
-};
-
-export const DESIGN_DETAIL_LAYOUT_CLASSLIST = ['design-detail-layout', 'overflow-hidden', 'm-0'];
diff --git a/app/assets/javascripts/design_management_legacy/graphql.js b/app/assets/javascripts/design_management_legacy/graphql.js
deleted file mode 100644
index fae337aa75b..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import { uniqueId } from 'lodash';
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
-import createDefaultClient from '~/lib/graphql';
-import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
-import typeDefs from './graphql/typedefs.graphql';
-
-Vue.use(VueApollo);
-
-const resolvers = {
- Mutation: {
- updateActiveDiscussion: (_, { id = null, source }, { cache }) => {
- const data = cache.readQuery({ query: activeDiscussionQuery });
- data.activeDiscussion = {
- __typename: 'ActiveDiscussion',
- id,
- source,
- };
- cache.writeQuery({ query: activeDiscussionQuery, data });
- },
- },
-};
-
-const defaultClient = createDefaultClient(
- resolvers,
- // This config is added temporarily to resolve an issue with duplicate design IDs.
- // Should be removed as soon as https://gitlab.com/gitlab-org/gitlab/issues/13495 is resolved
- {
- cacheConfig: {
- dataIdFromObject: object => {
- // eslint-disable-next-line no-underscore-dangle, @gitlab/require-i18n-strings
- if (object.__typename === 'Design') {
- return object.id && object.image ? `${object.id}-${object.image}` : uniqueId();
- }
- return defaultDataIdFromObject(object);
- },
- },
- typeDefs,
- },
-);
-
-export default new VueApollo({
- defaultClient,
-});
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql
deleted file mode 100644
index 4b1703e41c3..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql
+++ /dev/null
@@ -1,24 +0,0 @@
-#import "./design_note.fragment.graphql"
-#import "./design_list.fragment.graphql"
-#import "./diff_refs.fragment.graphql"
-#import "./discussion_resolved_status.fragment.graphql"
-
-fragment DesignItem on Design {
- ...DesignListItem
- fullPath
- diffRefs {
- ...DesignDiffRefs
- }
- discussions {
- nodes {
- id
- replyId
- ...ResolvedStatus
- notes {
- nodes {
- ...DesignNote
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql
deleted file mode 100644
index bc3132f9b42..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql
+++ /dev/null
@@ -1,8 +0,0 @@
-fragment DesignListItem on Design {
- id
- event
- filename
- notesCount
- image
- imageV432x230
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql
deleted file mode 100644
index 26edd2c0be1..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql
+++ /dev/null
@@ -1,29 +0,0 @@
-#import "./diff_refs.fragment.graphql"
-#import "~/graphql_shared/fragments/author.fragment.graphql"
-#import "./note_permissions.fragment.graphql"
-
-fragment DesignNote on Note {
- id
- author {
- ...Author
- }
- body
- bodyHtml
- createdAt
- resolved
- position {
- diffRefs {
- ...DesignDiffRefs
- }
- x
- y
- height
- width
- }
- userPermissions {
- ...DesignNotePermissions
- }
- discussion {
- id
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql
deleted file mode 100644
index 984a55814b0..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-fragment DesignDiffRefs on DiffRefs {
- baseSha
- startSha
- headSha
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql
deleted file mode 100644
index 7483b508721..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-fragment ResolvedStatus on Discussion {
- resolvable
- resolved
- resolvedAt
- resolvedBy {
- name
- webUrl
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql
deleted file mode 100644
index c243e39f3d3..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-fragment DesignNotePermissions on NotePermissions {
- adminNote
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql
deleted file mode 100644
index 7eb40b12f51..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql
+++ /dev/null
@@ -1,4 +0,0 @@
-fragment VersionListItem on DesignVersion {
- id
- sha
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql
deleted file mode 100644
index c8ade328120..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql
+++ /dev/null
@@ -1,21 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation createImageDiffNote($input: CreateImageDiffNoteInput!) {
- createImageDiffNote(input: $input) {
- note {
- ...DesignNote
- discussion {
- id
- replyId
- notes {
- edges {
- node {
- ...DesignNote
- }
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql
deleted file mode 100644
index 184ee6955dc..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation createNote($input: CreateNoteInput!) {
- createNote(input: $input) {
- note {
- ...DesignNote
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql
deleted file mode 100644
index 0b3cf636cdb..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/version.fragment.graphql"
-
-mutation destroyDesign($filenames: [String!]!, $projectPath: ID!, $iid: ID!) {
- designManagementDelete(input: { projectPath: $projectPath, iid: $iid, filenames: $filenames }) {
- version {
- ...VersionListItem
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql
deleted file mode 100644
index 1157fc05d5f..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-#import "../fragments/discussion_resolved_status.fragment.graphql"
-
-mutation toggleResolveDiscussion($id: ID!, $resolve: Boolean!) {
- discussionToggleResolve(input: { id: $id, resolve: $resolve }) {
- discussion {
- id
- ...ResolvedStatus
- notes {
- nodes {
- ...DesignNote
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql
deleted file mode 100644
index a24b6737159..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-mutation updateActiveDiscussion($id: String, $source: String) {
- updateActiveDiscussion(id: $id, source: $source) @client
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql
deleted file mode 100644
index 5562ca9d89f..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation updateImageDiffNote($input: UpdateImageDiffNoteInput!) {
- updateImageDiffNote(input: $input) {
- errors
- note {
- ...DesignNote
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql
deleted file mode 100644
index b995e99fb6a..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation updateNote($input: UpdateNoteInput!) {
- updateNote(input: $input) {
- note {
- ...DesignNote
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql
deleted file mode 100644
index d694e6558a0..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql
+++ /dev/null
@@ -1,21 +0,0 @@
-#import "../fragments/design.fragment.graphql"
-
-mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
- designManagementUpload(input: { projectPath: $projectPath, iid: $iid, files: $files }) {
- designs {
- ...DesignItem
- versions {
- edges {
- node {
- id
- sha
- }
- }
- }
- }
- skippedDesigns {
- filename
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql
deleted file mode 100644
index 111023cea68..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql
+++ /dev/null
@@ -1,6 +0,0 @@
-query activeDiscussion {
- activeDiscussion @client {
- id
- source
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql
deleted file mode 100644
index e1269761206..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql
+++ /dev/null
@@ -1,4 +0,0 @@
-query projectFullPath {
- projectPath @client
- issueIid @client
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql
deleted file mode 100644
index a87b256dc95..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-query permissions($fullPath: ID!, $iid: String!) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- userPermissions {
- createDesign
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql
deleted file mode 100644
index 07a9af55787..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql
+++ /dev/null
@@ -1,31 +0,0 @@
-#import "../fragments/design.fragment.graphql"
-#import "~/graphql_shared/fragments/author.fragment.graphql"
-
-query getDesign($fullPath: ID!, $iid: String!, $atVersion: ID, $filenames: [String!]) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- designCollection {
- designs(atVersion: $atVersion, filenames: $filenames) {
- edges {
- node {
- ...DesignItem
- issue {
- title
- webPath
- webUrl
- participants {
- edges {
- node {
- ...Author
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql
deleted file mode 100644
index 121a50555b3..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-#import "../fragments/design_list.fragment.graphql"
-#import "../fragments/version.fragment.graphql"
-
-query getDesignList($fullPath: ID!, $iid: String!, $atVersion: ID) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- designCollection {
- designs(atVersion: $atVersion) {
- edges {
- node {
- ...DesignListItem
- }
- }
- }
- versions {
- edges {
- node {
- ...VersionListItem
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql b/app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql
deleted file mode 100644
index fdbad4a90e0..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql
+++ /dev/null
@@ -1,12 +0,0 @@
-type ActiveDiscussion {
- id: ID
- source: String
-}
-
-extend type Query {
- activeDiscussion: ActiveDiscussion
-}
-
-extend type Mutation {
- updateActiveDiscussion(id: ID!, source: String!): Boolean
-}
diff --git a/app/assets/javascripts/design_management_legacy/index.js b/app/assets/javascripts/design_management_legacy/index.js
deleted file mode 100644
index 1fc5779515a..00000000000
--- a/app/assets/javascripts/design_management_legacy/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-// This application is being moved, please do not touch this files
-// Please see https://gitlab.com/gitlab-org/gitlab/-/issues/14744#note_364468096 for details
-
-import $ from 'jquery';
-import Vue from 'vue';
-import createRouter from './router';
-import App from './components/app.vue';
-import apolloProvider from './graphql';
-import getDesignListQuery from './graphql/queries/get_design_list.query.graphql';
-import { DESIGNS_ROUTE_NAME, ROOT_ROUTE_NAME } from './router/constants';
-
-export default () => {
- const el = document.querySelector('.js-design-management');
- const badge = document.querySelector('.js-designs-count');
- const { issueIid, projectPath, issuePath } = el.dataset;
- const router = createRouter(issuePath);
-
- $('.js-issue-tabs').on('shown.bs.tab', ({ target: { id } }) => {
- if (id === 'designs' && router.currentRoute.name === ROOT_ROUTE_NAME) {
- router.push({ name: DESIGNS_ROUTE_NAME });
- } else if (id === 'discussion') {
- router.push({ name: ROOT_ROUTE_NAME });
- }
- });
-
- apolloProvider.clients.defaultClient.cache.writeData({
- data: {
- projectPath,
- issueIid,
- activeDiscussion: {
- __typename: 'ActiveDiscussion',
- id: null,
- source: null,
- },
- },
- });
-
- apolloProvider.clients.defaultClient
- .watchQuery({
- query: getDesignListQuery,
- variables: {
- fullPath: projectPath,
- iid: issueIid,
- atVersion: null,
- },
- })
- .subscribe(({ data }) => {
- if (badge) {
- badge.textContent = data.project.issue.designCollection.designs.edges.length;
- }
- });
-
- return new Vue({
- el,
- router,
- apolloProvider,
- render(createElement) {
- return createElement(App);
- },
- });
-};
diff --git a/app/assets/javascripts/design_management_legacy/mixins/all_designs.js b/app/assets/javascripts/design_management_legacy/mixins/all_designs.js
deleted file mode 100644
index 544429928d2..00000000000
--- a/app/assets/javascripts/design_management_legacy/mixins/all_designs.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import { propertyOf } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__ } from '~/locale';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import { extractNodes } from '../utils/design_management_utils';
-import allVersionsMixin from './all_versions';
-import { DESIGNS_ROUTE_NAME } from '../router/constants';
-
-export default {
- mixins: [allVersionsMixin],
- apollo: {
- designs: {
- query: getDesignListQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- atVersion: this.designsVersion,
- };
- },
- update: data => {
- const designEdges = propertyOf(data)(['project', 'issue', 'designCollection', 'designs']);
- if (designEdges) {
- return extractNodes(designEdges);
- }
- return [];
- },
- error() {
- this.error = true;
- },
- result() {
- if (this.$route.query.version && !this.hasValidVersion) {
- createFlash(
- s__(
- 'DesignManagement|Requested design version does not exist. Showing latest version instead',
- ),
- );
- this.$router.replace({ name: DESIGNS_ROUTE_NAME, query: { version: undefined } });
- }
- },
- },
- },
- data() {
- return {
- designs: [],
- error: false,
- };
- },
-};
diff --git a/app/assets/javascripts/design_management_legacy/mixins/all_versions.js b/app/assets/javascripts/design_management_legacy/mixins/all_versions.js
deleted file mode 100644
index 3966fe71732..00000000000
--- a/app/assets/javascripts/design_management_legacy/mixins/all_versions.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import appDataQuery from '../graphql/queries/app_data.query.graphql';
-import { findVersionId } from '../utils/design_management_utils';
-
-export default {
- apollo: {
- appData: {
- query: appDataQuery,
- manual: true,
- result({ data: { projectPath, issueIid } }) {
- this.projectPath = projectPath;
- this.issueIid = issueIid;
- },
- },
- allVersions: {
- query: getDesignListQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- atVersion: null,
- };
- },
- update: data => data.project.issue.designCollection.versions.edges,
- },
- },
- computed: {
- hasValidVersion() {
- return (
- this.$route.query.version &&
- this.allVersions &&
- this.allVersions.some(version => version.node.id.endsWith(this.$route.query.version))
- );
- },
- designsVersion() {
- return this.hasValidVersion
- ? `gid://gitlab/DesignManagement::Version/${this.$route.query.version}`
- : null;
- },
- latestVersionId() {
- const latestVersion = this.allVersions[0];
- return latestVersion && findVersionId(latestVersion.node.id);
- },
- isLatestVersion() {
- if (this.allVersions.length > 0) {
- return (
- !this.$route.query.version ||
- !this.latestVersionId ||
- this.$route.query.version === this.latestVersionId
- );
- }
- return true;
- },
- },
- data() {
- return {
- allVersions: [],
- projectPath: '',
- issueIid: null,
- };
- },
-};
diff --git a/app/assets/javascripts/design_management_legacy/pages/design/index.vue b/app/assets/javascripts/design_management_legacy/pages/design/index.vue
deleted file mode 100644
index 2ada9eff8c6..00000000000
--- a/app/assets/javascripts/design_management_legacy/pages/design/index.vue
+++ /dev/null
@@ -1,378 +0,0 @@
-<script>
-import Mousetrap from 'mousetrap';
-import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
-import { ApolloMutation } from 'vue-apollo';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { fetchPolicies } from '~/lib/graphql';
-import allVersionsMixin from '../../mixins/all_versions';
-import Toolbar from '../../components/toolbar/index.vue';
-import DesignDestroyer from '../../components/design_destroyer.vue';
-import DesignScaler from '../../components/design_scaler.vue';
-import DesignPresentation from '../../components/design_presentation.vue';
-import DesignReplyForm from '../../components/design_notes/design_reply_form.vue';
-import DesignSidebar from '../../components/design_sidebar.vue';
-import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
-import appDataQuery from '../../graphql/queries/app_data.query.graphql';
-import createImageDiffNoteMutation from '../../graphql/mutations/create_image_diff_note.mutation.graphql';
-import updateImageDiffNoteMutation from '../../graphql/mutations/update_image_diff_note.mutation.graphql';
-import updateActiveDiscussionMutation from '../../graphql/mutations/update_active_discussion.mutation.graphql';
-import {
- extractDiscussions,
- extractDesign,
- updateImageDiffNoteOptimisticResponse,
-} from '../../utils/design_management_utils';
-import {
- updateStoreAfterAddImageDiffNote,
- updateStoreAfterUpdateImageDiffNote,
-} from '../../utils/cache_update';
-import {
- ADD_DISCUSSION_COMMENT_ERROR,
- ADD_IMAGE_DIFF_NOTE_ERROR,
- UPDATE_IMAGE_DIFF_NOTE_ERROR,
- DESIGN_NOT_FOUND_ERROR,
- DESIGN_VERSION_NOT_EXIST_ERROR,
- UPDATE_NOTE_ERROR,
- designDeletionError,
-} from '../../utils/error_messages';
-import { trackDesignDetailView } from '../../utils/tracking';
-import { DESIGNS_ROUTE_NAME } from '../../router/constants';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
-
-export default {
- components: {
- ApolloMutation,
- DesignReplyForm,
- DesignPresentation,
- DesignScaler,
- DesignDestroyer,
- Toolbar,
- GlLoadingIcon,
- GlAlert,
- DesignSidebar,
- },
- mixins: [allVersionsMixin],
- props: {
- id: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- design: {},
- comment: '',
- annotationCoordinates: null,
- projectPath: '',
- errorMessage: '',
- issueIid: '',
- scale: 1,
- resolvedDiscussionsExpanded: false,
- };
- },
- apollo: {
- appData: {
- query: appDataQuery,
- manual: true,
- result({ data: { projectPath, issueIid } }) {
- this.projectPath = projectPath;
- this.issueIid = issueIid;
- },
- },
- design: {
- query: getDesignQuery,
- // We want to see cached design version if we have one, and fetch newer version on the background to update discussions
- fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
- variables() {
- return this.designVariables;
- },
- update: data => extractDesign(data),
- result(res) {
- this.onDesignQueryResult(res);
- },
- error() {
- this.onQueryError(DESIGN_NOT_FOUND_ERROR);
- },
- },
- },
- computed: {
- isFirstLoading() {
- // We only want to show spinner on initial design load (when opened from a deep link to design)
- // If we already have cached a design, loading shouldn't be indicated to user
- return this.$apollo.queries.design.loading && !this.design.filename;
- },
- discussions() {
- if (!this.design.discussions) {
- return [];
- }
- return extractDiscussions(this.design.discussions);
- },
- markdownPreviewPath() {
- return `/${this.projectPath}/preview_markdown?target_type=Issue`;
- },
- isSubmitButtonDisabled() {
- return this.comment.trim().length === 0;
- },
- designVariables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- filenames: [this.$route.params.id],
- atVersion: this.designsVersion,
- };
- },
- mutationPayload() {
- const { x, y, width, height } = this.annotationCoordinates;
- return {
- noteableId: this.design.id,
- body: this.comment,
- position: {
- headSha: this.design.diffRefs.headSha,
- baseSha: this.design.diffRefs.baseSha,
- startSha: this.design.diffRefs.startSha,
- x,
- y,
- width,
- height,
- paths: {
- newPath: this.design.fullPath,
- },
- },
- };
- },
- isAnnotating() {
- return Boolean(this.annotationCoordinates);
- },
- resolvedDiscussions() {
- return this.discussions.filter(discussion => discussion.resolved);
- },
- },
- watch: {
- resolvedDiscussions(val) {
- if (!val.length) {
- this.resolvedDiscussionsExpanded = false;
- }
- },
- },
- mounted() {
- Mousetrap.bind('esc', this.closeDesign);
- this.trackEvent();
- // We need to reset the active discussion when opening a new design
- this.updateActiveDiscussion();
- },
- beforeDestroy() {
- Mousetrap.unbind('esc', this.closeDesign);
- },
- methods: {
- addImageDiffNoteToStore(
- store,
- {
- data: { createImageDiffNote },
- },
- ) {
- updateStoreAfterAddImageDiffNote(
- store,
- createImageDiffNote,
- getDesignQuery,
- this.designVariables,
- );
- },
- updateImageDiffNoteInStore(
- store,
- {
- data: { updateImageDiffNote },
- },
- ) {
- return updateStoreAfterUpdateImageDiffNote(
- store,
- updateImageDiffNote,
- getDesignQuery,
- this.designVariables,
- );
- },
- onMoveNote({ noteId, discussionId, position }) {
- const discussion = this.discussions.find(({ id }) => id === discussionId);
- const note = discussion.notes.find(
- ({ discussion: noteDiscussion }) => noteDiscussion.id === discussionId,
- );
-
- const mutationPayload = {
- optimisticResponse: updateImageDiffNoteOptimisticResponse(note, {
- position,
- }),
- variables: {
- input: {
- id: noteId,
- position,
- },
- },
- mutation: updateImageDiffNoteMutation,
- update: this.updateImageDiffNoteInStore,
- };
-
- return this.$apollo.mutate(mutationPayload).catch(e => this.onUpdateImageDiffNoteError(e));
- },
- onDesignQueryResult({ data, loading }) {
- // On the initial load with cache-and-network policy data is undefined while loading is true
- // To prevent throwing an error, we don't perform any logic until loading is false
- if (loading) {
- return;
- }
-
- if (!data || !extractDesign(data)) {
- this.onQueryError(DESIGN_NOT_FOUND_ERROR);
- } else if (this.$route.query.version && !this.hasValidVersion) {
- this.onQueryError(DESIGN_VERSION_NOT_EXIST_ERROR);
- }
- },
- onQueryError(message) {
- // because we redirect user to /designs (the issue page),
- // we want to create these flashes on the issue page
- createFlash(message);
- this.$router.push({ name: this.$options.DESIGNS_ROUTE_NAME });
- },
- onError(message, e) {
- this.errorMessage = message;
- throw e;
- },
- onCreateImageDiffNoteError(e) {
- this.onError(ADD_IMAGE_DIFF_NOTE_ERROR, e);
- },
- onUpdateNoteError(e) {
- this.onError(UPDATE_NOTE_ERROR, e);
- },
- onDesignDiscussionError(e) {
- this.onError(ADD_DISCUSSION_COMMENT_ERROR, e);
- },
- onUpdateImageDiffNoteError(e) {
- this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
- },
- onDesignDeleteError(e) {
- this.onError(designDeletionError({ singular: true }), e);
- },
- onResolveDiscussionError(e) {
- this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
- },
- openCommentForm(annotationCoordinates) {
- this.annotationCoordinates = annotationCoordinates;
- if (this.$refs.newDiscussionForm) {
- this.$refs.newDiscussionForm.focusInput();
- }
- },
- closeCommentForm() {
- this.comment = '';
- this.annotationCoordinates = null;
- },
- closeDesign() {
- this.$router.push({
- name: this.$options.DESIGNS_ROUTE_NAME,
- query: this.$route.query,
- });
- },
- trackEvent() {
- // TODO: This needs to be made aware of referers, or if it's rendered in a different context than a Issue
- trackDesignDetailView(
- 'issue-design-collection',
- 'issue',
- this.$route.query.version || this.latestVersionId,
- this.isLatestVersion,
- );
- },
- updateActiveDiscussion(id) {
- this.$apollo.mutate({
- mutation: updateActiveDiscussionMutation,
- variables: {
- id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.discussion,
- },
- });
- },
- toggleResolvedComments() {
- this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded;
- },
- },
- createImageDiffNoteMutation,
- DESIGNS_ROUTE_NAME,
-};
-</script>
-
-<template>
- <div
- class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row"
- >
- <gl-loading-icon v-if="isFirstLoading" size="xl" class="align-self-center" />
- <template v-else>
- <div class="d-flex overflow-hidden flex-grow-1 flex-column position-relative">
- <design-destroyer
- :filenames="[design.filename]"
- :project-path="projectPath"
- :iid="issueIid"
- @done="$router.push({ name: $options.DESIGNS_ROUTE_NAME })"
- @error="onDesignDeleteError"
- >
- <template #default="{ mutate, loading }">
- <toolbar
- :id="id"
- :is-deleting="loading"
- :is-latest-version="isLatestVersion"
- v-bind="design"
- @delete="mutate"
- />
- </template>
- </design-destroyer>
-
- <div v-if="errorMessage" class="p-3">
- <gl-alert variant="danger" @dismiss="errorMessage = null">
- {{ errorMessage }}
- </gl-alert>
- </div>
- <design-presentation
- :image="design.image"
- :image-name="design.filename"
- :discussions="discussions"
- :is-annotating="isAnnotating"
- :scale="scale"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- @openCommentForm="openCommentForm"
- @closeCommentForm="closeCommentForm"
- @moveNote="onMoveNote"
- />
-
- <div class="design-scaler-wrapper position-absolute mb-4 d-flex-center">
- <design-scaler @scale="scale = $event" />
- </div>
- </div>
- <design-sidebar
- :design="design"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- :markdown-preview-path="markdownPreviewPath"
- @onDesignDiscussionError="onDesignDiscussionError"
- @onCreateImageDiffNoteError="onCreateImageDiffNoteError"
- @updateNoteError="onUpdateNoteError"
- @resolveDiscussionError="onResolveDiscussionError"
- @toggleResolvedComments="toggleResolvedComments"
- >
- <template #replyForm>
- <apollo-mutation
- v-if="isAnnotating"
- #default="{ mutate, loading }"
- :mutation="$options.createImageDiffNoteMutation"
- :variables="{
- input: mutationPayload,
- }"
- :update="addImageDiffNoteToStore"
- @done="closeCommentForm"
- @error="onCreateImageDiffNoteError"
- >
- <design-reply-form
- ref="newDiscussionForm"
- v-model="comment"
- :is-saving="loading"
- :markdown-preview-path="markdownPreviewPath"
- @submitForm="mutate"
- @cancelForm="closeCommentForm"
- /> </apollo-mutation
- ></template>
- </design-sidebar>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/pages/index.vue b/app/assets/javascripts/design_management_legacy/pages/index.vue
deleted file mode 100644
index 66008a193ce..00000000000
--- a/app/assets/javascripts/design_management_legacy/pages/index.vue
+++ /dev/null
@@ -1,323 +0,0 @@
-<script>
-import { GlLoadingIcon, GlDeprecatedButton, GlAlert } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__, sprintf } from '~/locale';
-import UploadButton from '../components/upload/button.vue';
-import DeleteButton from '../components/delete_button.vue';
-import Design from '../components/list/item.vue';
-import DesignDestroyer from '../components/design_destroyer.vue';
-import DesignVersionDropdown from '../components/upload/design_version_dropdown.vue';
-import DesignDropzone from '../components/upload/design_dropzone.vue';
-import uploadDesignMutation from '../graphql/mutations/upload_design.mutation.graphql';
-import permissionsQuery from '../graphql/queries/design_permissions.query.graphql';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import allDesignsMixin from '../mixins/all_designs';
-import {
- UPLOAD_DESIGN_ERROR,
- EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
- EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
- designUploadSkippedWarning,
- designDeletionError,
-} from '../utils/error_messages';
-import { updateStoreAfterUploadDesign } from '../utils/cache_update';
-import {
- designUploadOptimisticResponse,
- isValidDesignFile,
-} from '../utils/design_management_utils';
-import { getFilename } from '~/lib/utils/file_upload';
-import { DESIGNS_ROUTE_NAME } from '../router/constants';
-
-const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
-
-export default {
- components: {
- GlLoadingIcon,
- GlAlert,
- GlDeprecatedButton,
- UploadButton,
- Design,
- DesignDestroyer,
- DesignVersionDropdown,
- DeleteButton,
- DesignDropzone,
- },
- mixins: [allDesignsMixin],
- apollo: {
- permissions: {
- query: permissionsQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- };
- },
- update: data => data.project.issue.userPermissions,
- },
- },
- data() {
- return {
- permissions: {
- createDesign: false,
- },
- filesToBeSaved: [],
- selectedDesigns: [],
- };
- },
- computed: {
- isLoading() {
- return this.$apollo.queries.designs.loading || this.$apollo.queries.permissions.loading;
- },
- isSaving() {
- return this.filesToBeSaved.length > 0;
- },
- canCreateDesign() {
- return this.permissions.createDesign;
- },
- showToolbar() {
- return this.canCreateDesign && this.allVersions.length > 0;
- },
- hasDesigns() {
- return this.designs.length > 0;
- },
- hasSelectedDesigns() {
- return this.selectedDesigns.length > 0;
- },
- canDeleteDesigns() {
- return this.isLatestVersion && this.hasSelectedDesigns;
- },
- projectQueryBody() {
- return {
- query: getDesignListQuery,
- variables: { fullPath: this.projectPath, iid: this.issueIid, atVersion: null },
- };
- },
- selectAllButtonText() {
- return this.hasSelectedDesigns
- ? s__('DesignManagement|Deselect all')
- : s__('DesignManagement|Select all');
- },
- },
- mounted() {
- this.toggleOnPasteListener(this.$route.name);
- },
- methods: {
- resetFilesToBeSaved() {
- this.filesToBeSaved = [];
- },
- /**
- * Determine if a design upload is valid, given [files]
- * @param {Array<File>} files
- */
- isValidDesignUpload(files) {
- if (!this.canCreateDesign) return false;
-
- if (files.length > MAXIMUM_FILE_UPLOAD_LIMIT) {
- createFlash(
- sprintf(
- s__(
- 'DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again.',
- ),
- {
- upload_limit: MAXIMUM_FILE_UPLOAD_LIMIT,
- },
- ),
- );
-
- return false;
- }
- return true;
- },
- onUploadDesign(files) {
- // convert to Array so that we have Array methods (.map, .some, etc.)
- this.filesToBeSaved = Array.from(files);
- if (!this.isValidDesignUpload(this.filesToBeSaved)) return null;
-
- const mutationPayload = {
- optimisticResponse: designUploadOptimisticResponse(this.filesToBeSaved),
- variables: {
- files: this.filesToBeSaved,
- projectPath: this.projectPath,
- iid: this.issueIid,
- },
- context: {
- hasUpload: true,
- },
- mutation: uploadDesignMutation,
- update: this.afterUploadDesign,
- };
-
- return this.$apollo
- .mutate(mutationPayload)
- .then(res => this.onUploadDesignDone(res))
- .catch(() => this.onUploadDesignError());
- },
- afterUploadDesign(
- store,
- {
- data: { designManagementUpload },
- },
- ) {
- updateStoreAfterUploadDesign(store, designManagementUpload, this.projectQueryBody);
- },
- onUploadDesignDone(res) {
- const skippedFiles = res?.data?.designManagementUpload?.skippedDesigns || [];
- const skippedWarningMessage = designUploadSkippedWarning(this.filesToBeSaved, skippedFiles);
- if (skippedWarningMessage) {
- createFlash(skippedWarningMessage, 'warning');
- }
-
- // if this upload resulted in a new version being created, redirect user to the latest version
- if (!this.isLatestVersion) {
- this.$router.push({ name: DESIGNS_ROUTE_NAME });
- }
- this.resetFilesToBeSaved();
- },
- onUploadDesignError() {
- this.resetFilesToBeSaved();
- createFlash(UPLOAD_DESIGN_ERROR);
- },
- changeSelectedDesigns(filename) {
- if (this.isDesignSelected(filename)) {
- this.selectedDesigns = this.selectedDesigns.filter(design => design !== filename);
- } else {
- this.selectedDesigns.push(filename);
- }
- },
- toggleDesignsSelection() {
- if (this.hasSelectedDesigns) {
- this.selectedDesigns = [];
- } else {
- this.selectedDesigns = this.designs.map(design => design.filename);
- }
- },
- isDesignSelected(filename) {
- return this.selectedDesigns.includes(filename);
- },
- isDesignToBeSaved(filename) {
- return this.filesToBeSaved.some(file => file.name === filename);
- },
- canSelectDesign(filename) {
- return this.isLatestVersion && this.canCreateDesign && !this.isDesignToBeSaved(filename);
- },
- onDesignDelete() {
- this.selectedDesigns = [];
- if (this.$route.query.version) this.$router.push({ name: DESIGNS_ROUTE_NAME });
- },
- onDesignDeleteError() {
- const errorMessage = designDeletionError({ singular: this.selectedDesigns.length === 1 });
- createFlash(errorMessage);
- },
- onExistingDesignDropzoneChange(files, existingDesignFilename) {
- const filesArr = Array.from(files);
-
- if (filesArr.length > 1) {
- createFlash(EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE);
- return;
- }
-
- if (!filesArr.some(({ name }) => existingDesignFilename === name)) {
- createFlash(EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE);
- return;
- }
-
- this.onUploadDesign(files);
- },
- onDesignPaste(event) {
- const { clipboardData } = event;
- const files = Array.from(clipboardData.files);
- if (clipboardData && files.length > 0) {
- if (!files.some(isValidDesignFile)) {
- return;
- }
- event.preventDefault();
- let filename = getFilename(event);
- if (!filename || filename === 'image.png') {
- filename = `design_${Date.now()}.png`;
- }
- const newFile = new File([files[0]], filename);
- this.onUploadDesign([newFile]);
- }
- },
- toggleOnPasteListener(route) {
- if (route === DESIGNS_ROUTE_NAME) {
- document.addEventListener('paste', this.onDesignPaste);
- } else {
- document.removeEventListener('paste', this.onDesignPaste);
- }
- },
- },
- beforeRouteUpdate(to, from, next) {
- this.toggleOnPasteListener(to.name);
- this.selectedDesigns = [];
- next();
- },
- beforeRouteLeave(to, from, next) {
- this.toggleOnPasteListener(to.name);
- next();
- },
-};
-</script>
-
-<template>
- <div>
- <header v-if="showToolbar" class="row-content-block border-top-0 p-2 d-flex">
- <div class="d-flex justify-content-between align-items-center w-100">
- <design-version-dropdown />
- <div :class="['qa-selector-toolbar', { 'd-flex': hasDesigns, 'd-none': !hasDesigns }]">
- <gl-deprecated-button
- v-if="isLatestVersion"
- variant="link"
- class="mr-2 js-select-all"
- @click="toggleDesignsSelection"
- >{{ selectAllButtonText }}</gl-deprecated-button
- >
- <design-destroyer
- #default="{ mutate, loading }"
- :filenames="selectedDesigns"
- :project-path="projectPath"
- :iid="issueIid"
- @done="onDesignDelete"
- @error="onDesignDeleteError"
- >
- <delete-button
- v-if="isLatestVersion"
- :is-deleting="loading"
- button-class="btn-danger btn-inverted mr-2"
- :has-selected-designs="hasSelectedDesigns"
- @deleteSelectedDesigns="mutate()"
- >
- {{ s__('DesignManagement|Delete selected') }}
- <gl-loading-icon v-if="loading" inline class="ml-1" />
- </delete-button>
- </design-destroyer>
- <upload-button v-if="canCreateDesign" :is-saving="isSaving" @upload="onUploadDesign" />
- </div>
- </div>
- </header>
- <div class="mt-4">
- <gl-loading-icon v-if="isLoading" size="md" />
- <gl-alert v-else-if="error" variant="danger" :dismissible="false">
- {{ __('An error occurred while loading designs. Please try again.') }}
- </gl-alert>
- <ol v-else class="list-unstyled row">
- <li class="col-md-6 col-lg-4 mb-3">
- <design-dropzone class="design-list-item" @change="onUploadDesign" />
- </li>
- <li v-for="design in designs" :key="design.id" class="col-md-6 col-lg-4 mb-3">
- <design-dropzone @change="onExistingDesignDropzoneChange($event, design.filename)"
- ><design v-bind="design" :is-uploading="isDesignToBeSaved(design.filename)"
- /></design-dropzone>
-
- <input
- v-if="canSelectDesign(design.filename)"
- :checked="isDesignSelected(design.filename)"
- type="checkbox"
- class="design-checkbox"
- @change="changeSelectedDesigns(design.filename)"
- />
- </li>
- </ol>
- </div>
- <router-view :key="$route.fullPath" />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/router/constants.js b/app/assets/javascripts/design_management_legacy/router/constants.js
deleted file mode 100644
index abeef520e33..00000000000
--- a/app/assets/javascripts/design_management_legacy/router/constants.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export const ROOT_ROUTE_NAME = 'root';
-export const DESIGNS_ROUTE_NAME = 'designs';
-export const DESIGN_ROUTE_NAME = 'design';
diff --git a/app/assets/javascripts/design_management_legacy/router/index.js b/app/assets/javascripts/design_management_legacy/router/index.js
deleted file mode 100644
index 28a81ed0278..00000000000
--- a/app/assets/javascripts/design_management_legacy/router/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'jquery';
-import Vue from 'vue';
-import VueRouter from 'vue-router';
-import routes from './routes';
-import { DESIGN_ROUTE_NAME } from './constants';
-import { getPageLayoutElement } from '~/design_management_legacy/utils/design_management_utils';
-import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '../constants';
-
-Vue.use(VueRouter);
-
-export default function createRouter(base) {
- const router = new VueRouter({
- base,
- mode: 'history',
- routes,
- });
- const pageEl = getPageLayoutElement();
-
- router.beforeEach(({ meta: { el }, name }, _, next) => {
- $(`#${el}`).tab('show');
-
- // apply a fullscreen layout style in Design View (a.k.a design detail)
- if (pageEl) {
- if (name === DESIGN_ROUTE_NAME) {
- pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- } else {
- pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- }
- }
-
- next();
- });
-
- return router;
-}
diff --git a/app/assets/javascripts/design_management_legacy/router/routes.js b/app/assets/javascripts/design_management_legacy/router/routes.js
deleted file mode 100644
index 788910e5514..00000000000
--- a/app/assets/javascripts/design_management_legacy/router/routes.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import Home from '../pages/index.vue';
-import DesignDetail from '../pages/design/index.vue';
-import { ROOT_ROUTE_NAME, DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from './constants';
-
-export default [
- {
- name: ROOT_ROUTE_NAME,
- path: '/',
- component: Home,
- meta: {
- el: 'discussion',
- },
- },
- {
- name: DESIGNS_ROUTE_NAME,
- path: '/designs',
- component: Home,
- meta: {
- el: 'designs',
- },
- children: [
- {
- name: DESIGN_ROUTE_NAME,
- path: ':id',
- component: DesignDetail,
- meta: {
- el: 'designs',
- },
- beforeEnter(
- {
- params: { id },
- },
- from,
- next,
- ) {
- if (typeof id === 'string') {
- next();
- }
- },
- props: ({ params: { id } }) => ({ id }),
- },
- ],
- },
-];
diff --git a/app/assets/javascripts/design_management_legacy/utils/cache_update.js b/app/assets/javascripts/design_management_legacy/utils/cache_update.js
deleted file mode 100644
index 5ba6f84c413..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/cache_update.js
+++ /dev/null
@@ -1,276 +0,0 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { extractCurrentDiscussion, extractDesign } from './design_management_utils';
-import {
- ADD_IMAGE_DIFF_NOTE_ERROR,
- UPDATE_IMAGE_DIFF_NOTE_ERROR,
- ADD_DISCUSSION_COMMENT_ERROR,
- designDeletionError,
-} from './error_messages';
-
-const deleteDesignsFromStore = (store, query, selectedDesigns) => {
- const data = store.readQuery(query);
-
- const changedDesigns = data.project.issue.designCollection.designs.edges.filter(
- ({ node }) => !selectedDesigns.includes(node.filename),
- );
- data.project.issue.designCollection.designs.edges = [...changedDesigns];
-
- store.writeQuery({
- ...query,
- data,
- });
-};
-
-/**
- * Adds a new version of designs to store
- *
- * @param {Object} store
- * @param {Object} query
- * @param {Object} version
- */
-const addNewVersionToStore = (store, query, version) => {
- if (!version) return;
-
- const data = store.readQuery(query);
- const newEdge = { node: version, __typename: 'DesignVersionEdge' };
-
- data.project.issue.designCollection.versions.edges = [
- newEdge,
- ...data.project.issue.designCollection.versions.edges,
- ];
-
- store.writeQuery({
- ...query,
- data,
- });
-};
-
-const addDiscussionCommentToStore = (store, createNote, query, queryVariables, discussionId) => {
- const data = store.readQuery({
- query,
- variables: queryVariables,
- });
-
- const design = extractDesign(data);
- const currentDiscussion = extractCurrentDiscussion(design.discussions, discussionId);
- currentDiscussion.notes.nodes = [...currentDiscussion.notes.nodes, createNote.note];
-
- design.notesCount += 1;
- if (
- !design.issue.participants.edges.some(
- participant => participant.node.username === createNote.note.author.username,
- )
- ) {
- design.issue.participants.edges = [
- ...design.issue.participants.edges,
- {
- __typename: 'UserEdge',
- node: {
- __typename: 'User',
- ...createNote.note.author,
- },
- },
- ];
- }
- store.writeQuery({
- query,
- variables: queryVariables,
- data: {
- ...data,
- design: {
- ...design,
- },
- },
- });
-};
-
-const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) => {
- const data = store.readQuery({
- query,
- variables,
- });
- const newDiscussion = {
- __typename: 'Discussion',
- id: createImageDiffNote.note.discussion.id,
- replyId: createImageDiffNote.note.discussion.replyId,
- resolvable: true,
- resolved: false,
- resolvedAt: null,
- resolvedBy: null,
- notes: {
- __typename: 'NoteConnection',
- nodes: [createImageDiffNote.note],
- },
- };
- const design = extractDesign(data);
- const notesCount = design.notesCount + 1;
- design.discussions.nodes = [...design.discussions.nodes, newDiscussion];
- if (
- !design.issue.participants.edges.some(
- participant => participant.node.username === createImageDiffNote.note.author.username,
- )
- ) {
- design.issue.participants.edges = [
- ...design.issue.participants.edges,
- {
- __typename: 'UserEdge',
- node: {
- __typename: 'User',
- ...createImageDiffNote.note.author,
- },
- },
- ];
- }
- store.writeQuery({
- query,
- variables,
- data: {
- ...data,
- design: {
- ...design,
- notesCount,
- },
- },
- });
-};
-
-const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables) => {
- const data = store.readQuery({
- query,
- variables,
- });
-
- const design = extractDesign(data);
- const discussion = extractCurrentDiscussion(
- design.discussions,
- updateImageDiffNote.note.discussion.id,
- );
-
- discussion.notes = {
- ...discussion.notes,
- nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
- };
-
- store.writeQuery({
- query,
- variables,
- data: {
- ...data,
- design,
- },
- });
-};
-
-const addNewDesignToStore = (store, designManagementUpload, query) => {
- const data = store.readQuery(query);
-
- const newDesigns = data.project.issue.designCollection.designs.edges.reduce((acc, design) => {
- if (!acc.find(d => d.filename === design.node.filename)) {
- acc.push(design.node);
- }
-
- return acc;
- }, designManagementUpload.designs);
-
- let newVersionNode;
- const findNewVersions = designManagementUpload.designs.find(design => design.versions);
-
- if (findNewVersions) {
- const findNewVersionsEdges = findNewVersions.versions.edges;
-
- if (findNewVersionsEdges && findNewVersionsEdges.length) {
- newVersionNode = [findNewVersionsEdges[0]];
- }
- }
-
- const newVersions = [
- ...(newVersionNode || []),
- ...data.project.issue.designCollection.versions.edges,
- ];
-
- const updatedDesigns = {
- __typename: 'DesignCollection',
- designs: {
- __typename: 'DesignConnection',
- edges: newDesigns.map(design => ({
- __typename: 'DesignEdge',
- node: design,
- })),
- },
- versions: {
- __typename: 'DesignVersionConnection',
- edges: newVersions,
- },
- };
-
- data.project.issue.designCollection = updatedDesigns;
-
- store.writeQuery({
- ...query,
- data,
- });
-};
-
-const onError = (data, message) => {
- createFlash(message);
- throw new Error(data.errors);
-};
-
-export const hasErrors = ({ errors = [] }) => errors?.length;
-
-/**
- * Updates a store after design deletion
- *
- * @param {Object} store
- * @param {Object} data
- * @param {Object} query
- * @param {Array} designs
- */
-export const updateStoreAfterDesignsDelete = (store, data, query, designs) => {
- if (hasErrors(data)) {
- onError(data, designDeletionError({ singular: designs.length === 1 }));
- } else {
- deleteDesignsFromStore(store, query, designs);
- addNewVersionToStore(store, query, data.version);
- }
-};
-
-export const updateStoreAfterAddDiscussionComment = (
- store,
- data,
- query,
- queryVariables,
- discussionId,
-) => {
- if (hasErrors(data)) {
- onError(data, ADD_DISCUSSION_COMMENT_ERROR);
- } else {
- addDiscussionCommentToStore(store, data, query, queryVariables, discussionId);
- }
-};
-
-export const updateStoreAfterAddImageDiffNote = (store, data, query, queryVariables) => {
- if (hasErrors(data)) {
- onError(data, ADD_IMAGE_DIFF_NOTE_ERROR);
- } else {
- addImageDiffNoteToStore(store, data, query, queryVariables);
- }
-};
-
-export const updateStoreAfterUpdateImageDiffNote = (store, data, query, queryVariables) => {
- if (hasErrors(data)) {
- onError(data, UPDATE_IMAGE_DIFF_NOTE_ERROR);
- } else {
- updateImageDiffNoteInStore(store, data, query, queryVariables);
- }
-};
-
-export const updateStoreAfterUploadDesign = (store, data, query) => {
- if (hasErrors(data)) {
- onError(data, data.errors[0]);
- } else {
- addNewDesignToStore(store, data, query);
- }
-};
diff --git a/app/assets/javascripts/design_management_legacy/utils/design_management_utils.js b/app/assets/javascripts/design_management_legacy/utils/design_management_utils.js
deleted file mode 100644
index 22705cf67a1..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/design_management_utils.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import { uniqueId } from 'lodash';
-import { VALID_DESIGN_FILE_MIMETYPE } from '../constants';
-
-export const isValidDesignFile = ({ type }) =>
- (type.match(VALID_DESIGN_FILE_MIMETYPE.regex) || []).length > 0;
-
-/**
- * Returns formatted array that doesn't contain
- * `edges`->`node` nesting
- *
- * @param {Array} elements
- */
-
-export const extractNodes = elements => elements.edges.map(({ node }) => node);
-
-/**
- * Returns formatted array of discussions that doesn't contain
- * `edges`->`node` nesting for child notes
- *
- * @param {Array} discussions
- */
-
-export const extractDiscussions = discussions =>
- discussions.nodes.map((discussion, index) => ({
- ...discussion,
- index: index + 1,
- notes: discussion.notes.nodes,
- }));
-
-/**
- * Returns a discussion with the given id from discussions array
- *
- * @param {Array} discussions
- */
-
-export const extractCurrentDiscussion = (discussions, id) =>
- discussions.nodes.find(discussion => discussion.id === id);
-
-export const findVersionId = id => (id.match('::Version/(.+$)') || [])[1];
-
-export const findNoteId = id => (id.match('DiffNote/(.+$)') || [])[1];
-
-export const extractDesigns = data => data.project.issue.designCollection.designs.edges;
-
-export const extractDesign = data => (extractDesigns(data) || [])[0]?.node;
-
-/**
- * Generates optimistic response for a design upload mutation
- * @param {Array<File>} files
- */
-export const designUploadOptimisticResponse = files => {
- const designs = files.map(file => ({
- // False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
- // eslint-disable-next-line @gitlab/require-i18n-strings
- __typename: 'Design',
- id: -uniqueId(),
- image: '',
- imageV432x230: '',
- filename: file.name,
- fullPath: '',
- notesCount: 0,
- event: 'NONE',
- diffRefs: {
- __typename: 'DiffRefs',
- baseSha: '',
- startSha: '',
- headSha: '',
- },
- discussions: {
- __typename: 'DesignDiscussion',
- nodes: [],
- },
- versions: {
- __typename: 'DesignVersionConnection',
- edges: {
- __typename: 'DesignVersionEdge',
- node: {
- __typename: 'DesignVersion',
- id: -uniqueId(),
- sha: -uniqueId(),
- },
- },
- },
- }));
-
- return {
- // False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
- // eslint-disable-next-line @gitlab/require-i18n-strings
- __typename: 'Mutation',
- designManagementUpload: {
- __typename: 'DesignManagementUploadPayload',
- designs,
- skippedDesigns: [],
- errors: [],
- },
- };
-};
-
-/**
- * Generates optimistic response for a design upload mutation
- * @param {Array<File>} files
- */
-export const updateImageDiffNoteOptimisticResponse = (note, { position }) => ({
- // False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/26
- // eslint-disable-next-line @gitlab/require-i18n-strings
- __typename: 'Mutation',
- updateImageDiffNote: {
- __typename: 'UpdateImageDiffNotePayload',
- note: {
- ...note,
- position: {
- ...note.position,
- ...position,
- },
- },
- errors: [],
- },
-});
-
-const normalizeAuthor = author => ({
- ...author,
- web_url: author.webUrl,
- avatar_url: author.avatarUrl,
-});
-
-export const extractParticipants = users => users.edges.map(({ node }) => normalizeAuthor(node));
-
-export const getPageLayoutElement = () => document.querySelector('.layout-page');
diff --git a/app/assets/javascripts/design_management_legacy/utils/error_messages.js b/app/assets/javascripts/design_management_legacy/utils/error_messages.js
deleted file mode 100644
index 7666c726c2f..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/error_messages.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import { __, s__, n__, sprintf } from '~/locale';
-
-export const ADD_DISCUSSION_COMMENT_ERROR = s__(
- 'DesignManagement|Could not add a new comment. Please try again.',
-);
-
-export const ADD_IMAGE_DIFF_NOTE_ERROR = s__(
- 'DesignManagement|Could not create new discussion. Please try again.',
-);
-
-export const UPDATE_IMAGE_DIFF_NOTE_ERROR = s__(
- 'DesignManagement|Could not update discussion. Please try again.',
-);
-
-export const UPDATE_NOTE_ERROR = s__('DesignManagement|Could not update note. Please try again.');
-
-export const UPLOAD_DESIGN_ERROR = s__(
- 'DesignManagement|Error uploading a new design. Please try again.',
-);
-
-export const UPLOAD_DESIGN_INVALID_FILETYPE_ERROR = __(
- 'Could not upload your designs as one or more files uploaded are not supported.',
-);
-
-export const DESIGN_NOT_FOUND_ERROR = __('Could not find design.');
-
-export const DESIGN_VERSION_NOT_EXIST_ERROR = __('Requested design version does not exist.');
-
-const DESIGN_UPLOAD_SKIPPED_MESSAGE = s__('DesignManagement|Upload skipped.');
-
-const ALL_DESIGNS_SKIPPED_MESSAGE = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
- 'The designs you tried uploading did not change.',
-)}`;
-
-export const EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE = __(
- 'You can only upload one design when dropping onto an existing design.',
-);
-
-export const EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE = __(
- 'You must upload a file with the same file name when dropping onto an existing design.',
-);
-
-const MAX_SKIPPED_FILES_LISTINGS = 5;
-
-const oneDesignSkippedMessage = filename =>
- `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${sprintf(s__('DesignManagement|%{filename} did not change.'), {
- filename,
- })}`;
-
-/**
- * Return warning message indicating that some (but not all) uploaded
- * files were skipped.
- * @param {Array<{ filename }>} skippedFiles
- */
-const someDesignsSkippedMessage = skippedFiles => {
- const designsSkippedMessage = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
- 'Some of the designs you tried uploading did not change:',
- )}`;
-
- const moreText = sprintf(s__(`DesignManagement|and %{moreCount} more.`), {
- moreCount: skippedFiles.length - MAX_SKIPPED_FILES_LISTINGS,
- });
-
- return `${designsSkippedMessage} ${skippedFiles
- .slice(0, MAX_SKIPPED_FILES_LISTINGS)
- .map(({ filename }) => filename)
- .join(', ')}${skippedFiles.length > MAX_SKIPPED_FILES_LISTINGS ? `, ${moreText}` : '.'}`;
-};
-
-export const designDeletionError = ({ singular = true } = {}) => {
- const design = singular ? __('a design') : __('designs');
- return sprintf(s__('Could not delete %{design}. Please try again.'), {
- design,
- });
-};
-
-/**
- * Return warning message, if applicable, that one, some or all uploaded
- * files were skipped.
- * @param {Array<{ filename }>} uploadedDesigns
- * @param {Array<{ filename }>} skippedFiles
- */
-export const designUploadSkippedWarning = (uploadedDesigns, skippedFiles) => {
- if (skippedFiles.length === 0) {
- return null;
- }
-
- if (skippedFiles.length === uploadedDesigns.length) {
- const { filename } = skippedFiles[0];
-
- return n__(oneDesignSkippedMessage(filename), ALL_DESIGNS_SKIPPED_MESSAGE, skippedFiles.length);
- }
-
- return someDesignsSkippedMessage(skippedFiles);
-};
diff --git a/app/assets/javascripts/design_management_legacy/utils/tracking.js b/app/assets/javascripts/design_management_legacy/utils/tracking.js
deleted file mode 100644
index b3ecc1453a6..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/tracking.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import Tracking from '~/tracking';
-
-// Tracking Constants
-const DESIGN_TRACKING_CONTEXT_SCHEMA = 'iglu:com.gitlab/design_management_context/jsonschema/1-0-0';
-const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
-const DESIGN_TRACKING_EVENT_NAME = 'view_design';
-
-// eslint-disable-next-line import/prefer-default-export
-export function trackDesignDetailView(
- referer = '',
- owner = '',
- designVersion = 1,
- latestVersion = false,
-) {
- Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENT_NAME, {
- label: DESIGN_TRACKING_EVENT_NAME,
- context: {
- schema: DESIGN_TRACKING_CONTEXT_SCHEMA,
- data: {
- 'design-version-number': designVersion,
- 'design-is-current-version': latestVersion,
- 'internal-object-referrer': referer,
- 'design-collection-owner': owner,
- },
- },
- });
-}