summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/design_management
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 07:08:36 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 07:08:36 +0000
commit48aff82709769b098321c738f3444b9bdaa694c6 (patch)
treee00c7c43e2d9b603a5a6af576b1685e400410dee /app/assets/javascripts/design_management
parent879f5329ee916a948223f8f43d77fba4da6cd028 (diff)
downloadgitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'app/assets/javascripts/design_management')
-rw-r--r--app/assets/javascripts/design_management/components/delete_button.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_note_pin.vue14
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_presentation.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_scaler.vue2
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue13
-rw-r--r--app/assets/javascripts/design_management/components/image.vue4
-rw-r--r--app/assets/javascripts/design_management/components/list/item.vue9
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/design_navigation.vue4
-rw-r--r--app/assets/javascripts/design_management/components/toolbar/index.vue8
-rw-r--r--app/assets/javascripts/design_management/components/upload/design_dropzone.vue10
-rw-r--r--app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql1
-rw-r--r--app/assets/javascripts/design_management/mixins/all_designs.js26
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue23
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue53
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js14
-rw-r--r--app/assets/javascripts/design_management/utils/design_management_utils.js4
-rw-r--r--app/assets/javascripts/design_management/utils/tracking.js28
18 files changed, 152 insertions, 71 deletions
diff --git a/app/assets/javascripts/design_management/components/delete_button.vue b/app/assets/javascripts/design_management/components/delete_button.vue
index 970197ef41b..273fa3f6be2 100644
--- a/app/assets/javascripts/design_management/components/delete_button.vue
+++ b/app/assets/javascripts/design_management/components/delete_button.vue
@@ -63,7 +63,7 @@ export default {
title: s__('DesignManagement|Are you sure you want to archive the selected designs?'),
actionPrimary: {
text: s__('DesignManagement|Archive designs'),
- attributes: { variant: 'warning' },
+ attributes: { variant: 'warning', 'data-qa-selector': 'confirm_archiving_button' },
},
actionCancel: {
text: __('Cancel'),
diff --git a/app/assets/javascripts/design_management/components/design_note_pin.vue b/app/assets/javascripts/design_management/components/design_note_pin.vue
index 2b5e62c2870..320e0654aab 100644
--- a/app/assets/javascripts/design_management/components/design_note_pin.vue
+++ b/app/assets/javascripts/design_management/components/design_note_pin.vue
@@ -17,19 +17,11 @@ export default {
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')
@@ -41,13 +33,13 @@ export default {
<template>
<button
- :style="pinStyle"
+ :style="position"
:aria-label="pinLabel"
:class="{
- 'btn-transparent comment-indicator': isNewNote,
+ 'btn-transparent comment-indicator gl-p-0': 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"
+ class="gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-font-lg gl-outline-0!"
type="button"
@mousedown="$emit('mousedown', $event)"
@mouseup="$emit('mouseup', $event)"
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index 5c4a3ab5f94..88f3ce0b8ea 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -266,7 +266,7 @@ export default {
type="button"
role="button"
:aria-label="$options.i18n.newCommentButtonLabel"
- class="gl-absolute gl-w-full gl-h-full gl-p-0 gl-top-0 gl-left-0 gl-outline-0! btn-transparent design-detail-overlay-add-comment"
+ class="gl-absolute gl-w-full gl-h-full gl-p-0 gl-top-0 gl-left-0 gl-outline-0! btn-transparent gl-hover-cursor-crosshair"
data-qa-selector="design_image_button"
@mouseup="onAddCommentMouseup"
></button>
@@ -276,7 +276,6 @@ export default {
v-if="resolvedDiscussionsExpanded || !note.resolved"
:key="note.id"
:label="note.index"
- :repositioning="isMovingNote(note.id)"
:position="
isMovingNote(note.id) && movingNoteNewPosition
? getNotePositionStyle(movingNoteNewPosition)
@@ -290,7 +289,6 @@ export default {
<design-note-pin
v-if="currentCommentForm"
:position="currentCommentPositionStyle"
- :repositioning="isMovingCurrentComment"
@mousedown.stop="onNoteMousedown"
@mouseup.stop="onNoteMouseup"
/>
diff --git a/app/assets/javascripts/design_management/components/design_presentation.vue b/app/assets/javascripts/design_management/components/design_presentation.vue
index 84dbb2809d9..c4d904e0d91 100644
--- a/app/assets/javascripts/design_management/components/design_presentation.vue
+++ b/app/assets/javascripts/design_management/components/design_presentation.vue
@@ -286,7 +286,7 @@ export default {
<template>
<div
ref="presentationViewport"
- class="h-100 w-100 p-3 overflow-auto position-relative"
+ class="gl-h-full gl-w-full gl-p-5 overflow-auto gl-relative"
:style="presentationStyle"
@mousedown="onPresentationMousedown"
@mousemove="onPresentationMousemove"
@@ -297,7 +297,7 @@ export default {
@touchend="onPresentationMouseup"
@touchcancel="onPresentationMouseup"
>
- <div class="h-100 w-100 d-flex align-items-center position-relative">
+ <div class="gl-h-full gl-w-full gl-display-flex gl-align-items-center gl-relative">
<design-image
v-if="image"
:image="image"
diff --git a/app/assets/javascripts/design_management/components/design_scaler.vue b/app/assets/javascripts/design_management/components/design_scaler.vue
index 55dee74bef5..8d26f84641e 100644
--- a/app/assets/javascripts/design_management/components/design_scaler.vue
+++ b/app/assets/javascripts/design_management/components/design_scaler.vue
@@ -51,7 +51,7 @@ export default {
<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 class="gl-display-flex gl-justify-content-center gl-align-items-center gl-icon s16">
</span>
</button>
diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue
index df425e3b96d..fb8e74c8c4c 100644
--- a/app/assets/javascripts/design_management/components/design_sidebar.vue
+++ b/app/assets/javascripts/design_management/components/design_sidebar.vue
@@ -71,14 +71,6 @@ export default {
resolvedCommentsToggleIcon() {
return this.resolvedDiscussionsExpanded ? 'chevron-down' : 'chevron-right';
},
- showTodoButton() {
- return this.glFeatures.designManagementTodoButton;
- },
- sidebarWrapperClass() {
- return {
- 'gl-pt-0': this.showTodoButton,
- };
- },
},
watch: {
isResolvedCommentsPopoverHidden(newVal) {
@@ -121,12 +113,11 @@ export default {
</script>
<template>
- <div class="image-notes" :class="sidebarWrapperClass" @click="handleSidebarClick">
+ <div class="image-notes gl-pt-0" @click="handleSidebarClick">
<div
- v-if="showTodoButton"
class="gl-py-4 gl-mb-4 gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
>
- <span>{{ __('To-Do') }}</span>
+ <span>{{ __('To Do') }}</span>
<design-todo-button :design="design" @error="$emit('todoError', $event)" />
</div>
<h2 class="gl-font-weight-bold gl-mt-0">
diff --git a/app/assets/javascripts/design_management/components/image.vue b/app/assets/javascripts/design_management/components/image.vue
index 91b7b576e0c..53062e6ebb0 100644
--- a/app/assets/javascripts/design_management/components/image.vue
+++ b/app/assets/javascripts/design_management/components/image.vue
@@ -93,8 +93,8 @@ export default {
</script>
<template>
- <div class="m-auto js-design-image">
- <gl-icon v-if="imageError" class="text-secondary-100" name="media-broken" :size="48" />
+ <div class="gl-mx-auto gl-my-auto js-design-image">
+ <gl-icon v-if="imageError" class="gl-text-gray-200" name="media-broken" :size="48" />
<img
v-show="!imageError"
ref="contentImg"
diff --git a/app/assets/javascripts/design_management/components/list/item.vue b/app/assets/javascripts/design_management/components/list/item.vue
index 36ea812d92e..fa09c7c15cc 100644
--- a/app/assets/javascripts/design_management/components/list/item.vue
+++ b/app/assets/javascripts/design_management/components/list/item.vue
@@ -132,7 +132,13 @@ export default {
>
<div v-if="icon.name" data-testid="designEvent" class="design-event gl-absolute">
<span :title="icon.tooltip" :aria-label="icon.tooltip">
- <gl-icon :name="icon.name" :size="18" :class="icon.classes" />
+ <gl-icon
+ :name="icon.name"
+ :size="18"
+ :class="icon.classes"
+ data-qa-selector="design_status_icon"
+ :data-qa-status="icon.name"
+ />
</span>
</div>
<gl-intersection-observer @appear="onAppear">
@@ -149,6 +155,7 @@ export default {
:alt="filename"
class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
data-qa-selector="design_image"
+ :data-qa-filename="filename"
@load="onImageLoad"
@error="onImageError"
/>
diff --git a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
index afca8ed2c6f..2719d701c12 100644
--- a/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/design_navigation.vue
@@ -64,9 +64,9 @@ export default {
</script>
<template>
- <div v-if="designsCount" class="d-flex align-items-center">
+ <div v-if="designsCount" class="gl-display-flex gl-align-items-center">
{{ paginationText }}
- <gl-button-group class="ml-3 mr-3">
+ <gl-button-group class="gl-mx-5">
<gl-button
:disabled="!previousDesign"
:title="s__('DesignManagement|Go to previous design')"
diff --git a/app/assets/javascripts/design_management/components/toolbar/index.vue b/app/assets/javascripts/design_management/components/toolbar/index.vue
index a1cb57123ab..8d25d467d59 100644
--- a/app/assets/javascripts/design_management/components/toolbar/index.vue
+++ b/app/assets/javascripts/design_management/components/toolbar/index.vue
@@ -106,12 +106,12 @@ export default {
>
<gl-icon 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 class="gl-overflow-hidden gl-display-flex gl-align-items-center">
+ <h2 class="gl-m-0 str-truncated-100 gl-font-base">{{ filename }}</h2>
+ <small v-if="updatedAt" class="gl-text-gray-500">{{ updatedText }}</small>
</div>
</div>
- <design-navigation :id="id" class="ml-auto flex-shrink-0" />
+ <design-navigation :id="id" class="gl-ml-auto gl-flex-shrink-0" />
<gl-button :href="image" icon="download" />
<delete-button
v-if="isLatestVersion && canDeleteDesign"
diff --git a/app/assets/javascripts/design_management/components/upload/design_dropzone.vue b/app/assets/javascripts/design_management/components/upload/design_dropzone.vue
index 7254b7cd16a..6694b0dab8d 100644
--- a/app/assets/javascripts/design_management/components/upload/design_dropzone.vue
+++ b/app/assets/javascripts/design_management/components/upload/design_dropzone.vue
@@ -83,7 +83,7 @@ export default {
<template>
<div
- class="w-100 position-relative"
+ class="gl-w-full gl-relative"
@dragstart.prevent.stop
@dragend.prevent.stop
@dragover.prevent.stop
@@ -93,7 +93,7 @@ export default {
>
<slot>
<button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 gl-align-items-center gl-justify-content-center gl-p-3"
+ class="card design-dropzone-card design-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
@click="openFileUpload"
>
<div
@@ -127,9 +127,9 @@ export default {
<transition name="design-dropzone-fade">
<div
v-show="dragging && !isDraggingDesign"
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
+ class="card design-dropzone-border design-dropzone-overlay gl-w-full gl-h-full gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-3 gl-bg-white"
>
- <div v-show="!isDragDataValid" class="mw-50 text-center">
+ <div v-show="!isDragDataValid" class="mw-50 gl-text-center">
<h3 :class="{ 'gl-font-base gl-display-inline': !hasDesigns }">{{ __('Oh no!') }}</h3>
<span>{{
__(
@@ -137,7 +137,7 @@ export default {
)
}}</span>
</div>
- <div v-show="isDragDataValid" class="mw-50 text-center">
+ <div v-show="isDragDataValid" class="mw-50 gl-text-center">
<h3 :class="{ 'gl-font-base gl-display-inline': !hasDesigns }">{{ __('Incoming!') }}</h3>
<span>{{ __('Drop your designs to start your upload.') }}</span>
</div>
diff --git a/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql b/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql
index 96efa8e8242..efa61edf51a 100644
--- a/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql
+++ b/app/assets/javascripts/design_management/graphql/queries/get_design_list.query.graphql
@@ -6,6 +6,7 @@ query getDesignList($fullPath: ID!, $iid: String!, $atVersion: ID) {
id
issue(iid: $iid) {
designCollection {
+ copyState
designs(atVersion: $atVersion) {
nodes {
...DesignListItem
diff --git a/app/assets/javascripts/design_management/mixins/all_designs.js b/app/assets/javascripts/design_management/mixins/all_designs.js
index 0c2858bb14b..62bcf216add 100644
--- a/app/assets/javascripts/design_management/mixins/all_designs.js
+++ b/app/assets/javascripts/design_management/mixins/all_designs.js
@@ -8,7 +8,7 @@ import { DESIGNS_ROUTE_NAME } from '../router/constants';
export default {
mixins: [allVersionsMixin],
apollo: {
- designs: {
+ designCollection: {
query: getDesignListQuery,
variables() {
return {
@@ -25,10 +25,11 @@ export default {
'designs',
'nodes',
]);
- if (designNodes) {
- return designNodes;
- }
- return [];
+ const copyState = propertyOf(data)(['project', 'issue', 'designCollection', 'copyState']);
+ return {
+ designs: designNodes,
+ copyState,
+ };
},
error() {
this.error = true;
@@ -42,13 +43,26 @@ export default {
);
this.$router.replace({ name: DESIGNS_ROUTE_NAME, query: { version: undefined } });
}
+ if (this.designCollection.copyState === 'ERROR') {
+ createFlash(
+ s__(
+ 'DesignManagement|There was an error moving your designs. Please upload your designs below.',
+ ),
+ 'warning',
+ );
+ }
},
},
},
data() {
return {
- designs: [],
+ designCollection: null,
error: false,
};
},
+ computed: {
+ designs() {
+ return this.designCollection?.designs || [];
+ },
+ },
};
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index c6225c516e2..6a96b06dcd8 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -40,6 +40,8 @@ import { trackDesignDetailView } from '../../utils/tracking';
import { DESIGNS_ROUTE_NAME } from '../../router/constants';
import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
+const DEFAULT_SCALE = 1;
+
export default {
components: {
ApolloMutation,
@@ -65,7 +67,7 @@ export default {
comment: '',
annotationCoordinates: null,
errorMessage: '',
- scale: 1,
+ scale: DEFAULT_SCALE,
resolvedDiscussionsExpanded: false,
};
},
@@ -157,6 +159,11 @@ export default {
beforeDestroy() {
Mousetrap.unbind('esc', this.closeDesign);
},
+ beforeRouteUpdate(to, from, next) {
+ // reset scale when the active design changes
+ this.scale = DEFAULT_SCALE;
+ next();
+ },
methods: {
addImageDiffNoteToStore(
store,
@@ -300,11 +307,13 @@ export default {
<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"
+ class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row"
>
- <gl-loading-icon v-if="isFirstLoading" size="xl" class="align-self-center" />
+ <gl-loading-icon v-if="isFirstLoading" size="xl" class="gl-align-self-center" />
<template v-else>
- <div class="d-flex overflow-hidden flex-grow-1 flex-column position-relative">
+ <div
+ class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative"
+ >
<design-destroyer
:filenames="[design.filename]"
:project-path="projectPath"
@@ -323,7 +332,7 @@ export default {
</template>
</design-destroyer>
- <div v-if="errorMessage" class="p-3">
+ <div v-if="errorMessage" class="gl-p-5">
<gl-alert variant="danger" @dismiss="errorMessage = null">
{{ errorMessage }}
</gl-alert>
@@ -340,7 +349,9 @@ export default {
@moveNote="onMoveNote"
/>
- <div class="design-scaler-wrapper position-absolute mb-4 d-flex-center">
+ <div
+ class="design-scaler-wrapper gl-absolute gl-mb-6 gl-display-flex gl-justify-content-center gl-align-items-center"
+ >
<design-scaler @scale="scale = $event" />
</div>
</div>
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index 6c4c8c75054..6e71dca41e9 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -3,6 +3,7 @@ import { GlLoadingIcon, GlButton, GlAlert } from '@gitlab/ui';
import VueDraggable from 'vuedraggable';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
+import { getFilename } from '~/lib/utils/file_upload';
import UploadButton from '../components/upload/button.vue';
import DeleteButton from '../components/delete_button.vue';
import Design from '../components/list/item.vue';
@@ -31,7 +32,7 @@ import {
isValidDesignFile,
moveDesignOptimisticResponse,
} from '../utils/design_management_utils';
-import { getFilename } from '~/lib/utils/file_upload';
+import { trackDesignCreate, trackDesignUpdate } from '../utils/tracking';
import { DESIGNS_ROUTE_NAME } from '../router/constants';
const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
@@ -71,11 +72,14 @@ export default {
selectedDesigns: [],
isDraggingDesign: false,
reorderedDesigns: null,
+ isReorderingInProgress: false,
};
},
computed: {
isLoading() {
- return this.$apollo.queries.designs.loading || this.$apollo.queries.permissions.loading;
+ return (
+ this.$apollo.queries.designCollection.loading || this.$apollo.queries.permissions.loading
+ );
},
isSaving() {
return this.filesToBeSaved.length > 0;
@@ -109,6 +113,9 @@ export default {
isDesignListEmpty() {
return !this.isSaving && !this.hasDesigns;
},
+ isDesignCollectionCopying() {
+ return this.designCollection && this.designCollection.copyState === 'IN_PROGRESS';
+ },
designDropzoneWrapperClass() {
return this.isDesignListEmpty
? 'col-12'
@@ -180,6 +187,7 @@ export default {
updateStoreAfterUploadDesign(store, designManagementUpload, this.projectQueryBody);
},
onUploadDesignDone(res) {
+ // display any warnings, if necessary
const skippedFiles = res?.data?.designManagementUpload?.skippedDesigns || [];
const skippedWarningMessage = designUploadSkippedWarning(this.filesToBeSaved, skippedFiles);
if (skippedWarningMessage) {
@@ -190,7 +198,19 @@ export default {
if (!this.isLatestVersion) {
this.$router.push({ name: DESIGNS_ROUTE_NAME });
}
+
+ // reset state
this.resetFilesToBeSaved();
+ this.trackUploadDesign(res);
+ },
+ trackUploadDesign(res) {
+ (res?.data?.designManagementUpload?.designs || []).forEach(design => {
+ if (design.event === 'CREATION') {
+ trackDesignCreate();
+ } else if (design.event === 'MODIFICATION') {
+ trackDesignUpdate();
+ }
+ });
},
onUploadDesignError() {
this.resetFilesToBeSaved();
@@ -277,6 +297,7 @@ export default {
return variables;
},
reorderDesigns({ moved: { newIndex, element } }) {
+ this.isReorderingInProgress = true;
this.$apollo
.mutate({
mutation: moveDesignMutation,
@@ -287,6 +308,9 @@ export default {
})
.catch(() => {
createFlash(MOVE_DESIGN_ERROR);
+ })
+ .finally(() => {
+ this.isReorderingInProgress = false;
});
},
onDesignMove(designs) {
@@ -311,7 +335,7 @@ export default {
@mouseenter="toggleOnPasteListener"
@mouseleave="toggleOffPasteListener"
>
- <header v-if="showToolbar" class="row-content-block border-top-0 p-2 d-flex">
+ <header v-if="showToolbar" class="row-content-block gl-border-t-0 gl-p-3 gl-display-flex">
<div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full">
<div>
<span class="gl-font-weight-bold gl-mr-3">{{ s__('DesignManagement|Designs') }}</span>
@@ -339,6 +363,7 @@ export default {
button-category="secondary"
button-class="gl-mr-3"
button-size="small"
+ data-qa-selector="archive_button"
:loading="loading"
:has-selected-designs="hasSelectedDesigns"
@deleteSelectedDesigns="mutate()"
@@ -350,15 +375,30 @@ export default {
</div>
</div>
</header>
- <div class="mt-4">
+ <div class="gl-mt-6">
<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>
+ <header
+ v-else-if="isDesignCollectionCopying"
+ class="card"
+ data-testid="design-collection-is-copying"
+ >
+ <div class="card-header design-card-header gl-border-b-0">
+ <div class="card-title gl-display-flex gl-align-items-center gl-my-0 gl-h-7">
+ {{
+ s__(
+ 'DesignManagement|Your designs are being copied and are on their way… Please refresh to update.',
+ )
+ }}
+ </div>
+ </div>
+ </header>
<vue-draggable
v-else
:value="designs"
- :disabled="!isLatestVersion"
+ :disabled="!isLatestVersion || isReorderingInProgress"
v-bind="$options.dragOptions"
tag="ol"
draggable=".js-design-tile"
@@ -390,6 +430,8 @@ export default {
:checked="isDesignSelected(design.filename)"
type="checkbox"
class="design-checkbox"
+ data-qa-selector="design_checkbox"
+ :data-qa-design="design.filename"
@change="changeSelectedDesigns(design.filename)"
/>
</li>
@@ -399,6 +441,7 @@ export default {
:is-dragging-design="isDraggingDesign"
:class="{ 'design-list-item design-list-item-new': !isDesignListEmpty }"
:has-designs="hasDesigns"
+ data-qa-selector="design_dropzone_content"
@change="onUploadDesign"
/>
</li>
diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index ff41136fd54..fc0530ff977 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -1,6 +1,6 @@
/* eslint-disable @gitlab/require-i18n-strings */
-import { groupBy } from 'lodash';
+import { differenceBy } from 'lodash';
import produce from 'immer';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { extractCurrentDiscussion, extractDesign, extractDesigns } from './design_management_utils';
@@ -132,10 +132,13 @@ const addNewDesignToStore = (store, designManagementUpload, query) => {
const data = produce(sourceData, draftData => {
const currentDesigns = extractDesigns(draftData);
- const existingDesigns = groupBy(currentDesigns, 'filename');
- const newDesigns = currentDesigns.concat(
- designManagementUpload.designs.filter(d => !existingDesigns[d.filename]),
- );
+ const difference = differenceBy(designManagementUpload.designs, currentDesigns, 'filename');
+
+ const newDesigns = currentDesigns
+ .map(design => {
+ return designManagementUpload.designs.find(d => d.filename === design.filename) || design;
+ })
+ .concat(difference);
let newVersionNode;
const findNewVersions = designManagementUpload.designs.find(design => design.versions);
@@ -155,6 +158,7 @@ const addNewDesignToStore = (store, designManagementUpload, query) => {
const updatedDesigns = {
__typename: 'DesignCollection',
+ copyState: 'READY',
designs: {
__typename: 'DesignConnection',
nodes: newDesigns,
diff --git a/app/assets/javascripts/design_management/utils/design_management_utils.js b/app/assets/javascripts/design_management/utils/design_management_utils.js
index 93e4d6060c3..687e793d3df 100644
--- a/app/assets/javascripts/design_management/utils/design_management_utils.js
+++ b/app/assets/javascripts/design_management/utils/design_management_utils.js
@@ -65,6 +65,10 @@ export const designUploadOptimisticResponse = files => {
fullPath: '',
notesCount: 0,
event: 'NONE',
+ currentUserTodos: {
+ __typename: 'TodoConnection',
+ nodes: [],
+ },
diffRefs: {
__typename: 'DiffRefs',
baseSha: '',
diff --git a/app/assets/javascripts/design_management/utils/tracking.js b/app/assets/javascripts/design_management/utils/tracking.js
index 49fa306914c..4a39268c38b 100644
--- a/app/assets/javascripts/design_management/utils/tracking.js
+++ b/app/assets/javascripts/design_management/utils/tracking.js
@@ -1,9 +1,16 @@
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';
+const DESIGN_TRACKING_CONTEXT_SCHEMAS = {
+ VIEW_DESIGN_SCHEMA: 'iglu:com.gitlab/design_management_context/jsonschema/1-0-0',
+};
+const DESIGN_TRACKING_EVENTS = {
+ VIEW_DESIGN: 'view_design',
+ CREATE_DESIGN: 'create_design',
+ UPDATE_DESIGN: 'update_design',
+};
+
+export const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
export function trackDesignDetailView(
referer = '',
@@ -11,10 +18,11 @@ export function trackDesignDetailView(
designVersion = 1,
latestVersion = false,
) {
- Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENT_NAME, {
- label: DESIGN_TRACKING_EVENT_NAME,
+ const eventName = DESIGN_TRACKING_EVENTS.VIEW_DESIGN;
+ Tracking.event(DESIGN_TRACKING_PAGE_NAME, eventName, {
+ label: eventName,
context: {
- schema: DESIGN_TRACKING_CONTEXT_SCHEMA,
+ schema: DESIGN_TRACKING_CONTEXT_SCHEMAS.VIEW_DESIGN_SCHEMA,
data: {
'design-version-number': designVersion,
'design-is-current-version': latestVersion,
@@ -24,3 +32,11 @@ export function trackDesignDetailView(
},
});
}
+
+export function trackDesignCreate() {
+ return Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENTS.CREATE_DESIGN);
+}
+
+export function trackDesignUpdate() {
+ return Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENTS.UPDATE_DESIGN);
+}