diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/sidebar')
16 files changed, 81 insertions, 181 deletions
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue deleted file mode 100644 index a1dca65a423..00000000000 --- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue +++ /dev/null @@ -1,101 +0,0 @@ -<script> -import { dateInWords, timeFor } from '~/lib/utils/datetime_utility'; -import { __ } from '~/locale'; -import timeagoMixin from '~/vue_shared/mixins/timeago'; -import collapsedCalendarIcon from './collapsed_calendar_icon.vue'; - -export default { - name: 'SidebarCollapsedGroupedDatePicker', - components: { - collapsedCalendarIcon, - }, - mixins: [timeagoMixin], - props: { - collapsed: { - type: Boolean, - required: false, - default: true, - }, - minDate: { - type: Date, - required: false, - default: null, - }, - maxDate: { - type: Date, - required: false, - default: null, - }, - disableClickableIcons: { - type: Boolean, - required: false, - default: false, - }, - }, - computed: { - hasMinAndMaxDates() { - return this.minDate && this.maxDate; - }, - hasNoMinAndMaxDates() { - return !this.minDate && !this.maxDate; - }, - showMinDateBlock() { - return this.minDate || this.hasNoMinAndMaxDates; - }, - showFromText() { - return !this.maxDate && this.minDate; - }, - iconClass() { - const disabledClass = this.disableClickableIcons ? 'disabled' : ''; - return `sidebar-collapsed-icon calendar-icon ${disabledClass}`; - }, - }, - methods: { - toggleSidebar() { - this.$emit('toggleCollapse'); - }, - dateText(dateType = 'min') { - const date = this[`${dateType}Date`]; - const dateWords = dateInWords(date, true); - const parsedDateWords = dateWords ? dateWords.replace(',', '') : dateWords; - - return date ? parsedDateWords : __('None'); - }, - tooltipText(dateType = 'min') { - const defaultText = dateType === 'min' ? __('Start date') : __('Due date'); - const date = this[`${dateType}Date`]; - const timeAgo = dateType === 'min' ? this.timeFormatted(date) : timeFor(date); - const dateText = date ? [this.dateText(dateType), `(${timeAgo})`].join(' ') : ''; - - if (date) { - return [defaultText, dateText].join('<br />'); - } - return __('Start and due date'); - }, - }, -}; -</script> - -<template> - <div class="block sidebar-grouped-item gl-cursor-pointer" role="button" @click="toggleSidebar"> - <collapsed-calendar-icon - v-if="showMinDateBlock" - :container-class="iconClass" - :tooltip-text="tooltipText('min')" - > - <span class="sidebar-collapsed-value"> - <span v-if="showFromText">{{ __('From') }}</span> <span>{{ dateText('min') }}</span> - </span> - </collapsed-calendar-icon> - <div v-if="hasMinAndMaxDates" class="text-center sidebar-collapsed-divider">-</div> - <collapsed-calendar-icon - v-if="maxDate" - :container-class="iconClass" - :tooltip-text="tooltipText('max')" - > - <span class="sidebar-collapsed-value"> - <span v-if="!minDate">{{ __('Until') }}</span> <span>{{ dateText('max') }}</span> - </span> - </collapsed-calendar-icon> - </div> -</template> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue index 4234bc72f3a..7e259cb8b96 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue @@ -179,6 +179,8 @@ export default { document.addEventListener('mousedown', this.handleDocumentMousedown); document.addEventListener('click', this.handleDocumentClick); + + this.updateLabelsSetState(); }, beforeDestroy() { document.removeEventListener('mousedown', this.handleDocumentMousedown); 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 f7485de0342..13a6dd43207 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 @@ -172,6 +172,13 @@ export default { showDropdown() { this.$refs.dropdown.show(); }, + clearSearch() { + if (!this.allowMultiselect || this.isStandalone) { + return; + } + this.searchKey = ''; + this.setFocus(); + }, }, }; </script> @@ -188,12 +195,12 @@ export default { > <template #header> <dropdown-header - v-if="!isStandalone" ref="header" - v-model="searchKey" + :search-key="searchKey" :labels-create-title="labelsCreateTitle" :labels-list-title="labelsListTitle" :show-dropdown-contents-create-view="showDropdownContentsCreateView" + :is-standalone="isStandalone" @toggleDropdownContentsCreateView="toggleDropdownContent" @closeDropdown="$emit('closeDropdown')" @input="debouncedSearchKeyUpdate" @@ -210,6 +217,7 @@ export default { :attr-workspace-path="attrWorkspacePath" :label-create-type="labelCreateType" @hideCreateView="toggleDropdownContent" + @input="clearSearch" /> </template> <template #footer> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue index 10064b01648..7a0f20b0c83 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue @@ -6,9 +6,6 @@ export default { GlButton, GlSearchBoxByType, }, - model: { - prop: 'searchKey', - }, props: { labelsCreateTitle: { type: String, @@ -31,6 +28,11 @@ export default { type: String, required: true, }, + isStandalone: { + type: Boolean, + required: false, + default: false, + }, }, computed: { dropdownTitle() { @@ -47,7 +49,11 @@ export default { <template> <div data-testid="dropdown-header"> - <div class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!"> + <div + v-if="!isStandalone" + class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!" + data-testid="dropdown-header-title" + > <gl-button v-if="showDropdownContentsCreateView" :aria-label="__('Go back')" diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue index aed5bc303ee..57ee816c4c7 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue @@ -1,10 +1,15 @@ <script> -import { GlLabel } from '@gitlab/ui'; +import { GlIcon, GlLabel, GlTooltipDirective } from '@gitlab/ui'; import { sortBy } from 'lodash'; import { isScopedLabel } from '~/lib/utils/common_utils'; +import { s__, sprintf } from '~/locale'; export default { + directives: { + GlTooltip: GlTooltipDirective, + }, components: { + GlIcon, GlLabel, }, inject: ['allowScopedLabels'], @@ -35,6 +40,23 @@ export default { sortedSelectedLabels() { return sortBy(this.selectedLabels, (label) => (isScopedLabel(label) ? 0 : 1)); }, + labelsList() { + const labelsString = this.selectedLabels.length + ? this.selectedLabels + .slice(0, 5) + .map((label) => label.title) + .join(', ') + : s__('LabelSelect|Labels'); + + if (this.selectedLabels.length > 5) { + return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), { + labelsString, + remainingLabelCount: this.selectedLabels.length - 5, + }); + } + + return labelsString; + }, }, methods: { labelFilterUrl(label) { @@ -48,6 +70,9 @@ export default { removeLabel(labelId) { this.$emit('onLabelRemove', labelId); }, + handleCollapsedClick() { + this.$emit('onCollapsedValueClick'); + }, }, }; </script> @@ -57,16 +82,30 @@ export default { :class="{ 'has-labels': selectedLabels.length, }" - class="hide-collapsed value issuable-show-labels js-value" + class="value issuable-show-labels js-value" data-testid="value-wrapper" > - <span v-if="!selectedLabels.length" class="text-secondary" data-testid="empty-placeholder"> + <div + v-gl-tooltip.left.viewport + :title="labelsList" + class="sidebar-collapsed-icon" + @click="handleCollapsedClick" + > + <gl-icon name="labels" /> + <span class="gl-font-base gl-line-height-24">{{ selectedLabels.length }}</span> + </div> + <span + v-if="!selectedLabels.length" + class="text-secondary hide-collapsed" + data-testid="empty-placeholder" + > <slot></slot> </span> <template v-else> <gl-label v-for="label in sortedSelectedLabels" :key="label.id" + class="hide-collapsed" data-qa-selector="selected_label_content" :data-qa-label-name="label.title" :title="label.title" diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue deleted file mode 100644 index 122250d1ce7..00000000000 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue +++ /dev/null @@ -1,55 +0,0 @@ -<script> -import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; -import { s__, sprintf } from '~/locale'; - -export default { - directives: { - GlTooltip: GlTooltipDirective, - }, - components: { - GlIcon, - }, - props: { - labels: { - type: Array, - required: true, - }, - }, - computed: { - labelsList() { - const labelsString = this.labels.length - ? this.labels - .slice(0, 5) - .map((label) => label.title) - .join(', ') - : s__('LabelSelect|Labels'); - - if (this.labels.length > 5) { - return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), { - labelsString, - remainingLabelCount: this.labels.length - 5, - }); - } - - return labelsString; - }, - }, - methods: { - handleClick() { - this.$emit('onValueClick'); - }, - }, -}; -</script> - -<template> - <div - v-gl-tooltip.left.viewport - :title="labelsList" - class="sidebar-collapsed-icon" - @click="handleClick" - > - <gl-icon name="labels" /> - <span>{{ labels.length }}</span> - </div> -</template> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql index c130cc426dc..c442c17eb88 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql @@ -2,6 +2,7 @@ query epicLabels($fullPath: ID!, $iid: ID) { workspace: group(fullPath: $fullPath) { + id issuable: epic(iid: $iid) { id labels { diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql index 45fcb50732e..cb054e2968f 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql @@ -1,8 +1,8 @@ #import "~/graphql_shared/fragments/label.fragment.graphql" mutation updateEpicLabels($input: UpdateEpicInput!) { - updateEpic(input: $input) { - epic { + updateIssuableLabels: updateEpic(input: $input) { + issuable: epic { id labels { nodes { diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql index e471d279b24..2904857270e 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql @@ -2,6 +2,7 @@ query issueLabels($fullPath: ID!, $iid: String) { workspace: project(fullPath: $fullPath) { + id issuable: issue(iid: $iid) { id labels { diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql index dd80e89c8a7..e0cdfd91658 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql @@ -2,6 +2,7 @@ query mergeRequestLabels($fullPath: ID!, $iid: String!) { workspace: project(fullPath: $fullPath) { + id issuable: mergeRequest(iid: $iid) { id labels { 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 97a65c13933..3adda69b892 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 @@ -2,14 +2,13 @@ import { debounce } from 'lodash'; import { MutationOperationMode, getIdFromGraphQLId } from '~/graphql_shared/utils'; import createFlash from '~/flash'; -import { IssuableType } from '~/issue_show/constants'; +import { IssuableType } from '~/issues/constants'; import { __ } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; import { issuableLabelsQueries } from '~/sidebar/constants'; import { DEBOUNCE_DROPDOWN_DELAY, DropdownVariant } from './constants'; import DropdownContents from './dropdown_contents.vue'; import DropdownValue from './dropdown_value.vue'; -import DropdownValueCollapsed from './dropdown_value_collapsed.vue'; import { isDropdownVariantSidebar, isDropdownVariantStandalone, @@ -20,7 +19,6 @@ export default { components: { DropdownValue, DropdownContents, - DropdownValueCollapsed, SidebarEditableItem, }, inject: { @@ -225,15 +223,13 @@ export default { variables: { input: inputVariables }, }) .then(({ data }) => { - const { mutationName } = issuableLabelsQueries[this.issuableType]; - - if (data[mutationName]?.errors?.length) { + if (data.updateIssuableLabels?.errors?.length) { throw new Error(); } this.$emit('updateSelectedLabels', { - id: data[mutationName]?.[this.issuableType]?.id, - labels: data[mutationName]?.[this.issuableType]?.labels?.nodes, + id: data.updateIssuableLabels?.issuable?.id, + labels: data.updateIssuableLabels?.issuable?.labels?.nodes, }); }) .catch((error) => @@ -288,18 +284,14 @@ export default { <template> <div - class="labels-select-wrapper position-relative" + class="labels-select-wrapper gl-relative" :class="{ 'is-standalone': isDropdownVariantStandalone(variant), 'is-embedded': isDropdownVariantEmbedded(variant), }" + data-qa-selector="labels_block" > <template v-if="isDropdownVariantSidebar(variant)"> - <dropdown-value-collapsed - ref="dropdownButtonCollapsed" - :labels="issuableLabels" - @onValueClick="handleCollapsedValueClick" - /> <sidebar-editable-item ref="editable" :title="__('Labels')" @@ -315,6 +307,7 @@ export default { :labels-filter-base-path="labelsFilterBasePath" :labels-filter-param="labelsFilterParam" @onLabelRemove="handleLabelRemove" + @onCollapsedValueClick="handleCollapsedValueClick" > <slot></slot> </dropdown-value> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql index d99fc125012..bb6c7181e5c 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql @@ -7,6 +7,7 @@ query alertAssignees( $iid: String! ) { workspace: project(fullPath: $fullPath) { + id issuable: alertManagementAlert(domain: $domain, iid: $iid) { iid assignees { diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql index 93b9833bb7d..be270e440ed 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql @@ -4,6 +4,7 @@ query issueAssignees($fullPath: ID!, $iid: String!) { workspace: project(fullPath: $fullPath) { __typename + id issuable: issue(iid: $iid) { __typename id diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql index 48787305459..96a40e597ee 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql @@ -4,6 +4,7 @@ query issueParticipants($fullPath: ID!, $iid: String!) { workspace: project(fullPath: $fullPath) { __typename + id issuable: issue(iid: $iid) { __typename id diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql index 53f7381760e..81e19e48d75 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql @@ -3,6 +3,7 @@ query getMrAssignees($fullPath: ID!, $iid: String!) { workspace: project(fullPath: $fullPath) { + id issuable: mergeRequest(iid: $iid) { id assignees { diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql index 6adbd4098f2..3496d5f4a2e 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql +++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql @@ -3,6 +3,7 @@ query getMrParticipants($fullPath: ID!, $iid: String!) { workspace: project(fullPath: $fullPath) { + id issuable: mergeRequest(iid: $iid) { id participants { |