mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-08-19 01:23:09 +00:00
378 lines
9.4 KiB
Vue
378 lines
9.4 KiB
Vue
<script>
|
|
import {
|
|
GlDisclosureDropdown,
|
|
GlDisclosureDropdownGroup,
|
|
GlDisclosureDropdownItem,
|
|
GlTooltipDirective,
|
|
} from '@gitlab/ui';
|
|
import { s__, __ } from '~/locale';
|
|
import { visitUrl, appendLineRangeHashToUrl } from '~/lib/utils/url_utility';
|
|
import Tracking from '~/tracking';
|
|
import ConfirmForkModal from '~/vue_shared/components/web_ide/confirm_fork_modal.vue';
|
|
import { keysFor, GO_TO_PROJECT_WEBIDE } from '~/behaviors/shortcuts/keybindings';
|
|
import { shouldDisableShortcuts } from '~/behaviors/shortcuts/shortcuts_toggle';
|
|
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
|
import { KEY_EDIT, KEY_WEB_IDE, KEY_GITPOD, KEY_PIPELINE_EDITOR } from './constants';
|
|
|
|
export const i18n = {
|
|
webIdeText: s__('WebIDE|Quickly and easily edit multiple files in your project.'),
|
|
webIdeTooltip: s__(
|
|
'WebIDE|Quickly and easily edit multiple files in your project. Press . to open',
|
|
),
|
|
toggleText: __('Edit'),
|
|
gitpodText: __('Launch a ready-to-code development environment for your project.'),
|
|
};
|
|
|
|
const TRACKING_ACTION_NAME = 'click_consolidated_edit';
|
|
|
|
export default {
|
|
name: 'CEWebIdeLink',
|
|
components: {
|
|
GlDisclosureDropdown,
|
|
GlDisclosureDropdownGroup,
|
|
GlDisclosureDropdownItem,
|
|
ConfirmForkModal,
|
|
},
|
|
directives: {
|
|
GlTooltip: GlTooltipDirective,
|
|
},
|
|
i18n,
|
|
mixins: [Tracking.mixin(), glFeatureFlagsMixin()],
|
|
props: {
|
|
isFork: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
needsToFork: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
needsToForkWithWebIde: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
isGitpodEnabledForUser: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
isBlob: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
showEditButton: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: true,
|
|
},
|
|
showWebIdeButton: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: true,
|
|
},
|
|
isGitpodEnabledForInstance: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
showPipelineEditorButton: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
editUrl: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
buttonVariant: {
|
|
type: String,
|
|
required: false,
|
|
default: null,
|
|
},
|
|
pipelineEditorUrl: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
webIdeUrl: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
webIdeText: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
gitpodUrl: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
gitpodText: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
disableForkModal: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
forkPath: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
forkModalId: {
|
|
type: String,
|
|
required: false,
|
|
default: '',
|
|
},
|
|
cssClasses: {
|
|
type: String,
|
|
required: false,
|
|
default: 'sm:gl-ml-3',
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
customTooltipText: {
|
|
type: String,
|
|
required: false,
|
|
default: __('You cannot edit this file'),
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
showForkModal: false,
|
|
};
|
|
},
|
|
computed: {
|
|
hideIDEActionsInDirectoryView() {
|
|
return this.glFeatures.directoryCodeDropdownUpdates && !this.isBlob;
|
|
},
|
|
actions() {
|
|
return this.hideIDEActionsInDirectoryView
|
|
? [this.pipelineEditorAction, this.editAction].filter(Boolean)
|
|
: [this.pipelineEditorAction, this.webIdeAction, this.editAction, this.gitpodAction].filter(
|
|
Boolean,
|
|
);
|
|
},
|
|
hasActions() {
|
|
return this.actions.length > 0;
|
|
},
|
|
editButtonVariant() {
|
|
if (this.buttonVariant) {
|
|
return this.buttonVariant;
|
|
}
|
|
return this.isBlob ? 'confirm' : 'default';
|
|
},
|
|
editAction() {
|
|
if (!this.showEditButton) return null;
|
|
|
|
const handleOptions = this.needsToFork
|
|
? {
|
|
href: '#modal-confirm-fork-edit',
|
|
handle: () => {
|
|
if (this.disableForkModal) {
|
|
this.$emit('edit', 'simple');
|
|
return;
|
|
}
|
|
|
|
this.showModal('showForkModal');
|
|
},
|
|
}
|
|
: { href: this.editUrl };
|
|
|
|
return {
|
|
key: KEY_EDIT,
|
|
text: __('Edit single file'),
|
|
secondaryText: __('Edit this file only.'),
|
|
tracking: {
|
|
action: TRACKING_ACTION_NAME,
|
|
label: 'single_file',
|
|
},
|
|
...handleOptions,
|
|
};
|
|
},
|
|
shortcutsDisabled() {
|
|
return shouldDisableShortcuts();
|
|
},
|
|
webIdeActionShortcutKey() {
|
|
return keysFor(GO_TO_PROJECT_WEBIDE)[0];
|
|
},
|
|
webIdeActionText() {
|
|
if (this.webIdeText) {
|
|
return this.webIdeText;
|
|
}
|
|
if (this.isBlob) {
|
|
return __('Open in Web IDE');
|
|
}
|
|
if (this.isFork) {
|
|
return __('Edit fork in Web IDE');
|
|
}
|
|
|
|
return __('Web IDE');
|
|
},
|
|
webIdeAction() {
|
|
if (!this.showWebIdeButton) return null;
|
|
|
|
const handleOptions = this.needsToForkWithWebIde
|
|
? {
|
|
handle: () => {
|
|
if (this.disableForkModal) {
|
|
this.$emit('edit', 'ide');
|
|
return;
|
|
}
|
|
|
|
this.showModal('showForkModal');
|
|
},
|
|
}
|
|
: {
|
|
handle: () => {
|
|
const url = appendLineRangeHashToUrl(this.webIdeUrl);
|
|
visitUrl(url, true);
|
|
},
|
|
};
|
|
|
|
return {
|
|
key: KEY_WEB_IDE,
|
|
text: this.webIdeActionText,
|
|
secondaryText: this.$options.i18n.webIdeText,
|
|
shortcut: this.webIdeActionShortcutKey,
|
|
tracking: {
|
|
action: TRACKING_ACTION_NAME,
|
|
label: 'web_ide',
|
|
},
|
|
...handleOptions,
|
|
};
|
|
},
|
|
gitpodActionText() {
|
|
if (this.isBlob) {
|
|
return __('Open in Gitpod');
|
|
}
|
|
return this.gitpodText || __('Gitpod');
|
|
},
|
|
computedShowGitpodButton() {
|
|
return this.isGitpodEnabledForInstance && this.isGitpodEnabledForUser && this.gitpodUrl;
|
|
},
|
|
pipelineEditorAction() {
|
|
if (!this.showPipelineEditorButton) {
|
|
return null;
|
|
}
|
|
|
|
const secondaryText = __('Edit, lint, and visualize your pipeline.');
|
|
|
|
return {
|
|
key: KEY_PIPELINE_EDITOR,
|
|
text: __('Edit in pipeline editor'),
|
|
secondaryText,
|
|
href: this.pipelineEditorUrl,
|
|
tracking: {
|
|
action: TRACKING_ACTION_NAME,
|
|
label: 'pipeline_editor',
|
|
},
|
|
};
|
|
},
|
|
gitpodAction() {
|
|
if (!this.computedShowGitpodButton) return null;
|
|
|
|
const handleOptions = {
|
|
handle: () => {
|
|
visitUrl(this.gitpodUrl, true);
|
|
},
|
|
};
|
|
|
|
return {
|
|
key: KEY_GITPOD,
|
|
text: this.gitpodActionText,
|
|
secondaryText: this.$options.i18n.gitpodText,
|
|
tracking: {
|
|
action: TRACKING_ACTION_NAME,
|
|
label: 'gitpod',
|
|
},
|
|
...handleOptions,
|
|
};
|
|
},
|
|
mountForkModal() {
|
|
const { disableForkModal, showWebIdeButton, showEditButton } = this;
|
|
if (disableForkModal) return false;
|
|
|
|
return showWebIdeButton || showEditButton;
|
|
},
|
|
tooltipText() {
|
|
return this.disabled ? this.customTooltipText : '';
|
|
},
|
|
},
|
|
methods: {
|
|
showModal(dataKey) {
|
|
this[dataKey] = true;
|
|
},
|
|
executeAction(action) {
|
|
this.track(action.tracking.action, { label: action.tracking.label });
|
|
action.handle?.();
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="hasActions" :class="cssClasses">
|
|
<gl-disclosure-dropdown
|
|
v-gl-tooltip="tooltipText"
|
|
:variant="editButtonVariant"
|
|
:category="isBlob ? 'primary' : 'secondary'"
|
|
:toggle-text="$options.i18n.toggleText"
|
|
:disabled="disabled"
|
|
:aria-label="tooltipText"
|
|
data-testid="action-dropdown"
|
|
fluid-width
|
|
block
|
|
@shown="$emit('shown')"
|
|
@hidden="$emit('hidden')"
|
|
>
|
|
<slot name="before-actions"></slot>
|
|
<gl-disclosure-dropdown-group class="edit-dropdown-group-width">
|
|
<gl-disclosure-dropdown-item
|
|
v-for="action in actions"
|
|
:key="action.key"
|
|
:item="action"
|
|
:data-testid="`${action.key}-menu-item`"
|
|
@action="executeAction(action)"
|
|
>
|
|
<template #list-item>
|
|
<div class="gl-flex gl-flex-col">
|
|
<span class="gl-mb-2 gl-flex gl-items-center gl-justify-between">
|
|
<span data-testid="action-primary-text" class="gl-font-bold">{{
|
|
action.text
|
|
}}</span>
|
|
<kbd v-if="action.shortcut && !shortcutsDisabled" class="flat">{{
|
|
action.shortcut
|
|
}}</kbd>
|
|
</span>
|
|
<span data-testid="action-secondary-text" class="gl-text-sm gl-text-subtle">
|
|
{{ action.secondaryText }}
|
|
</span>
|
|
</div>
|
|
</template>
|
|
</gl-disclosure-dropdown-item>
|
|
</gl-disclosure-dropdown-group>
|
|
<slot name="after-actions"></slot>
|
|
</gl-disclosure-dropdown>
|
|
<confirm-fork-modal
|
|
v-if="mountForkModal"
|
|
v-model="showForkModal"
|
|
:modal-id="forkModalId"
|
|
:fork-path="forkPath"
|
|
/>
|
|
</div>
|
|
</template>
|