diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-08 15:12:41 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-08 15:12:41 +0300 |
commit | 8fea353b907d1fd571f5450a757cafee73cfbfd0 (patch) | |
tree | 38cd1edddd3de94d6f743029c164fab5691a7241 /app/assets/javascripts/sidebar | |
parent | db5097a28b061ef273a058aa64845c79635ea4e7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/sidebar')
4 files changed, 133 insertions, 6 deletions
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue index b62a2c7bcd1..6c615109bb8 100644 --- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue +++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue @@ -9,6 +9,8 @@ import { GlLoadingIcon, GlIcon, GlTooltipDirective, + GlPopover, + GlButton, } from '@gitlab/ui'; import { kebabCase, snakeCase } from 'lodash'; import createFlash from '~/flash'; @@ -17,6 +19,7 @@ import { IssuableType } from '~/issues/constants'; import { timeFor } from '~/lib/utils/datetime_utility'; import { __ } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { dropdowni18nText, Tracking, @@ -47,7 +50,10 @@ export default { GlSearchBoxByType, GlIcon, GlLoadingIcon, + GlPopover, + GlButton, }, + mixins: [glFeatureFlagMixin()], inject: { isClassicSidebar: { default: false, @@ -66,6 +72,7 @@ export default { }, }, }, + props: { issuableAttribute: { type: String, @@ -111,6 +118,10 @@ export default { }; }, update(data) { + if (this.glFeatures?.epicWidgetEditConfirmation && this.isEpic) { + this.hasCurrentAttribute = data?.workspace?.issuable.hasEpic; + } + return data?.workspace?.issuable.attribute; }, error(error) { @@ -179,6 +190,8 @@ export default { updating: false, selectedTitle: null, currentAttribute: null, + hasCurrentAttribute: false, + editConfirmation: false, attributesList: [], tracking: { event: Tracking.editEvent, @@ -228,6 +241,15 @@ export default { snake: snakeCase(this.issuableAttribute), }; }, + shouldShowConfirmationPopover() { + if (!this.glFeatures?.epicWidgetEditConfirmation) { + return false; + } + + return this.isEpic && this.currentAttribute === null && this.hasCurrentAttribute + ? !this.editConfirmation + : false; + }, }, methods: { updateAttribute(attributeId) { @@ -299,6 +321,17 @@ export default { setFocus() { this.$refs.search.focusInput(); }, + handlePopoverClose() { + this.$refs.popover.$emit('close'); + }, + handlePopoverConfirm(cb) { + this.editConfirmation = true; + this.handlePopoverClose(); + setTimeout(cb, 0); + }, + handleEditConfirmation() { + this.$refs.popover.$emit('open'); + }, }, }; </script> @@ -308,10 +341,13 @@ export default { ref="editable" :title="attributeTypeTitle" :data-testid="`${formatIssuableAttribute.kebab}-edit`" + :button-id="`${formatIssuableAttribute.kebab}-edit`" :tracking="tracking" + :should-show-confirmation-popover="shouldShowConfirmationPopover" :loading="updating || loading" @open="handleOpen" @close="handleClose" + @edit-confirm="handleEditConfirmation" > <template #collapsed> <slot name="value-collapsed" :current-attribute="currentAttribute"> @@ -332,6 +368,10 @@ export default { :class="isClassicSidebar ? 'hide-collapsed' : 'gl-mt-3'" > <span v-if="updating">{{ selectedTitle }}</span> + <template v-else-if="!currentAttribute && hasCurrentAttribute"> + <gl-icon name="warning" class="gl-text-orange-500" /> + <span class="gl-text-gray-500">{{ i18n.noPermissionToView }}</span> + </template> <span v-else-if="!currentAttribute" class="gl-text-gray-500"> {{ $options.i18n.none }} </span> @@ -354,7 +394,40 @@ export default { </slot> </div> </template> - <template #default> + <template v-if="shouldShowConfirmationPopover" #default="{ toggle }"> + <gl-popover + ref="popover" + :target="`${formatIssuableAttribute.kebab}-edit`" + placement="bottomleft" + boundary="viewport" + triggers="click" + > + <div class="gl-mb-4 gl-font-base"> + {{ i18n.editConfirmation }} + </div> + <div class="gl-display-flex gl-align-items-center"> + <gl-button + size="small" + variant="confirm" + category="primary" + data-testid="confirm-edit-cta" + @click.prevent="() => handlePopoverConfirm(toggle)" + >{{ i18n.editConfirmationCta }}</gl-button + > + <gl-button + class="gl-ml-auto" + size="small" + name="cancel" + variant="default" + category="primary" + data-testid="confirm-edit-cancel" + @click.prevent="handlePopoverClose" + >{{ i18n.editConfirmationCancel }}</gl-button + > + </div> + </gl-popover> + </template> + <template v-else #default> <gl-dropdown ref="newDropdown" lazy diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue index 7551b181a58..cc88812c7b0 100644 --- a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue +++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue @@ -14,6 +14,11 @@ export default { }, }, props: { + buttonId: { + type: String, + required: false, + default: '', + }, title: { type: String, required: false, @@ -48,6 +53,11 @@ export default { required: false, default: true, }, + shouldShowConfirmationPopover: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -97,6 +107,11 @@ export default { window.removeEventListener('keyup', this.collapseOnEscape); }, toggle({ emitEvent = true } = {}) { + if (this.shouldShowConfirmationPopover) { + this.$emit('edit-confirm'); + return; + } + if (this.edit) { this.collapse({ emitEvent }); } else { @@ -132,6 +147,7 @@ export default { <slot name="collapsed-right"></slot> <gl-button v-if="canUpdate && !initialLoading && canEdit" + :id="buttonId" category="tertiary" size="small" class="gl-text-gray-900! gl-ml-auto hide-collapsed gl-mr-n2 shortcut-sidebar-dropdown-toggle" @@ -151,7 +167,7 @@ export default { <slot name="collapsed">{{ __('None') }}</slot> </div> <div v-show="edit" data-testid="expanded-content" :class="{ 'gl-mt-3': !isClassicSidebar }"> - <slot :edit="edit"></slot> + <slot :edit="edit" :toggle="toggle"></slot> </div> </template> </div> diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue index da93c97f07a..13981c477c6 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue @@ -1,8 +1,16 @@ <script> -import { GlIcon, GlLink, GlModal, GlButton, GlModalDirective, GlLoadingIcon } from '@gitlab/ui'; +import { + GlIcon, + GlLink, + GlModal, + GlButton, + GlModalDirective, + GlLoadingIcon, + GlTooltipDirective, +} from '@gitlab/ui'; import { IssuableType } from '~/issues/constants'; import { s__, __ } from '~/locale'; -import { timeTrackingQueries } from '~/sidebar/constants'; +import { HOW_TO_TRACK_TIME, timeTrackingQueries } from '~/sidebar/constants'; import eventHub from '../../event_hub'; import TimeTrackingCollapsedState from './collapsed_state.vue'; @@ -31,6 +39,7 @@ export default { }, directives: { GlModal: GlModalDirective, + GlTooltip: GlTooltipDirective, }, inject: { issuableType: { @@ -162,6 +171,12 @@ export default { this.issuableId ); }, + timeTrackingIconTitle() { + return this.showHelpState ? '' : HOW_TO_TRACK_TIME; + }, + timeTrackingIconName() { + return this.showHelpState ? 'close' : 'question-o'; + }, }, watch: { /** @@ -212,7 +227,12 @@ export default { class="gl-ml-auto" @click="toggleHelpState(!showHelpState)" > - <gl-icon :name="showHelpState ? 'close' : 'question-o'" class="gl-text-gray-900!" /> + <gl-icon + v-gl-tooltip.left + :title="timeTrackingIconTitle" + :name="timeTrackingIconName" + class="gl-text-gray-900!" + /> </gl-button> </div> <div v-if="!isTimeTrackingInfoLoading" class="hide-collapsed"> diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js index 989dc574bc3..60cb4cff727 100644 --- a/app/assets/javascripts/sidebar/constants.js +++ b/app/assets/javascripts/sidebar/constants.js @@ -1,4 +1,4 @@ -import { s__, sprintf } from '~/locale'; +import { s__, __, sprintf } from '~/locale'; import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql'; import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql'; import userSearchWithMRPermissionsQuery from '~/graphql_shared/queries/users_search_with_mr_permissions.graphql'; @@ -313,8 +313,26 @@ export function dropdowni18nText(issuableAttribute, issuableType) { ), { issuableAttribute, issuableType }, ), + noPermissionToView: sprintf( + s__("DropdownWidget|You don't have permission to view this %{issuableAttribute}."), + { issuableAttribute }, + ), + editConfirmation: sprintf( + s__( + 'DropdownWidget|You do not have permission to view the currently assigned %{issuableAttribute} and will not be able to choose it again if you reassign it.', + ), + { + issuableAttribute, + }, + ), + editConfirmationCta: sprintf(s__('DropdownWidget|Edit %{issuableAttribute}'), { + issuableAttribute, + }), + editConfirmationCancel: s__('DropdownWidget|Cancel'), }; } export const escalationStatusQuery = getEscalationStatusQuery; export const escalationStatusMutation = updateEscalationStatusMutation; + +export const HOW_TO_TRACK_TIME = __('How to track time'); |