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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-13 18:10:03 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-13 18:10:03 +0300
commit6df7943512ca90323c69b926404cc561b6305ce2 (patch)
tree5dbdb697f641358516ddae9b45ab8bae5d58de81 /app/assets/javascripts/design_management/pages
parent5605efec12c99adf88f641391cb879dedf8fa05e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/design_management/pages')
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue98
1 files changed, 85 insertions, 13 deletions
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index e35d1a8c419..6e130b7c741 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -2,6 +2,7 @@
import { GlLoadingIcon, GlButton, GlAlert } from '@gitlab/ui';
import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
+import VueDraggable from 'vuedraggable';
import UploadButton from '../components/upload/button.vue';
import DeleteButton from '../components/delete_button.vue';
import Design from '../components/list/item.vue';
@@ -9,6 +10,7 @@ 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 moveDesignMutation from '../graphql/mutations/move_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';
@@ -16,13 +18,18 @@ import {
UPLOAD_DESIGN_ERROR,
EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
+ MOVE_DESIGN_ERROR,
designUploadSkippedWarning,
designDeletionError,
} from '../utils/error_messages';
-import { updateStoreAfterUploadDesign } from '../utils/cache_update';
+import {
+ updateStoreAfterUploadDesign,
+ updateDesignsOnStoreAfterReorder,
+} from '../utils/cache_update';
import {
designUploadOptimisticResponse,
isValidDesignFile,
+ moveDesignOptimisticResponse,
} from '../utils/design_management_utils';
import { getFilename } from '~/lib/utils/file_upload';
import { DESIGNS_ROUTE_NAME } from '../router/constants';
@@ -40,6 +47,7 @@ export default {
DesignVersionDropdown,
DeleteButton,
DesignDropzone,
+ VueDraggable,
},
mixins: [allDesignsMixin],
apollo: {
@@ -61,6 +69,8 @@ export default {
},
filesToBeSaved: [],
selectedDesigns: [],
+ isDraggingDesign: false,
+ reorderedDesigns: null,
};
},
computed: {
@@ -254,11 +264,48 @@ export default {
toggleOffPasteListener() {
document.removeEventListener('paste', this.onDesignPaste);
},
+ designMoveVariables(newIndex, element) {
+ const variables = {
+ id: element.id,
+ };
+ if (newIndex > 0) {
+ variables.previous = this.reorderedDesigns[newIndex - 1].id;
+ }
+ if (newIndex < this.reorderedDesigns.length - 1) {
+ variables.next = this.reorderedDesigns[newIndex + 1].id;
+ }
+ return variables;
+ },
+ reorderDesigns({ moved: { newIndex, element } }) {
+ this.$apollo
+ .mutate({
+ mutation: moveDesignMutation,
+ variables: this.designMoveVariables(newIndex, element),
+ update: (store, { data: { designManagementMove } }) => {
+ return updateDesignsOnStoreAfterReorder(
+ store,
+ designManagementMove,
+ this.projectQueryBody,
+ );
+ },
+ optimisticResponse: moveDesignOptimisticResponse(this.reorderedDesigns),
+ })
+ .catch(() => {
+ createFlash(MOVE_DESIGN_ERROR);
+ });
+ },
+ onDesignMove(designs) {
+ this.reorderedDesigns = designs;
+ },
},
beforeRouteUpdate(to, from, next) {
this.selectedDesigns = [];
next();
},
+ dragOptions: {
+ animation: 200,
+ ghostClass: 'gl-visibility-hidden',
+ },
};
</script>
@@ -312,20 +359,35 @@ export default {
<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="designDropzoneWrapperClass" data-testid="design-dropzone-wrapper">
- <design-dropzone
- :class="{ 'design-list-item design-list-item-new': !isDesignListEmpty }"
- :has-designs="hasDesigns"
- @change="onUploadDesign"
- />
- </li>
- <li v-for="design in designs" :key="design.id" class="col-md-6 col-lg-3 gl-mb-3">
+ <vue-draggable
+ v-else
+ :value="designs"
+ :disabled="!isLatestVersion"
+ v-bind="$options.dragOptions"
+ tag="ol"
+ draggable=".js-design-tile"
+ class="list-unstyled row"
+ @start="isDraggingDesign = true"
+ @end="isDraggingDesign = false"
+ @change="reorderDesigns"
+ @input="onDesignMove"
+ >
+ <li
+ v-for="design in designs"
+ :key="design.id"
+ class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
+ >
<design-dropzone
:has-designs="hasDesigns"
+ :is-dragging-design="isDraggingDesign"
@change="onExistingDesignDropzoneChange($event, design.filename)"
- ><design v-bind="design" :is-uploading="isDesignToBeSaved(design.filename)"
- /></design-dropzone>
+ >
+ <design
+ v-bind="design"
+ :is-uploading="isDesignToBeSaved(design.filename)"
+ class="gl-bg-white"
+ />
+ </design-dropzone>
<input
v-if="canSelectDesign(design.filename)"
@@ -335,7 +397,17 @@ export default {
@change="changeSelectedDesigns(design.filename)"
/>
</li>
- </ol>
+ <template #header>
+ <li :class="designDropzoneWrapperClass" data-testid="design-dropzone-wrapper">
+ <design-dropzone
+ :is-dragging-design="isDraggingDesign"
+ :class="{ 'design-list-item design-list-item-new': !isDesignListEmpty }"
+ :has-designs="hasDesigns"
+ @change="onUploadDesign"
+ />
+ </li>
+ </template>
+ </vue-draggable>
</div>
<router-view :key="$route.fullPath" />
</div>