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>2021-08-30 12:09:12 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-08-30 12:09:12 +0300
commit4ac9f1b8eaef29daa484b27a3113505cfa6a6dcb (patch)
treebda090fb8cf7c97765ee891bd58f7f9ee4271301 /app/assets/javascripts
parentabbedc2027e64b11b03be4639411f1943b81f7ce (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/javascripts/main_jh.js1
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue40
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue189
9 files changed, 96 insertions, 183 deletions
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 1aaefcaa13b..abd13a30156 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -37,6 +37,7 @@ import initBroadcastNotifications from './broadcast_notification';
import { initTopNav } from './nav';
import 'ee_else_ce/main_ee';
+import 'jh_else_ce/main_jh';
applyGitLabUIConfig();
diff --git a/app/assets/javascripts/main_jh.js b/app/assets/javascripts/main_jh.js
new file mode 100644
index 00000000000..13a6b8f3d3d
--- /dev/null
+++ b/app/assets/javascripts/main_jh.js
@@ -0,0 +1 @@
+// This is an empty file to satisfy jh_else_ce import for the JH main entry point
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 031472a7d20..831f3987041 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -258,6 +258,7 @@ export function mountSidebarLabels() {
allowScopedLabels: parseBoolean(el.dataset.allowScopedLabels),
initiallySelectedLabels: JSON.parse(el.dataset.selectedLabels),
variant: DropdownVariant.Sidebar,
+ canUpdate: parseBoolean(el.dataset.canEdit),
},
render: (createElement) => createElement(SidebarLabels),
});
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
index 6694e349b6e..b5c3ffabae0 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
@@ -60,7 +60,7 @@ export default {
},
},
methods: {
- ...mapActions(['toggleDropdownContentsCreateView', 'toggleDropdownContents']),
+ ...mapActions(['toggleDropdownContentsCreateView']),
},
};
</script>
@@ -83,7 +83,7 @@ export default {
size="small"
class="js-btn-back dropdown-header-button p-0"
icon="arrow-left"
- @click="toggleDropdownContentsCreateView"
+ @click.stop="toggleDropdownContentsCreateView"
/>
<span class="flex-grow-1">{{ dropdownTitle }}</span>
<gl-button
@@ -92,7 +92,7 @@ export default {
size="small"
class="dropdown-header-button gl-p-0!"
icon="close"
- @click="toggleDropdownContents"
+ @click="$emit('closeDropdown')"
/>
</div>
<component
@@ -103,7 +103,7 @@ export default {
:footer-create-label-title="footerCreateLabelTitle"
:footer-manage-label-title="footerManageLabelTitle"
@hideCreateView="toggleDropdownContentsCreateView"
- @closeDropdown="$emit('closeDropdown', $event)"
+ @setLabels="$emit('setLabels', $event)"
@toggleDropdownContentsCreateView="toggleDropdownContentsCreateView"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
index 4651e7a1576..2e31b386fdd 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue
@@ -1,8 +1,10 @@
<script>
import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import produce from 'immer';
import createFlash from '~/flash';
import { __ } from '~/locale';
import createLabelMutation from './graphql/create_label.mutation.graphql';
+import projectLabelsQuery from './graphql/project_labels.query.graphql';
const errorMessage = __('Error creating label.');
@@ -47,6 +49,25 @@ export default {
handleColorClick(color) {
this.selectedColor = this.getColorCode(color);
},
+ updateLabelsInCache(store, label) {
+ const sourceData = store.readQuery({
+ query: projectLabelsQuery,
+ variables: { fullPath: this.projectPath, searchTerm: '' },
+ });
+
+ const collator = new Intl.Collator('en');
+ const data = produce(sourceData, (draftData) => {
+ const { nodes } = draftData.workspace.labels;
+ nodes.push(label);
+ nodes.sort((a, b) => collator.compare(a.title, b.title));
+ });
+
+ store.writeQuery({
+ query: projectLabelsQuery,
+ variables: { fullPath: this.projectPath, searchTerm: '' },
+ data,
+ });
+ },
async createLabel() {
this.labelCreateInProgress = true;
try {
@@ -59,6 +80,14 @@ export default {
color: this.selectedColor,
projectPath: this.projectPath,
},
+ update: (
+ store,
+ {
+ data: {
+ labelCreate: { label },
+ },
+ },
+ ) => this.updateLabelsInCache(store, label),
});
if (labelCreate.errors.length) {
createFlash({ message: errorMessage });
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
index ffa37424c2c..224dbd3e29b 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue
@@ -112,7 +112,7 @@ export default {
this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
},
beforeDestroy() {
- this.$emit('closeDropdown', this.localSelectedLabels);
+ this.$emit('setLabels', this.localSelectedLabels);
this.debouncedSearchKeyUpdate.cancel();
},
methods: {
@@ -166,7 +166,7 @@ export default {
this.updateSelectedLabels(this.visibleLabels[this.currentHighlightItem]);
this.searchKey = '';
} else if (e.keyCode === ESC_KEY_CODE) {
- this.$emit('closeDropdown', this.localSelectedLabels);
+ this.$emit('setLabels', this.localSelectedLabels);
}
if (e.keyCode !== ESC_KEY_CODE) {
@@ -180,7 +180,7 @@ export default {
handleLabelClick(label) {
this.updateSelectedLabels(label);
if (!this.allowMultiselect) {
- this.$emit('closeDropdown', this.localSelectedLabels);
+ this.$emit('setLabels', this.localSelectedLabels);
}
},
setSearchKey(value) {
@@ -240,7 +240,7 @@ export default {
<gl-link
class="gl-display-flex gl-flex-direction-row gl-w-full gl-overflow-break-word label-item"
data-testid="create-label-button"
- @click="$emit('toggleDropdownContentsCreateView')"
+ @click.stop="$emit('toggleDropdownContentsCreateView')"
>
{{ footerCreateLabelTitle }}
</gl-link>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue
deleted file mode 100644
index 46edfa1c42a..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_title.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-<script>
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
-import { mapState, mapActions } from 'vuex';
-
-export default {
- components: {
- GlButton,
- GlLoadingIcon,
- },
- props: {
- labelsSelectInProgress: {
- type: Boolean,
- required: true,
- },
- },
- computed: {
- ...mapState(['allowLabelEdit', 'labelsFetchInProgress']),
- },
- methods: {
- ...mapActions(['toggleDropdownContents']),
- },
-};
-</script>
-
-<template>
- <div class="title hide-collapsed gl-mb-3">
- {{ __('Labels') }}
- <template v-if="allowLabelEdit">
- <gl-loading-icon v-show="labelsSelectInProgress" size="sm" inline />
- <gl-button
- category="tertiary"
- size="small"
- class="float-right js-sidebar-dropdown-toggle gl-mr-n2"
- data-qa-selector="labels_edit_button"
- @click="toggleDropdownContents"
- >{{ __('Edit') }}</gl-button
- >
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql
index 9aa4f5d165e..eb478645a03 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql
@@ -6,9 +6,7 @@ mutation createLabel($title: String!, $color: String, $projectPath: ID, $groupPa
id
color
description
- descriptionHtml
title
- textColor
}
errors
}
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
index 0499dfe468f..efe524996b2 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
@@ -1,14 +1,12 @@
<script>
-import $ from 'jquery';
import Vue from 'vue';
import Vuex, { mapState, mapActions, mapGetters } from 'vuex';
import { isInViewport } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
-
+import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { DropdownVariant } from './constants';
import DropdownButton from './dropdown_button.vue';
import DropdownContents from './dropdown_contents.vue';
-import DropdownTitle from './dropdown_title.vue';
import DropdownValue from './dropdown_value.vue';
import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
import issueLabelsQuery from './graphql/issue_labels.query.graphql';
@@ -19,11 +17,11 @@ Vue.use(Vuex);
export default {
store: new Vuex.Store(labelsSelectModule()),
components: {
- DropdownTitle,
DropdownValue,
DropdownButton,
DropdownContents,
DropdownValueCollapsed,
+ SidebarEditableItem,
},
inject: ['iid', 'projectPath'],
props: {
@@ -139,15 +137,12 @@ export default {
},
},
computed: {
- ...mapState(['showDropdownButton', 'showDropdownContents']),
+ ...mapState(['showDropdownContents']),
...mapGetters([
'isDropdownVariantSidebar',
'isDropdownVariantStandalone',
'isDropdownVariantEmbedded',
]),
- dropdownButtonVisible() {
- return this.isDropdownVariantSidebar ? this.showDropdownButton : true;
- },
},
watch: {
selectedLabels(selectedLabels) {
@@ -182,99 +177,20 @@ export default {
footerCreateLabelTitle: this.footerCreateLabelTitle,
footerManageLabelTitle: this.footerManageLabelTitle,
});
-
- this.$store.subscribeAction({
- after: this.handleVuexActionDispatch,
- });
-
- document.addEventListener('mousedown', this.handleDocumentMousedown);
- document.addEventListener('click', this.handleDocumentClick);
- },
- beforeDestroy() {
- document.removeEventListener('mousedown', this.handleDocumentMousedown);
- document.removeEventListener('click', this.handleDocumentClick);
},
methods: {
- ...mapActions(['setInitialState', 'toggleDropdownContents']),
- /**
- * This method stores a mousedown event's target.
- * Required by the click listener because the click
- * event itself has no reference to this element.
- */
- handleDocumentMousedown({ target }) {
- this.mousedownTarget = target;
- },
- /**
- * This method listens for document-wide click event
- * and toggle dropdown if user clicks anywhere outside
- * the dropdown while dropdown is visible.
- */
- handleDocumentClick({ target }) {
- // We also perform the toggle exception check for the
- // last mousedown event's target to avoid hiding the
- // box when the mousedown happened inside the box and
- // only the mouseup did not.
- if (
- this.showDropdownContents &&
- !this.preventDropdownToggleOnClick(target) &&
- !this.preventDropdownToggleOnClick(this.mousedownTarget)
- ) {
- this.toggleDropdownContents();
- }
- },
- /**
- * This method checks whether a given click target
- * should prevent the dropdown from being toggled.
- */
- preventDropdownToggleOnClick(target) {
- // This approach of element detection is needed
- // as the dropdown wrapper is not using `GlDropdown` as
- // it will also require us to use `BDropdownForm`
- // which is yet to be implemented in GitLab UI.
- const hasExceptionClass = [
- 'js-dropdown-button',
- 'js-btn-cancel-create',
- 'js-sidebar-dropdown-toggle',
- ].some(
- (className) =>
- target?.classList.contains(className) ||
- target?.parentElement?.classList.contains(className),
- );
-
- const hasExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
- (className) => $(target).parents(className).length,
- );
-
- const isInDropdownButtonCollapsed = this.$refs.dropdownButtonCollapsed?.$el.contains(target);
-
- const isInDropdownContents = this.$refs.dropdownContents?.$el.contains(target);
-
- return (
- hasExceptionClass ||
- hasExceptionParent ||
- isInDropdownButtonCollapsed ||
- isInDropdownContents
- );
- },
+ ...mapActions(['setInitialState']),
handleDropdownClose(labels) {
- // Only emit label updates if there are any labels to update
- // on UI.
- if (this.showDropdownContents) {
- this.toggleDropdownContents();
- }
if (labels.length) this.$emit('updateSelectedLabels', labels);
this.$emit('onDropdownClose');
},
+ collapseDropdown() {
+ this.$refs.editable.collapse();
+ },
handleCollapsedValueClick() {
this.$emit('toggleCollapse');
},
- setContentIsOnViewport(showDropdownContents) {
- if (!showDropdownContents) {
- this.contentIsOnViewport = true;
-
- return;
- }
-
+ setContentIsOnViewport() {
this.$nextTick(() => {
if (this.$refs.dropdownContents) {
this.contentIsOnViewport = isInViewport(this.$refs.dropdownContents.$el);
@@ -299,48 +215,55 @@ export default {
:labels="issueLabels"
@onValueClick="handleCollapsedValueClick"
/>
- <dropdown-title
- :allow-label-edit="allowLabelEdit"
- :labels-select-in-progress="labelsSelectInProgress"
- />
- <dropdown-value
- :disable-labels="labelsSelectInProgress"
- :selected-labels="issueLabels"
- :allow-label-remove="allowLabelRemove"
- :allow-scoped-labels="allowScopedLabels"
- :labels-filter-base-path="labelsFilterBasePath"
- :labels-filter-param="labelsFilterParam"
- @onLabelRemove="$emit('onLabelRemove', $event)"
+ <sidebar-editable-item
+ ref="editable"
+ :title="__('Labels')"
+ :loading="labelsSelectInProgress"
+ @open="setContentIsOnViewport"
+ @close="contentIsOnViewport = true"
>
- <slot></slot>
- </dropdown-value>
- <dropdown-button v-show="dropdownButtonVisible" class="gl-mt-2" />
- <dropdown-contents
- v-if="dropdownButtonVisible && showDropdownContents"
- ref="dropdownContents"
- :allow-multiselect="allowMultiselect"
- :labels-list-title="labelsListTitle"
- :footer-create-label-title="footerCreateLabelTitle"
- :footer-manage-label-title="footerManageLabelTitle"
- :render-on-top="!contentIsOnViewport"
- :labels-create-title="labelsCreateTitle"
- :selected-labels="selectedLabels"
- @closeDropdown="handleDropdownClose"
- />
- </template>
- <template v-if="isDropdownVariantStandalone || isDropdownVariantEmbedded">
- <dropdown-button v-show="dropdownButtonVisible" />
- <dropdown-contents
- v-if="dropdownButtonVisible && showDropdownContents"
- ref="dropdownContents"
- :allow-multiselect="allowMultiselect"
- :labels-list-title="labelsListTitle"
- :footer-create-label-title="footerCreateLabelTitle"
- :footer-manage-label-title="footerManageLabelTitle"
- :render-on-top="!contentIsOnViewport"
- :selected-labels="selectedLabels"
- @closeDropdown="handleDropdownClose"
- />
+ <template #collapsed>
+ <dropdown-value
+ :disable-labels="labelsSelectInProgress"
+ :selected-labels="issueLabels"
+ :allow-label-remove="allowLabelRemove"
+ :allow-scoped-labels="allowScopedLabels"
+ :labels-filter-base-path="labelsFilterBasePath"
+ :labels-filter-param="labelsFilterParam"
+ @onLabelRemove="$emit('onLabelRemove', $event)"
+ >
+ <slot></slot>
+ </dropdown-value>
+ </template>
+ <template #default="{ edit }">
+ <dropdown-value
+ :disable-labels="labelsSelectInProgress"
+ :selected-labels="issueLabels"
+ :allow-label-remove="allowLabelRemove"
+ :allow-scoped-labels="allowScopedLabels"
+ :labels-filter-base-path="labelsFilterBasePath"
+ :labels-filter-param="labelsFilterParam"
+ class="gl-mb-2"
+ @onLabelRemove="$emit('onLabelRemove', $event)"
+ >
+ <slot></slot>
+ </dropdown-value>
+ <dropdown-button />
+ <dropdown-contents
+ v-if="edit"
+ ref="dropdownContents"
+ :allow-multiselect="allowMultiselect"
+ :labels-list-title="labelsListTitle"
+ :footer-create-label-title="footerCreateLabelTitle"
+ :footer-manage-label-title="footerManageLabelTitle"
+ :render-on-top="!contentIsOnViewport"
+ :labels-create-title="labelsCreateTitle"
+ :selected-labels="selectedLabels"
+ @closeDropdown="collapseDropdown"
+ @setLabels="handleDropdownClose"
+ />
+ </template>
+ </sidebar-editable-item>
</template>
</div>
</template>