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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-10 15:10:18 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-10 15:10:18 +0300
commite838c62efb5d95fe76b5bbb6cba8b73c40eb2008 (patch)
tree6950ae1392a4c596e0885e7f79a8b69d6b008afb /app/assets/javascripts/labels
parent240609275dbc67cfd6eab5d5a55ab632db41a9ac (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.vue81
-rw-r--r--app/assets/javascripts/labels/components/promote_label_modal.vue113
-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.js16
-rw-r--r--app/assets/javascripts/labels/event_hub.js3
-rw-r--r--app/assets/javascripts/labels/index.js135
-rw-r--r--app/assets/javascripts/labels/init_labels.js19
-rw-r--r--app/assets/javascripts/labels/labels_select.js2
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 = {}) {