291 lines
8.6 KiB
Vue
291 lines
8.6 KiB
Vue
<script>
|
||
import {
|
||
GlAvatar,
|
||
GlBadge,
|
||
GlDisclosureDropdown,
|
||
GlDisclosureDropdownGroup,
|
||
GlDisclosureDropdownItem,
|
||
} from '@gitlab/ui';
|
||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||
import { s__, __, sprintf } from '~/locale';
|
||
import NewNavToggle from '~/nav/components/new_nav_toggle.vue';
|
||
import Tracking from '~/tracking';
|
||
import PersistentUserCallout from '~/persistent_user_callout';
|
||
import UserNameGroup from './user_name_group.vue';
|
||
|
||
export default {
|
||
feedbackUrl: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391533',
|
||
i18n: {
|
||
newNavigation: {
|
||
badgeLabel: s__('NorthstarNavigation|Alpha'),
|
||
sectionTitle: s__('NorthstarNavigation|Navigation redesign'),
|
||
},
|
||
setStatus: s__('SetStatusModal|Set status'),
|
||
editStatus: s__('SetStatusModal|Edit status'),
|
||
editProfile: s__('CurrentUser|Edit profile'),
|
||
preferences: s__('CurrentUser|Preferences'),
|
||
buyPipelineMinutes: s__('CurrentUser|Buy Pipeline minutes'),
|
||
oneOfGroupsRunningOutOfPipelineMinutes: s__('CurrentUser|One of your groups is running out'),
|
||
gitlabNext: s__('CurrentUser|Switch to GitLab Next'),
|
||
provideFeedback: s__('NorthstarNavigation|Provide feedback'),
|
||
startTrial: s__('CurrentUser|Start an Ultimate trial'),
|
||
signOut: __('Sign out'),
|
||
},
|
||
components: {
|
||
GlAvatar,
|
||
GlBadge,
|
||
GlDisclosureDropdown,
|
||
GlDisclosureDropdownGroup,
|
||
GlDisclosureDropdownItem,
|
||
NewNavToggle,
|
||
UserNameGroup,
|
||
},
|
||
directives: {
|
||
SafeHtml,
|
||
},
|
||
mixins: [Tracking.mixin()],
|
||
inject: ['toggleNewNavEndpoint'],
|
||
props: {
|
||
data: {
|
||
required: true,
|
||
type: Object,
|
||
},
|
||
},
|
||
computed: {
|
||
toggleText() {
|
||
return sprintf(__('%{user} user’s menu'), { user: this.data.name });
|
||
},
|
||
statusItem() {
|
||
const { busy, customized } = this.data.status;
|
||
|
||
const statusLabel =
|
||
busy || customized ? this.$options.i18n.editStatus : this.$options.i18n.setStatus;
|
||
|
||
return {
|
||
text: statusLabel,
|
||
extraAttrs: {
|
||
class: 'js-set-status-modal-trigger',
|
||
},
|
||
};
|
||
},
|
||
trialItem() {
|
||
return {
|
||
text: this.$options.i18n.startTrial,
|
||
href: this.data.trial.url,
|
||
};
|
||
},
|
||
editProfileItem() {
|
||
return {
|
||
text: this.$options.i18n.editProfile,
|
||
href: this.data.settings.profile_path,
|
||
extraAttrs: {
|
||
'data-qa-selector': 'edit_profile_link',
|
||
},
|
||
};
|
||
},
|
||
preferencesItem() {
|
||
return {
|
||
text: this.$options.i18n.preferences,
|
||
href: this.data.settings.profile_preferences_path,
|
||
};
|
||
},
|
||
addBuyPipelineMinutesMenuItem() {
|
||
return this.data.pipeline_minutes?.show_buy_pipeline_minutes;
|
||
},
|
||
buyPipelineMinutesItem() {
|
||
return {
|
||
text: this.$options.i18n.buyPipelineMinutes,
|
||
warningText: this.$options.i18n.oneOfGroupsRunningOutOfPipelineMinutes,
|
||
href: this.data.pipeline_minutes?.buy_pipeline_minutes_path,
|
||
extraAttrs: {
|
||
class: 'js-follow-link',
|
||
},
|
||
};
|
||
},
|
||
gitlabNextItem() {
|
||
return {
|
||
text: this.$options.i18n.gitlabNext,
|
||
href: this.data.canary_toggle_com_url,
|
||
};
|
||
},
|
||
feedbackItem() {
|
||
return {
|
||
text: this.$options.i18n.provideFeedback,
|
||
href: this.$options.feedbackUrl,
|
||
extraAttrs: {
|
||
target: '_blank',
|
||
},
|
||
};
|
||
},
|
||
signOutGroup() {
|
||
return {
|
||
items: [
|
||
{
|
||
text: this.$options.i18n.signOut,
|
||
href: this.data.sign_out_link,
|
||
extraAttrs: {
|
||
'data-method': 'post',
|
||
'data-qa-selector': 'sign_out_link',
|
||
class: 'sign-out-link',
|
||
},
|
||
},
|
||
],
|
||
};
|
||
},
|
||
statusModalData() {
|
||
const defaultData = {
|
||
'data-current-emoji': '',
|
||
'data-current-message': '',
|
||
'data-default-emoji': 'speech_balloon',
|
||
};
|
||
|
||
if (!this.data.status.customized) {
|
||
return defaultData;
|
||
}
|
||
return {
|
||
...defaultData,
|
||
'data-current-emoji': this.data.status.emoji,
|
||
'data-current-message': this.data.status.message,
|
||
'data-current-availability': this.data.status.availability,
|
||
'data-current-clear-status-after': this.data.status.clear_after,
|
||
};
|
||
},
|
||
buyPipelineMinutesCalloutData() {
|
||
return this.showNotificationDot
|
||
? {
|
||
'data-feature-id': this.data.pipeline_minutes.callout_attrs.feature_id,
|
||
'data-dismiss-endpoint': this.data.pipeline_minutes.callout_attrs.dismiss_endpoint,
|
||
}
|
||
: {};
|
||
},
|
||
showNotificationDot() {
|
||
return this.data.pipeline_minutes?.show_notification_dot;
|
||
},
|
||
},
|
||
methods: {
|
||
onShow() {
|
||
this.trackEvents();
|
||
this.initCallout();
|
||
},
|
||
initCallout() {
|
||
if (this.showNotificationDot) {
|
||
PersistentUserCallout.factory(this.$refs?.buyPipelineMinutesNotificationCallout.$el);
|
||
}
|
||
},
|
||
trackEvents() {
|
||
if (this.addBuyPipelineMinutesMenuItem) {
|
||
const {
|
||
'track-action': trackAction,
|
||
'track-label': label,
|
||
'track-property': property,
|
||
} = this.data.pipeline_minutes.tracking_attrs;
|
||
this.track(trackAction, { label, property });
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<template>
|
||
<div>
|
||
<gl-disclosure-dropdown
|
||
placement="right"
|
||
data-testid="user-dropdown"
|
||
data-qa-selector="user_menu"
|
||
@shown="onShow"
|
||
>
|
||
<template #toggle>
|
||
<button class="user-bar-item btn-with-notification">
|
||
<span class="gl-sr-only">{{ toggleText }}</span>
|
||
<gl-avatar
|
||
:size="24"
|
||
:entity-name="data.name"
|
||
:src="data.avatar_url"
|
||
aria-hidden="true"
|
||
data-qa-selector="user_avatar_content"
|
||
/>
|
||
<span
|
||
v-if="showNotificationDot"
|
||
class="notification-dot-warning"
|
||
data-testid="buy-pipeline-minutes-notification-dot"
|
||
v-bind="data.pipeline_minutes.notification_dot_attrs"
|
||
>
|
||
</span>
|
||
</button>
|
||
</template>
|
||
|
||
<user-name-group :user="data" />
|
||
<gl-disclosure-dropdown-group bordered>
|
||
<gl-disclosure-dropdown-item
|
||
v-if="data.status.can_update"
|
||
:item="statusItem"
|
||
data-testid="status-item"
|
||
/>
|
||
|
||
<gl-disclosure-dropdown-item
|
||
v-if="data.trial.has_start_trial"
|
||
:item="trialItem"
|
||
data-testid="start-trial-item"
|
||
>
|
||
<template #list-item>
|
||
{{ trialItem.text }}
|
||
<gl-emoji data-name="rocket" />
|
||
</template>
|
||
</gl-disclosure-dropdown-item>
|
||
|
||
<gl-disclosure-dropdown-item :item="editProfileItem" data-testid="edit-profile-item" />
|
||
|
||
<gl-disclosure-dropdown-item :item="preferencesItem" data-testid="preferences-item" />
|
||
|
||
<gl-disclosure-dropdown-item
|
||
v-if="addBuyPipelineMinutesMenuItem"
|
||
ref="buyPipelineMinutesNotificationCallout"
|
||
:item="buyPipelineMinutesItem"
|
||
v-bind="buyPipelineMinutesCalloutData"
|
||
data-testid="buy-pipeline-minutes-item"
|
||
>
|
||
<template #list-item>
|
||
<span class="gl-display-flex gl-flex-direction-column">
|
||
<span>{{ buyPipelineMinutesItem.text }} <gl-emoji data-name="clock9" /></span>
|
||
<span
|
||
v-if="data.pipeline_minutes.show_with_subtext"
|
||
class="gl-font-sm small gl-pt-2 gl-text-orange-800"
|
||
>{{ buyPipelineMinutesItem.warningText }}</span
|
||
>
|
||
</span>
|
||
</template>
|
||
</gl-disclosure-dropdown-item>
|
||
|
||
<gl-disclosure-dropdown-item
|
||
v-if="data.gitlab_com_but_not_canary"
|
||
:item="gitlabNextItem"
|
||
data-testid="gitlab-next-item"
|
||
/>
|
||
</gl-disclosure-dropdown-group>
|
||
|
||
<gl-disclosure-dropdown-group bordered>
|
||
<template #group-label>
|
||
<span class="gl-font-sm">{{ $options.i18n.newNavigation.sectionTitle }}</span>
|
||
<gl-badge size="sm" variant="info"
|
||
>{{ $options.i18n.newNavigation.badgeLabel }}
|
||
</gl-badge>
|
||
</template>
|
||
<new-nav-toggle :endpoint="toggleNewNavEndpoint" enabled new-navigation />
|
||
<gl-disclosure-dropdown-item :item="feedbackItem" data-testid="feedback-item" />
|
||
</gl-disclosure-dropdown-group>
|
||
|
||
<gl-disclosure-dropdown-group
|
||
v-if="data.can_sign_out"
|
||
bordered
|
||
:group="signOutGroup"
|
||
data-testid="sign-out-group"
|
||
/>
|
||
</gl-disclosure-dropdown>
|
||
|
||
<div
|
||
v-if="data.status.can_update"
|
||
class="js-set-status-modal-wrapper"
|
||
v-bind="statusModalData"
|
||
></div>
|
||
</div>
|
||
</template>
|