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:
Diffstat (limited to 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue')
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue200
1 files changed, 200 insertions, 0 deletions
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue
new file mode 100644
index 00000000000..aa1184ed314
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents_create_view.vue
@@ -0,0 +1,200 @@
+<script>
+import {
+ GlAlert,
+ GlTooltipDirective,
+ GlButton,
+ GlFormInput,
+ GlLink,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import produce from 'immer';
+import { createAlert } from '~/flash';
+import { __ } from '~/locale';
+import { workspaceLabelsQueries } from '../../../constants';
+import createLabelMutation from './graphql/create_label.mutation.graphql';
+import { LabelType } from './constants';
+
+const errorMessage = __('Error creating label.');
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlFormInput,
+ GlLink,
+ GlLoadingIcon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ fullPath: {
+ type: String,
+ required: true,
+ },
+ attrWorkspacePath: {
+ type: String,
+ required: true,
+ },
+ labelCreateType: {
+ type: String,
+ required: true,
+ },
+ workspaceType: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ labelTitle: '',
+ selectedColor: '',
+ labelCreateInProgress: false,
+ error: undefined,
+ };
+ },
+ computed: {
+ disableCreate() {
+ return !this.labelTitle.length || !this.selectedColor.length || this.labelCreateInProgress;
+ },
+ suggestedColors() {
+ const colorsMap = gon.suggested_label_colors;
+ return Object.keys(colorsMap).map((color) => ({ [color]: colorsMap[color] }));
+ },
+ mutationVariables() {
+ const attributePath = this.labelCreateType === LabelType.group ? 'groupPath' : 'projectPath';
+
+ return {
+ title: this.labelTitle,
+ color: this.selectedColor,
+ [attributePath]: this.attrWorkspacePath,
+ };
+ },
+ },
+ methods: {
+ getColorCode(color) {
+ return Object.keys(color).pop();
+ },
+ getColorName(color) {
+ return Object.values(color).pop();
+ },
+ handleColorClick(color) {
+ this.selectedColor = this.getColorCode(color);
+ },
+ updateLabelsInCache(store, label) {
+ const { query } = workspaceLabelsQueries[this.workspaceType];
+
+ const sourceData = store.readQuery({
+ query,
+ variables: { fullPath: this.fullPath, 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,
+ variables: { fullPath: this.fullPath, searchTerm: '' },
+ data,
+ });
+ },
+ async createLabel() {
+ this.labelCreateInProgress = true;
+ try {
+ const {
+ data: { labelCreate },
+ } = await this.$apollo.mutate({
+ mutation: createLabelMutation,
+ variables: this.mutationVariables,
+ update: (
+ store,
+ {
+ data: {
+ labelCreate: { label },
+ },
+ },
+ ) => {
+ if (label) {
+ this.updateLabelsInCache(store, label);
+ }
+ },
+ });
+ if (labelCreate.errors.length) {
+ [this.error] = labelCreate.errors;
+ } else {
+ this.$emit('hideCreateView');
+ }
+ } catch {
+ createAlert({ message: errorMessage });
+ }
+ this.labelCreateInProgress = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="labels-select-contents-create js-labels-create">
+ <div class="dropdown-input">
+ <gl-alert v-if="error" variant="danger" :dismissible="false" class="gl-mt-3">
+ {{ error }}
+ </gl-alert>
+ <gl-form-input
+ v-model.trim="labelTitle"
+ class="gl-mt-3"
+ :placeholder="__('Name new label')"
+ :autofocus="true"
+ data-testid="label-title-input"
+ />
+ </div>
+ <div class="dropdown-content gl-px-3">
+ <div class="suggest-colors suggest-colors-dropdown gl-mt-0! gl-mb-3! gl-mb-0">
+ <gl-link
+ v-for="(color, index) in suggestedColors"
+ :key="index"
+ v-gl-tooltip:tooltipcontainer
+ :style="{ backgroundColor: getColorCode(color) }"
+ :title="getColorName(color)"
+ @click.prevent="handleColorClick(color)"
+ />
+ </div>
+ <div class="color-input-container gl-display-flex">
+ <span
+ class="dropdown-label-color-preview gl-relative gl-display-inline-block"
+ data-testid="selected-color"
+ :style="{ backgroundColor: selectedColor }"
+ ></span>
+ <gl-form-input
+ v-model.trim="selectedColor"
+ class="gl-rounded-top-left-none gl-rounded-bottom-left-none gl-mb-2"
+ :placeholder="__('Use custom color #FF0000')"
+ data-testid="selected-color-text"
+ />
+ </div>
+ </div>
+ <div class="dropdown-actions gl-display-flex gl-justify-content-space-between gl-pt-3 gl-px-3">
+ <gl-button
+ :disabled="disableCreate"
+ category="primary"
+ variant="confirm"
+ class="gl-display-flex gl-align-items-center"
+ data-testid="create-button"
+ @click="createLabel"
+ >
+ <gl-loading-icon v-if="labelCreateInProgress" size="sm" :inline="true" class="mr-1" />
+ {{ __('Create') }}
+ </gl-button>
+ <gl-button
+ class="js-btn-cancel-create"
+ data-testid="cancel-button"
+ @click.stop="$emit('hideCreateView')"
+ >
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ </div>
+</template>