diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-10 15:10:18 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-10 15:10:18 +0300 |
commit | e838c62efb5d95fe76b5bbb6cba8b73c40eb2008 (patch) | |
tree | 6950ae1392a4c596e0885e7f79a8b69d6b008afb /app/assets/javascripts/labels | |
parent | 240609275dbc67cfd6eab5d5a55ab632db41a9ac (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/labels')
-rw-r--r-- | app/assets/javascripts/labels/components/delete_label_modal.vue | 81 | ||||
-rw-r--r-- | app/assets/javascripts/labels/components/promote_label_modal.vue | 113 | ||||
-rw-r--r-- | app/assets/javascripts/labels/create_label_dropdown.js (renamed from app/assets/javascripts/labels/create_label.js) | 0 | ||||
-rw-r--r-- | app/assets/javascripts/labels/delete_label_modal.js | 16 | ||||
-rw-r--r-- | app/assets/javascripts/labels/event_hub.js | 3 | ||||
-rw-r--r-- | app/assets/javascripts/labels/index.js | 135 | ||||
-rw-r--r-- | app/assets/javascripts/labels/init_labels.js | 19 | ||||
-rw-r--r-- | app/assets/javascripts/labels/labels_select.js | 2 |
8 files changed, 333 insertions, 36 deletions
diff --git a/app/assets/javascripts/labels/components/delete_label_modal.vue b/app/assets/javascripts/labels/components/delete_label_modal.vue new file mode 100644 index 00000000000..1ff0938d086 --- /dev/null +++ b/app/assets/javascripts/labels/components/delete_label_modal.vue @@ -0,0 +1,81 @@ +<script> +import { GlModal, GlSprintf, GlButton } from '@gitlab/ui'; +import { uniqueId } from 'lodash'; + +export default { + components: { + GlModal, + GlSprintf, + GlButton, + }, + props: { + selector: { + type: String, + required: true, + }, + }, + data() { + return { + labelName: '', + subjectName: '', + destroyPath: '', + modalId: uniqueId('modal-delete-label-'), + }; + }, + mounted() { + document.querySelectorAll(this.selector).forEach((button) => { + button.addEventListener('click', (e) => { + e.preventDefault(); + + const { labelName, subjectName, destroyPath } = button.dataset; + this.labelName = labelName; + this.subjectName = subjectName; + this.destroyPath = destroyPath; + this.openModal(); + }); + }); + }, + methods: { + openModal() { + this.$refs.modal.show(); + }, + closeModal() { + this.$refs.modal.hide(); + }, + }, +}; +</script> + +<template> + <gl-modal ref="modal" :modal-id="modalId"> + <template #modal-title> + <gl-sprintf :message="__('Delete label: %{labelName}')"> + <template #labelName> + {{ labelName }} + </template> + </gl-sprintf> + </template> + <gl-sprintf + :message=" + __( + `%{strongStart}${labelName}%{strongEnd} will be permanently deleted from ${subjectName}. This cannot be undone.`, + ) + " + > + <template #strong="{ content }"> + <strong>{{ content }}</strong> + </template> + </gl-sprintf> + <template #modal-footer> + <gl-button category="secondary" @click="closeModal">{{ __('Cancel') }}</gl-button> + <gl-button + category="primary" + variant="danger" + :href="destroyPath" + data-method="delete" + data-testid="delete-button" + >{{ __('Delete label') }}</gl-button + > + </template> + </gl-modal> +</template> diff --git a/app/assets/javascripts/labels/components/promote_label_modal.vue b/app/assets/javascripts/labels/components/promote_label_modal.vue new file mode 100644 index 00000000000..e708cd32fff --- /dev/null +++ b/app/assets/javascripts/labels/components/promote_label_modal.vue @@ -0,0 +1,113 @@ +<script> +import { GlSprintf, GlModal } from '@gitlab/ui'; +import createFlash from '~/flash'; +import axios from '~/lib/utils/axios_utils'; +import { visitUrl } from '~/lib/utils/url_utility'; +import { s__, __, sprintf } from '~/locale'; +import eventHub from '../event_hub'; + +export default { + primaryProps: { + text: s__('Labels|Promote Label'), + attributes: [{ variant: 'warning' }, { category: 'primary' }], + }, + cancelProps: { + text: __('Cancel'), + }, + components: { + GlModal, + GlSprintf, + }, + props: { + url: { + type: String, + required: true, + }, + labelTitle: { + type: String, + required: true, + }, + labelColor: { + type: String, + required: true, + }, + labelTextColor: { + type: String, + required: true, + }, + groupName: { + type: String, + required: true, + }, + }, + computed: { + text() { + return sprintf( + s__(`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. + Existing project labels with the same title will be merged. If a group label with the same title exists, + it will also be merged. This action cannot be reversed.`), + { + labelTitle: this.labelTitle, + groupName: this.groupName, + }, + ); + }, + }, + methods: { + onSubmit() { + eventHub.$emit('promoteLabelModal.requestStarted', this.url); + return axios + .post(this.url, { params: { format: 'json' } }) + .then((response) => { + eventHub.$emit('promoteLabelModal.requestFinished', { + labelUrl: this.url, + successful: true, + }); + visitUrl(response.data.url); + }) + .catch((error) => { + eventHub.$emit('promoteLabelModal.requestFinished', { + labelUrl: this.url, + successful: false, + }); + createFlash({ + message: error, + }); + }); + }, + }, +}; +</script> +<template> + <gl-modal + modal-id="promote-label-modal" + :action-primary="$options.primaryProps" + :action-cancel="$options.cancelProps" + @primary="onSubmit" + > + <template #modal-title> + <div class="modal-title-with-label"> + <gl-sprintf + :message=" + s__( + 'Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}', + ) + " + > + <template #labelTitle> + <span + class="label color-label" + :style="`background-color: ${labelColor}; color: ${labelTextColor};`" + > + {{ labelTitle }} + </span> + </template> + <template #span="{ content }" + ><span>{{ content }}</span></template + > + </gl-sprintf> + </div> + </template> + {{ text }} + </gl-modal> +</template> diff --git a/app/assets/javascripts/labels/create_label.js b/app/assets/javascripts/labels/create_label_dropdown.js index 8c166158a44..8c166158a44 100644 --- a/app/assets/javascripts/labels/create_label.js +++ b/app/assets/javascripts/labels/create_label_dropdown.js diff --git a/app/assets/javascripts/labels/delete_label_modal.js b/app/assets/javascripts/labels/delete_label_modal.js deleted file mode 100644 index cf7c9e7734f..00000000000 --- a/app/assets/javascripts/labels/delete_label_modal.js +++ /dev/null @@ -1,16 +0,0 @@ -import Vue from 'vue'; -import DeleteLabelModal from '~/vue_shared/components/delete_label_modal.vue'; - -const mountDeleteLabelModal = (optionalProps) => - new Vue({ - render(h) { - return h(DeleteLabelModal, { - props: { - selector: '.js-delete-label-modal-button', - ...optionalProps, - }, - }); - }, - }).$mount(); - -export default (optionalProps = {}) => mountDeleteLabelModal(optionalProps); diff --git a/app/assets/javascripts/labels/event_hub.js b/app/assets/javascripts/labels/event_hub.js new file mode 100644 index 00000000000..e31806ad199 --- /dev/null +++ b/app/assets/javascripts/labels/event_hub.js @@ -0,0 +1,3 @@ +import createEventHub from '~/helpers/event_hub_factory'; + +export default createEventHub(); diff --git a/app/assets/javascripts/labels/index.js b/app/assets/javascripts/labels/index.js new file mode 100644 index 00000000000..15706435e25 --- /dev/null +++ b/app/assets/javascripts/labels/index.js @@ -0,0 +1,135 @@ +import $ from 'jquery'; +import Vue from 'vue'; +import { BV_SHOW_MODAL } from '~/lib/utils/constants'; +import Translate from '~/vue_shared/translate'; +import DeleteLabelModal from './components/delete_label_modal.vue'; +import PromoteLabelModal from './components/promote_label_modal.vue'; +import eventHub from './event_hub'; +import GroupLabelSubscription from './group_label_subscription'; +import LabelManager from './label_manager'; +import ProjectLabelSubscription from './project_label_subscription'; + +export function initDeleteLabelModal(optionalProps = {}) { + new Vue({ + render(h) { + return h(DeleteLabelModal, { + props: { + selector: '.js-delete-label-modal-button', + ...optionalProps, + }, + }); + }, + }).$mount(); +} + +export function initLabels() { + if ($('.prioritized-labels').length) { + new LabelManager(); // eslint-disable-line no-new + } + $('.label-subscription').each((i, el) => { + const $el = $(el); + + if ($el.find('.dropdown-group-label').length) { + new GroupLabelSubscription($el); // eslint-disable-line no-new + } else { + new ProjectLabelSubscription($el); // eslint-disable-line no-new + } + }); +} + +export function initLabelIndex() { + Vue.use(Translate); + + initLabels(); + initDeleteLabelModal(); + + const onRequestFinished = ({ labelUrl, successful }) => { + const button = document.querySelector( + `.js-promote-project-label-button[data-url="${labelUrl}"]`, + ); + + if (!successful) { + button.removeAttribute('disabled'); + } + }; + + const onRequestStarted = (labelUrl) => { + const button = document.querySelector( + `.js-promote-project-label-button[data-url="${labelUrl}"]`, + ); + button.setAttribute('disabled', ''); + eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished); + }; + + const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button'); + + return new Vue({ + el: '#js-promote-label-modal', + data() { + return { + modalProps: { + labelTitle: '', + labelColor: '', + labelTextColor: '', + url: '', + groupName: '', + }, + }; + }, + mounted() { + eventHub.$on('promoteLabelModal.props', this.setModalProps); + eventHub.$emit('promoteLabelModal.mounted'); + + promoteLabelButtons.forEach((button) => { + button.removeAttribute('disabled'); + button.addEventListener('click', () => { + this.$root.$emit(BV_SHOW_MODAL, 'promote-label-modal'); + eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted); + + this.setModalProps({ + labelTitle: button.dataset.labelTitle, + labelColor: button.dataset.labelColor, + labelTextColor: button.dataset.labelTextColor, + url: button.dataset.url, + groupName: button.dataset.groupName, + }); + }); + }); + }, + beforeDestroy() { + eventHub.$off('promoteLabelModal.props', this.setModalProps); + }, + methods: { + setModalProps(modalProps) { + this.modalProps = modalProps; + }, + }, + render(createElement) { + return createElement(PromoteLabelModal, { + props: this.modalProps, + }); + }, + }); +} + +export function initAdminLabels() { + const pagination = document.querySelector('.labels .gl-pagination'); + const emptyState = document.querySelector('.labels .nothing-here-block.hidden'); + + function removeLabelSuccessCallback() { + this.closest('li').classList.add('gl-display-none!'); + + const labelsCount = document.querySelectorAll( + 'ul.manage-labels-list li:not(.gl-display-none\\!)', + ).length; + + // display the empty state if there are no more labels + if (labelsCount < 1 && !pagination && emptyState) { + emptyState.classList.remove('hidden'); + } + } + + document.querySelectorAll('.js-remove-label').forEach((row) => { + row.addEventListener('ajax:success', removeLabelSuccessCallback); + }); +} diff --git a/app/assets/javascripts/labels/init_labels.js b/app/assets/javascripts/labels/init_labels.js deleted file mode 100644 index 10bfbf7960c..00000000000 --- a/app/assets/javascripts/labels/init_labels.js +++ /dev/null @@ -1,19 +0,0 @@ -import $ from 'jquery'; -import GroupLabelSubscription from './group_label_subscription'; -import LabelManager from './label_manager'; -import ProjectLabelSubscription from './project_label_subscription'; - -export default () => { - if ($('.prioritized-labels').length) { - new LabelManager(); // eslint-disable-line no-new - } - $('.label-subscription').each((i, el) => { - const $el = $(el); - - if ($el.find('.dropdown-group-label').length) { - new GroupLabelSubscription($el); // eslint-disable-line no-new - } else { - new ProjectLabelSubscription($el); // eslint-disable-line no-new - } - }); -}; diff --git a/app/assets/javascripts/labels/labels_select.js b/app/assets/javascripts/labels/labels_select.js index 1219a115c89..ae0cf94b861 100644 --- a/app/assets/javascripts/labels/labels_select.js +++ b/app/assets/javascripts/labels/labels_select.js @@ -9,7 +9,7 @@ import { isScopedLabel } from '~/lib/utils/common_utils'; import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { sprintf, __ } from '~/locale'; -import CreateLabelDropdown from './create_label'; +import CreateLabelDropdown from './create_label_dropdown'; export default class LabelsSelect { constructor(els, options = {}) { |