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-16 15:15:41 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-16 15:15:41 +0300
commita32fd79d1e34ca4da1d5390c0aaf91d660e03fc8 (patch)
tree1fdbd979134478c9a2518a8a19a3404a7d1cc44c /app/assets/javascripts
parent884e3abdb08566b80afd73e9b0d5a7b6c5ac33bd (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_events_list.vue28
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_history_item.vue4
-rw-r--r--app/assets/javascripts/integrations/constants.js1
-rw-r--r--app/assets/javascripts/integrations/edit/components/confirmation_modal.vue9
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue48
-rw-r--r--app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue8
-rw-r--r--app/assets/javascripts/integrations/edit/index.js21
-rw-r--r--app/assets/javascripts/integrations/edit/store/actions.js1
-rw-r--r--app/assets/javascripts/integrations/edit/store/getters.js2
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutations.js3
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js45
-rw-r--r--app/assets/javascripts/issues/show/components/app.vue22
-rw-r--r--app/assets/javascripts/issues/show/components/delete_issue_modal.vue71
-rw-r--r--app/assets/javascripts/issues/show/components/edit_actions.vue53
-rw-r--r--app/assets/javascripts/issues/show/components/form.vue5
-rw-r--r--app/assets/javascripts/issues/show/components/header_actions.vue77
-rw-r--r--app/assets/javascripts/issues/show/incident.js2
-rw-r--r--app/assets/javascripts/issues/show/issue.js2
-rw-r--r--app/assets/javascripts/pages/admin/integrations/edit/index.js18
-rw-r--r--app/assets/javascripts/pages/groups/settings/integrations/edit/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/services/edit/index.js5
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue3
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue34
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue3
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue3
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql4
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql6
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql6
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql4
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js42
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql22
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js32
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue6
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue12
-rw-r--r--app/assets/javascripts/security_configuration/components/training_provider_list.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue45
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue55
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue8
40 files changed, 436 insertions, 317 deletions
diff --git a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
index 146b647cb46..6567ce203bc 100644
--- a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
+++ b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
@@ -1,5 +1,12 @@
<script>
-import { GlLoadingIcon, GlEmptyState, GlLink, GlIcon, GlAlert } from '@gitlab/ui';
+import {
+ GlLoadingIcon,
+ GlEmptyState,
+ GlLink,
+ GlIcon,
+ GlAlert,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { n__, s__, __ } from '~/locale';
import { formatDate, getDayDifference, isToday } from '~/lib/utils/datetime_utility';
@@ -16,10 +23,14 @@ export default {
GlIcon,
ActivityHistoryItem,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
i18n: {
emptyText: s__(
'ClusterAgents|See Agent activity updates such as tokens created or revoked and clusters connected or not connected.',
),
+ emptyTooltip: s__('ClusterAgents|What is GitLab Agent activity?'),
error: s__(
'ClusterAgents|An error occurred while retrieving GitLab Agent activity. Reload the page to try again.',
),
@@ -150,12 +161,15 @@ export default {
:svg-path="activityEmptyStateImage"
:svg-height="150"
>
- <template #description>
- <div>
- <span>{{ $options.i18n.emptyText }}</span>
-
- <gl-link :href="$options.emptyHelpLink"><gl-icon name="question" :size="14" /></gl-link>
- </div>
+ <template #description
+ >{{ $options.i18n.emptyText }}
+ <gl-link
+ v-gl-tooltip
+ :href="$options.emptyHelpLink"
+ :title="$options.i18n.emptyTooltip"
+ :aria-label="$options.i18n.emptyTooltip"
+ ><gl-icon name="question" :size="14"
+ /></gl-link>
</template>
</gl-empty-state>
</div>
diff --git a/app/assets/javascripts/clusters/agents/components/activity_history_item.vue b/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
index 39389c3b04b..7792d89a575 100644
--- a/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
+++ b/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
@@ -64,12 +64,12 @@ export default {
<p class="gl-mt-2 gl-mb-0 gl-pb-2" :class="bodyClass">
<gl-sprintf :message="eventDetails.body">
<template #userName>
- <strong>{{ eventDetails.user.name }}</strong>
+ <span class="gl-font-weight-bold">{{ eventDetails.user.name }}</span>
<gl-link :href="eventDetails.user.webUrl">@{{ eventDetails.user.username }}</gl-link>
</template>
<template #strong="{ content }">
- <strong> {{ content }} </strong>
+ <span class="gl-font-weight-bold"> {{ content }} </span>
</template>
</gl-sprintf>
<time-ago-tooltip :time="eventDetails.recordedAt" />
diff --git a/app/assets/javascripts/integrations/constants.js b/app/assets/javascripts/integrations/constants.js
index 177e3d6f9cc..84656bd41bb 100644
--- a/app/assets/javascripts/integrations/constants.js
+++ b/app/assets/javascripts/integrations/constants.js
@@ -1,6 +1,5 @@
import { s__, __ } from '~/locale';
-export const SAVE_INTEGRATION_EVENT = 'saveIntegration';
export const VALIDATE_INTEGRATION_FORM_EVENT = 'validateIntegrationForm';
export const integrationLevels = {
diff --git a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
index 89f7e3b7a89..bc6aa231a93 100644
--- a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
@@ -1,22 +1,17 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { mapGetters } from 'vuex';
import { __ } from '~/locale';
export default {
components: {
GlModal,
},
+
computed: {
- ...mapGetters(['isDisabled']),
primaryProps() {
return {
text: __('Save'),
- attributes: [
- { variant: 'confirm' },
- { category: 'primary' },
- { disabled: this.isDisabled },
- ],
+ attributes: [{ variant: 'confirm' }, { category: 'primary' }],
};
},
cancelProps() {
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index 60a6d13ce69..e570a468944 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -4,7 +4,6 @@ import * as Sentry from '@sentry/browser';
import { mapState, mapActions, mapGetters } from 'vuex';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
- SAVE_INTEGRATION_EVENT,
VALIDATE_INTEGRATION_FORM_EVENT,
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
@@ -54,12 +53,13 @@ export default {
data() {
return {
integrationActive: false,
- testingLoading: false,
+ isTesting: false,
+ isSaving: false,
};
},
computed: {
- ...mapGetters(['currentKey', 'propsSource', 'isDisabled']),
- ...mapState(['defaultState', 'customState', 'override', 'isSaving', 'isResetting']),
+ ...mapGetters(['currentKey', 'propsSource']),
+ ...mapState(['defaultState', 'customState', 'override', 'isResetting']),
isEditable() {
return this.propsSource.editable;
},
@@ -78,11 +78,8 @@ export default {
showTestButton() {
return this.propsSource.canTest;
},
- disableSaveButton() {
- return Boolean(this.isResetting || this.testingLoading);
- },
- disableResetButton() {
- return Boolean(this.isSaving || this.testingLoading);
+ disableButtons() {
+ return Boolean(this.isSaving || this.isResetting || this.isTesting);
},
},
mounted() {
@@ -90,21 +87,20 @@ export default {
this.form = document.querySelector(this.formSelector);
},
methods: {
- ...mapActions([
- 'setOverride',
- 'setIsSaving',
- 'setIsResetting',
- 'fetchResetIntegration',
- 'requestJiraIssueTypes',
- ]),
+ ...mapActions(['setOverride', 'fetchResetIntegration', 'requestJiraIssueTypes']),
onSaveClick() {
- this.setIsSaving(true);
+ this.isSaving = true;
+
+ if (this.integrationActive && !this.form.checkValidity()) {
+ this.isSaving = false;
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ return;
+ }
- const formValid = this.form.checkValidity() || this.integrationActive === false;
- eventHub.$emit(SAVE_INTEGRATION_EVENT, formValid);
+ this.form.submit();
},
onTestClick() {
- this.testingLoading = true;
+ this.isTesting = true;
if (!this.form.checkValidity()) {
eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
@@ -126,7 +122,7 @@ export default {
Sentry.captureException(error);
})
.finally(() => {
- this.testingLoading = false;
+ this.isTesting = false;
});
},
onResetClick() {
@@ -211,7 +207,7 @@ export default {
category="primary"
variant="confirm"
:loading="isSaving"
- :disabled="disableSaveButton"
+ :disabled="disableButtons"
data-qa-selector="save_changes_button"
>
{{ __('Save changes') }}
@@ -224,7 +220,7 @@ export default {
variant="confirm"
type="submit"
:loading="isSaving"
- :disabled="disableSaveButton"
+ :disabled="disableButtons"
data-testid="save-button"
data-qa-selector="save_changes_button"
@click.prevent="onSaveClick"
@@ -236,8 +232,8 @@ export default {
v-if="showTestButton"
category="secondary"
variant="confirm"
- :loading="testingLoading"
- :disabled="isDisabled"
+ :loading="isTesting"
+ :disabled="disableButtons"
data-testid="test-button"
@click.prevent="onTestClick"
>
@@ -250,7 +246,7 @@ export default {
category="secondary"
variant="confirm"
:loading="isResetting"
- :disabled="disableResetButton"
+ :disabled="disableButtons"
data-testid="reset-button"
>
{{ __('Reset') }}
diff --git a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
index 9472a3eeafe..5a445235219 100644
--- a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
@@ -1,6 +1,5 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { mapGetters } from 'vuex';
import { __ } from '~/locale';
@@ -9,15 +8,10 @@ export default {
GlModal,
},
computed: {
- ...mapGetters(['isDisabled']),
primaryProps() {
return {
text: __('Reset'),
- attributes: [
- { variant: 'warning' },
- { category: 'primary' },
- { disabled: this.isDisabled },
- ],
+ attributes: [{ variant: 'warning' }, { category: 'primary' }],
};
},
cancelProps() {
diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js
index 2e41d2914b7..9c9e3edbeb8 100644
--- a/app/assets/javascripts/integrations/edit/index.js
+++ b/app/assets/javascripts/integrations/edit/index.js
@@ -85,28 +85,31 @@ function parseDatasetToProps(data) {
};
}
-export default (el, defaultEl, formSelector) => {
- if (!el) {
+export default function initIntegrationSettingsForm(formSelector) {
+ const customSettingsEl = document.querySelector('.js-vue-integration-settings');
+ const defaultSettingsEl = document.querySelector('.js-vue-default-integration-settings');
+
+ if (!customSettingsEl) {
return null;
}
- const props = parseDatasetToProps(el.dataset);
+ const customSettingsProps = parseDatasetToProps(customSettingsEl.dataset);
const initialState = {
defaultState: null,
- customState: props,
+ customState: customSettingsProps,
};
- if (defaultEl) {
- initialState.defaultState = Object.freeze(parseDatasetToProps(defaultEl.dataset));
+ if (defaultSettingsEl) {
+ initialState.defaultState = Object.freeze(parseDatasetToProps(defaultSettingsEl.dataset));
}
// Here, we capture the "helpHtml", so we can pass it to the Vue component
// to position it where ever it wants.
// Because this node is a _child_ of `el`, it will be removed when the Vue component is mounted,
// so we don't need to manually remove it.
- const helpHtml = el.querySelector('.js-integration-help-html')?.innerHTML;
+ const helpHtml = customSettingsEl.querySelector('.js-integration-help-html')?.innerHTML;
return new Vue({
- el,
+ el: customSettingsEl,
store: createStore(initialState),
render(createElement) {
return createElement(IntegrationForm, {
@@ -117,4 +120,4 @@ export default (el, defaultEl, formSelector) => {
});
},
});
-};
+}
diff --git a/app/assets/javascripts/integrations/edit/store/actions.js b/app/assets/javascripts/integrations/edit/store/actions.js
index 6c1bfaa7858..97565a3a69c 100644
--- a/app/assets/javascripts/integrations/edit/store/actions.js
+++ b/app/assets/javascripts/integrations/edit/store/actions.js
@@ -10,7 +10,6 @@ import eventHub from '../event_hub';
import * as types from './mutation_types';
export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override);
-export const setIsSaving = ({ commit }, isSaving) => commit(types.SET_IS_SAVING, isSaving);
export const setIsResetting = ({ commit }, isResetting) =>
commit(types.SET_IS_RESETTING, isResetting);
diff --git a/app/assets/javascripts/integrations/edit/store/getters.js b/app/assets/javascripts/integrations/edit/store/getters.js
index 10d370de856..b79132128cc 100644
--- a/app/assets/javascripts/integrations/edit/store/getters.js
+++ b/app/assets/javascripts/integrations/edit/store/getters.js
@@ -1,7 +1,5 @@
export const isInheriting = (state) => (state.defaultState === null ? false : !state.override);
-export const isDisabled = (state) => state.isSaving || state.isResetting;
-
export const propsSource = (state, getters) =>
getters.isInheriting ? state.defaultState : state.customState;
diff --git a/app/assets/javascripts/integrations/edit/store/mutation_types.js b/app/assets/javascripts/integrations/edit/store/mutation_types.js
index dd4a79f6fe0..ddf6bef7554 100644
--- a/app/assets/javascripts/integrations/edit/store/mutation_types.js
+++ b/app/assets/javascripts/integrations/edit/store/mutation_types.js
@@ -1,5 +1,4 @@
export const SET_OVERRIDE = 'SET_OVERRIDE';
-export const SET_IS_SAVING = 'SET_IS_SAVING';
export const SET_IS_RESETTING = 'SET_IS_RESETTING';
export const SET_IS_LOADING_JIRA_ISSUE_TYPES = 'SET_IS_LOADING_JIRA_ISSUE_TYPES';
diff --git a/app/assets/javascripts/integrations/edit/store/mutations.js b/app/assets/javascripts/integrations/edit/store/mutations.js
index f76081e62f0..e7e312ce650 100644
--- a/app/assets/javascripts/integrations/edit/store/mutations.js
+++ b/app/assets/javascripts/integrations/edit/store/mutations.js
@@ -4,9 +4,6 @@ export default {
[types.SET_OVERRIDE](state, override) {
state.override = override;
},
- [types.SET_IS_SAVING](state, isSaving) {
- state.isSaving = isSaving;
- },
[types.SET_IS_RESETTING](state, isResetting) {
state.isResetting = isResetting;
},
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
deleted file mode 100644
index 193bc1c4e9b..00000000000
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { delay } from 'lodash';
-import initForm from './edit';
-import eventHub from './edit/event_hub';
-import { SAVE_INTEGRATION_EVENT, VALIDATE_INTEGRATION_FORM_EVENT } from './constants';
-
-export default class IntegrationSettingsForm {
- constructor(formSelector) {
- this.formSelector = formSelector;
- this.$form = document.querySelector(formSelector);
-
- this.vue = null;
-
- // Form Metadata
- this.testEndPoint = this.$form.dataset.testUrl;
- }
-
- init() {
- // Init Vue component
- this.vue = initForm(
- document.querySelector('.js-vue-integration-settings'),
- document.querySelector('.js-vue-default-integration-settings'),
- this.formSelector,
- );
- eventHub.$on(SAVE_INTEGRATION_EVENT, (formValid) => {
- this.saveIntegration(formValid);
- });
- }
-
- saveIntegration(formValid) {
- // Save Service if not active and check the following if active;
- // 1) If form contents are valid
- // 2) If this service can be saved
- // If both conditions are true, we override form submission
- // and save the service using provided configuration.
-
- if (formValid) {
- delay(() => {
- this.$form.submit();
- }, 100);
- } else {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
- this.vue.$store.dispatch('setIsSaving', false);
- }
- }
-}
diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue
index 13e8943d655..eeaf865a35f 100644
--- a/app/assets/javascripts/issues/show/components/app.vue
+++ b/app/assets/javascripts/issues/show/components/app.vue
@@ -289,13 +289,11 @@ export default {
window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
- eventHub.$on('delete.issuable', this.deleteIssuable);
eventHub.$on('update.issuable', this.updateIssuable);
eventHub.$on('close.form', this.closeForm);
eventHub.$on('open.form', this.openForm);
},
beforeDestroy() {
- eventHub.$off('delete.issuable', this.deleteIssuable);
eventHub.$off('update.issuable', this.updateIssuable);
eventHub.$off('close.form', this.closeForm);
eventHub.$off('open.form', this.openForm);
@@ -418,25 +416,6 @@ export default {
});
},
- deleteIssuable(payload) {
- return this.service
- .deleteIssuable(payload)
- .then((res) => res.data)
- .then((data) => {
- // Stop the poll so we don't get 404's with the issuable not existing
- this.poll.stop();
-
- visitUrl(data.web_url);
- })
- .catch(() => {
- createFlash({
- message: sprintf(__('Error deleting %{issuableType}'), {
- issuableType: this.issuableType,
- }),
- });
- });
- },
-
hideStickyHeader() {
this.isStickyHeaderShowing = false;
},
@@ -475,6 +454,7 @@ export default {
<div>
<div v-if="canUpdate && showForm">
<form-component
+ :endpoint="endpoint"
:form-state="formState"
:initial-description-text="initialDescriptionText"
:can-destroy="canDestroy"
diff --git a/app/assets/javascripts/issues/show/components/delete_issue_modal.vue b/app/assets/javascripts/issues/show/components/delete_issue_modal.vue
new file mode 100644
index 00000000000..26862346b86
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/delete_issue_modal.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { __, sprintf } from '~/locale';
+
+export default {
+ actionCancel: { text: __('Cancel') },
+ csrf,
+ components: {
+ GlModal,
+ },
+ props: {
+ issuePath: {
+ type: String,
+ required: true,
+ },
+ issueType: {
+ type: String,
+ required: true,
+ },
+ modalId: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ actionPrimary() {
+ return {
+ attributes: { variant: 'danger' },
+ text: this.title,
+ };
+ },
+ bodyText() {
+ return this.issueType.toLowerCase() === 'epic'
+ ? __('Delete this epic and all descendants?')
+ : sprintf(__('%{issuableType} will be removed! Are you sure?'), {
+ issuableType: capitalizeFirstCharacter(this.issueType),
+ });
+ },
+ },
+ methods: {
+ submitForm() {
+ this.$emit('delete');
+ this.$refs.form.submit();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ :action-cancel="$options.actionCancel"
+ :action-primary="actionPrimary"
+ :modal-id="modalId"
+ size="sm"
+ :title="title"
+ @primary="submitForm"
+ >
+ <form ref="form" :action="issuePath" method="post">
+ <input type="hidden" name="_method" value="delete" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+ <input type="hidden" name="destroy_confirm" value="true" />
+ {{ bodyText }}
+ </form>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/edit_actions.vue b/app/assets/javascripts/issues/show/components/edit_actions.vue
index 5b7d232fde7..4daf6f2b61b 100644
--- a/app/assets/javascripts/issues/show/components/edit_actions.vue
+++ b/app/assets/javascripts/issues/show/components/edit_actions.vue
@@ -1,10 +1,12 @@
<script>
-import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
+import { GlButton, GlModalDirective } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { __, sprintf } from '~/locale';
+import Tracking from '~/tracking';
import eventHub from '../event_hub';
import updateMixin from '../mixins/update';
import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
+import DeleteIssueModal from './delete_issue_modal.vue';
const issuableTypes = {
issue: __('Issue'),
@@ -12,20 +14,26 @@ const issuableTypes = {
incident: __('Incident'),
};
+const trackingMixin = Tracking.mixin({ label: 'delete_issue' });
+
export default {
components: {
+ DeleteIssueModal,
GlButton,
- GlModal,
},
directives: {
GlModal: GlModalDirective,
},
- mixins: [updateMixin],
+ mixins: [trackingMixin, updateMixin],
props: {
canDestroy: {
type: Boolean,
required: true,
},
+ endpoint: {
+ required: true,
+ type: String,
+ },
formState: {
type: Object,
required: true,
@@ -65,27 +73,9 @@ export default {
issuableType: this.typeToShow.toLowerCase(),
});
},
- deleteIssuableModalText() {
- return this.issuableType === 'epic'
- ? __('Delete this epic and all descendants?')
- : sprintf(__('%{issuableType} will be removed! Are you sure?'), {
- issuableType: this.typeToShow,
- });
- },
isSubmitEnabled() {
return this.formState.title.trim() !== '';
},
- modalActionProps() {
- return {
- primary: {
- text: this.deleteIssuableButtonText,
- attributes: [{ variant: 'danger' }, { loading: this.deleteLoading }],
- },
- cancel: {
- text: __('Cancel'),
- },
- };
- },
shouldShowDeleteButton() {
return this.canDestroy && this.showDeleteButton;
},
@@ -101,7 +91,7 @@ export default {
},
deleteIssuable() {
this.deleteLoading = true;
- eventHub.$emit('delete.issuable', { destroy_confirm: true });
+ eventHub.$emit('delete.issuable');
},
},
};
@@ -135,22 +125,17 @@ export default {
variant="danger"
class="qa-delete-button"
data-testid="issuable-delete-button"
+ @click="track('click_button')"
>
{{ deleteIssuableButtonText }}
</gl-button>
- <gl-modal
- ref="removeModal"
+ <delete-issue-modal
+ :issue-path="endpoint"
+ :issue-type="typeToShow"
:modal-id="modalId"
- size="sm"
- :action-primary="modalActionProps.primary"
- :action-cancel="modalActionProps.cancel"
- @primary="deleteIssuable"
- >
- <template #modal-title>{{ deleteIssuableButtonText }}</template>
- <div>
- <p class="gl-mb-1">{{ deleteIssuableModalText }}</p>
- </div>
- </gl-modal>
+ :title="deleteIssuableButtonText"
+ @delete="deleteIssuable"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/issues/show/components/form.vue b/app/assets/javascripts/issues/show/components/form.vue
index 783595028d5..6447ec85b4e 100644
--- a/app/assets/javascripts/issues/show/components/form.vue
+++ b/app/assets/javascripts/issues/show/components/form.vue
@@ -26,6 +26,10 @@ export default {
type: Boolean,
required: true,
},
+ endpoint: {
+ type: String,
+ required: true,
+ },
formState: {
type: Object,
required: true,
@@ -213,6 +217,7 @@ export default {
:enable-autocomplete="enableAutocomplete"
/>
<edit-actions
+ :endpoint="endpoint"
:form-state="formState"
:can-destroy="canDestroy"
:show-delete-button="showDeleteButton"
diff --git a/app/assets/javascripts/issues/show/components/header_actions.vue b/app/assets/javascripts/issues/show/components/header_actions.vue
index 75a5a4af949..700ef92a0f3 100644
--- a/app/assets/javascripts/issues/show/components/header_actions.vue
+++ b/app/assets/javascripts/issues/show/components/header_actions.vue
@@ -1,5 +1,13 @@
<script>
-import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlLink,
+ GlModal,
+ GlModalDirective,
+} from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import createFlash, { FLASH_TYPES } from '~/flash';
import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
@@ -10,23 +18,21 @@ import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale';
import eventHub from '~/notes/event_hub';
+import Tracking from '~/tracking';
import promoteToEpicMutation from '../queries/promote_to_epic.mutation.graphql';
import updateIssueMutation from '../queries/update_issue.mutation.graphql';
+import DeleteIssueModal from './delete_issue_modal.vue';
+
+const trackingMixin = Tracking.mixin({ label: 'delete_issue' });
export default {
- components: {
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlLink,
- GlModal,
- },
actionCancel: {
text: __('Cancel'),
},
actionPrimary: {
text: __('Yes, close issue'),
},
+ deleteModalId: 'delete-modal-id',
i18n: {
promoteErrorMessage: __(
'Something went wrong while promoting the issue to an epic. Please try again.',
@@ -35,10 +41,26 @@ export default {
'The issue was successfully promoted to an epic. Redirecting to epic...',
),
},
+ components: {
+ DeleteIssueModal,
+ GlButton,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlLink,
+ GlModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ mixins: [trackingMixin],
inject: {
canCreateIssue: {
default: false,
},
+ canDestroyIssue: {
+ default: false,
+ },
canPromoteToEpic: {
default: false,
},
@@ -57,6 +79,9 @@ export default {
isIssueAuthor: {
default: false,
},
+ issuePath: {
+ default: '',
+ },
issueType: {
default: IssuableType.Issue,
},
@@ -92,6 +117,9 @@ export default {
? sprintf(__('Reopen %{issueType}'), { issueType: this.issueTypeText })
: sprintf(__('Close %{issueType}'), { issueType: this.issueTypeText });
},
+ deleteButtonText() {
+ return sprintf(__('Delete %{issuableType}'), { issuableType: this.issueTypeText });
+ },
qaSelector() {
return this.isClosed ? 'reopen_issue_button' : 'close_issue_button';
},
@@ -141,8 +169,7 @@ export default {
})
.then(({ data }) => {
if (data.updateIssue.errors.length) {
- createFlash({ message: data.updateIssue.errors.join('. ') });
- return;
+ throw new Error();
}
const payload = {
@@ -175,8 +202,7 @@ export default {
})
.then(({ data }) => {
if (data.promoteToEpic.errors.length) {
- createFlash({ message: data.promoteToEpic.errors.join('; ') });
- return;
+ throw new Error();
}
createFlash({
@@ -228,6 +254,16 @@ export default {
>
{{ __('Submit as spam') }}
</gl-dropdown-item>
+ <template v-if="canDestroyIssue">
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ v-gl-modal="$options.deleteModalId"
+ variant="danger"
+ @click="track('click_dropdown')"
+ >
+ {{ deleteButtonText }}
+ </gl-dropdown-item>
+ </template>
</gl-dropdown>
<gl-button
@@ -271,6 +307,16 @@ export default {
>
{{ __('Submit as spam') }}
</gl-dropdown-item>
+ <template v-if="canDestroyIssue">
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ v-gl-modal="$options.deleteModalId"
+ variant="danger"
+ @click="track('click_dropdown')"
+ >
+ {{ deleteButtonText }}
+ </gl-dropdown-item>
+ </template>
</gl-dropdown>
<gl-modal
@@ -288,5 +334,12 @@ export default {
</li>
</ul>
</gl-modal>
+
+ <delete-issue-modal
+ :issue-path="issuePath"
+ :issue-type="issueType"
+ :modal-id="$options.deleteModalId"
+ :title="deleteButtonText"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/issues/show/incident.js b/app/assets/javascripts/issues/show/incident.js
index 3aff2d9c54a..a260c31e1da 100644
--- a/app/assets/javascripts/issues/show/incident.js
+++ b/app/assets/javascripts/issues/show/incident.js
@@ -81,12 +81,14 @@ export function initIncidentHeaderActions(store) {
store,
provide: {
canCreateIssue: parseBoolean(el.dataset.canCreateIncident),
+ canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
canReportSpam: parseBoolean(el.dataset.canReportSpam),
canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
iid: el.dataset.iid,
isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
+ issuePath: el.dataset.issuePath,
issueType: el.dataset.issueType,
newIssuePath: el.dataset.newIssuePath,
projectPath: el.dataset.projectPath,
diff --git a/app/assets/javascripts/issues/show/issue.js b/app/assets/javascripts/issues/show/issue.js
index b3deb7571ee..60e90934af8 100644
--- a/app/assets/javascripts/issues/show/issue.js
+++ b/app/assets/javascripts/issues/show/issue.js
@@ -66,12 +66,14 @@ export function initIssueHeaderActions(store) {
store,
provide: {
canCreateIssue: parseBoolean(el.dataset.canCreateIssue),
+ canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
canReportSpam: parseBoolean(el.dataset.canReportSpam),
canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
iid: el.dataset.iid,
isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
+ issuePath: el.dataset.issuePath,
issueType: el.dataset.issueType,
newIssuePath: el.dataset.newIssuePath,
projectPath: el.dataset.projectPath,
diff --git a/app/assets/javascripts/pages/admin/integrations/edit/index.js b/app/assets/javascripts/pages/admin/integrations/edit/index.js
index 8002fa8bf78..8485b460261 100644
--- a/app/assets/javascripts/pages/admin/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/admin/integrations/edit/index.js
@@ -1,15 +1,11 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initIntegrationSettingsForm from '~/integrations/edit';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-function initIntegrations() {
- const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
- const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- integrationSettingsForm.init();
+initIntegrationSettingsForm('.js-integration-settings-form');
- if (prometheusSettingsWrapper) {
- const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
- prometheusMetrics.loadActiveMetrics();
- }
+const prometheusSettingsSelector = '.js-prometheus-metrics-monitoring';
+const prometheusSettingsWrapper = document.querySelector(prometheusSettingsSelector);
+if (prometheusSettingsWrapper) {
+ const prometheusMetrics = new PrometheusMetrics(prometheusSettingsSelector);
+ prometheusMetrics.loadActiveMetrics();
}
-
-initIntegrations();
diff --git a/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js b/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
index a8698e10c57..8485b460261 100644
--- a/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
@@ -1,11 +1,11 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initIntegrationSettingsForm from '~/integrations/edit';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
-const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
-integrationSettingsForm.init();
+initIntegrationSettingsForm('.js-integration-settings-form');
+const prometheusSettingsSelector = '.js-prometheus-metrics-monitoring';
+const prometheusSettingsWrapper = document.querySelector(prometheusSettingsSelector);
if (prometheusSettingsWrapper) {
- const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
+ const prometheusMetrics = new PrometheusMetrics(prometheusSettingsSelector);
prometheusMetrics.loadActiveMetrics();
}
diff --git a/app/assets/javascripts/pages/projects/services/edit/index.js b/app/assets/javascripts/pages/projects/services/edit/index.js
index 03ffc323fc0..a2b18d86240 100644
--- a/app/assets/javascripts/pages/projects/services/edit/index.js
+++ b/app/assets/javascripts/pages/projects/services/edit/index.js
@@ -1,9 +1,8 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initIntegrationSettingsForm from '~/integrations/edit';
import PrometheusAlerts from '~/prometheus_alerts';
import CustomMetrics from '~/prometheus_metrics/custom_metrics';
-const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
-integrationSettingsForm.init();
+initIntegrationSettingsForm('.js-integration-settings-form');
const prometheusSettingsSelector = '.js-prometheus-metrics-monitoring';
const prometheusSettingsWrapper = document.querySelector(prometheusSettingsSelector);
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
index 0d28dd4e461..54c9688d88f 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
@@ -60,6 +60,9 @@ export default {
apollo: {
currentBranch: {
query: getCurrentBranch,
+ update(data) {
+ return data.workBranches.current.name;
+ },
},
},
computed: {
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
index 7ac7bffc833..4f79a81d539 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -20,8 +20,8 @@ import {
} from '~/pipeline_editor/constants';
import updateCurrentBranchMutation from '~/pipeline_editor/graphql/mutations/client/update_current_branch.mutation.graphql';
import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.query.graphql';
-import getCurrentBranchQuery from '~/pipeline_editor/graphql/queries/client/current_branch.query.graphql';
-import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql';
+import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.query.graphql';
+import getLastCommitBranch from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql';
export default {
i18n: {
@@ -61,8 +61,8 @@ export default {
},
data() {
return {
- branchSelected: null,
availableBranches: [],
+ branchSelected: null,
filteredBranches: [],
isSearchingBranches: false,
pageLimit: this.paginationLimit,
@@ -93,15 +93,25 @@ export default {
},
},
currentBranch: {
- query: getCurrentBranchQuery,
+ query: getCurrentBranch,
+ update(data) {
+ return data.workBranches.current.name;
+ },
},
lastCommitBranch: {
- query: getLastCommitBranchQuery,
- result({ data: { lastCommitBranch } }) {
- if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) {
- return;
+ query: getLastCommitBranch,
+ update(data) {
+ return data.workBranches.lastCommit.name;
+ },
+ result({ data }) {
+ if (data) {
+ const { name: lastCommitBranch } = data.workBranches.lastCommit;
+ if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) {
+ return;
+ }
+
+ this.availableBranches.unshift(lastCommitBranch);
}
- this.availableBranches.unshift(lastCommitBranch);
},
},
},
@@ -109,12 +119,12 @@ export default {
branches() {
return this.searchTerm.length > 0 ? this.filteredBranches : this.availableBranches;
},
- isBranchesLoading() {
- return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
- },
enableBranchSwitcher() {
return this.branches.length > 0 || this.searchTerm.length > 0;
},
+ isBranchesLoading() {
+ return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
+ },
},
watch: {
shouldLoadNewBranch(flag) {
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
index 7d042e02052..16ad648afca 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
@@ -48,6 +48,9 @@ export default {
apollo: {
pipelineEtag: {
query: getPipelineEtag,
+ update(data) {
+ return data.etags.pipeline;
+ },
},
pipeline: {
context() {
diff --git a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
index 798e337b493..833d784f940 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
@@ -43,6 +43,9 @@ export default {
apollo: {
appStatus: {
query: getAppStatus,
+ update(data) {
+ return data.app.status;
+ },
},
},
computed: {
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
index bd4f8d6ebc3..3f50a1225d8 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -91,6 +91,9 @@ export default {
apollo: {
appStatus: {
query: getAppStatus,
+ update(data) {
+ return data.app.status;
+ },
},
},
computed: {
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql
index 938f36c7d5c..0df8cafa3cb 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql
@@ -1,3 +1,5 @@
query getAppStatus {
- appStatus @client
+ app @client {
+ status
+ }
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql
index acd46013f5b..1f4f9d26f24 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql
@@ -1,3 +1,7 @@
query getCurrentBranch {
- currentBranch @client
+ workBranches @client {
+ current {
+ name
+ }
+ }
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
index e8a32d728d5..a83129759de 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
@@ -1,3 +1,7 @@
query getLastCommitBranchQuery {
- lastCommitBranch @client
+ workBranches @client {
+ lastCommit {
+ name
+ }
+ }
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql
index b9946a9e233..8df6e74a5d9 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql
@@ -1,3 +1,5 @@
query getPipelineEtag {
- pipelineEtag @client
+ etags @client {
+ pipeline
+ }
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index bb1f5a863cd..fa1c70c1994 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -1,7 +1,7 @@
import axios from '~/lib/utils/axios_utils';
import getAppStatus from './queries/client/app_status.query.graphql';
-import getCurrentBranchQuery from './queries/client/current_branch.query.graphql';
-import getLastCommitBranchQuery from './queries/client/last_commit_branch.query.graphql';
+import getCurrentBranch from './queries/client/current_branch.query.graphql';
+import getLastCommitBranch from './queries/client/last_commit_branch.query.graphql';
import getPipelineEtag from './queries/client/pipeline_etag.query.graphql';
export const resolvers = {
@@ -35,25 +35,51 @@ export const resolvers = {
updateAppStatus: (_, { appStatus }, { cache }) => {
cache.writeQuery({
query: getAppStatus,
- data: { appStatus },
+ data: {
+ app: {
+ __typename: 'PipelineEditorApp',
+ status: appStatus,
+ },
+ },
});
},
updateCurrentBranch: (_, { currentBranch }, { cache }) => {
cache.writeQuery({
- query: getCurrentBranchQuery,
- data: { currentBranch },
+ query: getCurrentBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ current: {
+ __typename: 'WorkBranch',
+ name: currentBranch,
+ },
+ },
+ },
});
},
updateLastCommitBranch: (_, { lastCommitBranch }, { cache }) => {
cache.writeQuery({
- query: getLastCommitBranchQuery,
- data: { lastCommitBranch },
+ query: getLastCommitBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ lastCommit: {
+ __typename: 'WorkBranch',
+ name: lastCommitBranch,
+ },
+ },
+ },
});
},
updatePipelineEtag: (_, { pipelineEtag }, { cache }) => {
cache.writeQuery({
query: getPipelineEtag,
- data: { pipelineEtag },
+ data: {
+ etags: {
+ __typename: 'EtagValues',
+ pipeline: pipelineEtag,
+ },
+ },
});
},
},
diff --git a/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql b/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
index f4f65262158..508ff22c46e 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
@@ -1,7 +1,23 @@
-type BlobContent {
- rawData: String!
+type PipelineEditorApp {
+ status: String!
+}
+
+type BranchList {
+ current: WorkBranch!
+ lastCommit: WorkBranch!
+}
+
+type EtagValues {
+ pipeline: String!
+}
+
+type WorkBranch {
+ name: String!
+ commit: String
}
extend type Query {
- blobContent: BlobContent
+ app: PipelineEditorApp
+ etags: EtagValues
+ workBranches: BranchList
}
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 299f593a19e..ee93e327b76 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -7,7 +7,7 @@ import { EDITOR_APP_STATUS_LOADING } from './constants';
import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants';
import getCurrentBranch from './graphql/queries/client/current_branch.query.graphql';
import getAppStatus from './graphql/queries/client/app_status.query.graphql';
-import getLastCommitBranchQuery from './graphql/queries/client/last_commit_branch.query.graphql';
+import getLastCommitBranch from './graphql/queries/client/last_commit_branch.query.graphql';
import getPipelineEtag from './graphql/queries/client/pipeline_etag.query.graphql';
import { resolvers } from './graphql/resolvers';
import typeDefs from './graphql/typedefs.graphql';
@@ -68,28 +68,46 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
cache.writeQuery({
query: getAppStatus,
data: {
- appStatus: EDITOR_APP_STATUS_LOADING,
+ app: {
+ __typename: 'PipelineEditorApp',
+ status: EDITOR_APP_STATUS_LOADING,
+ },
},
});
cache.writeQuery({
query: getCurrentBranch,
data: {
- currentBranch: initialBranchName || defaultBranch,
+ workBranches: {
+ __typename: 'BranchList',
+ current: {
+ __typename: 'WorkBranch',
+ name: initialBranchName || defaultBranch,
+ },
+ },
},
});
cache.writeQuery({
- query: getPipelineEtag,
+ query: getLastCommitBranch,
data: {
- pipelineEtag,
+ workBranches: {
+ __typename: 'BranchList',
+ lastCommit: {
+ __typename: 'WorkBranch',
+ name: '',
+ },
+ },
},
});
cache.writeQuery({
- query: getLastCommitBranchQuery,
+ query: getPipelineEtag,
data: {
- lastCommitBranch: '',
+ etags: {
+ __typename: 'EtagValues',
+ pipeline: pipelineEtag,
+ },
},
});
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 0c922979b14..e397054f06a 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -160,6 +160,9 @@ export default {
},
appStatus: {
query: getAppStatus,
+ update(data) {
+ return data.app.status;
+ },
},
commitSha: {
query: getLatestCommitShaQuery,
@@ -184,6 +187,9 @@ export default {
},
currentBranch: {
query: getCurrentBranch,
+ update(data) {
+ return data.workBranches.current.name;
+ },
},
starterTemplate: {
query: getTemplate,
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index a71097bb501..75d2b324623 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -4,7 +4,6 @@ import { __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
-import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue';
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from './constants';
@@ -88,7 +87,6 @@ export default {
return {
autoDevopsEnabledAlertDismissedProjects: [],
errorMessage: '',
- securityTrainingProviders: [],
};
},
computed: {
@@ -110,11 +108,6 @@ export default {
);
},
},
- apollo: {
- securityTrainingProviders: {
- query: securityTrainingProvidersQuery,
- },
- },
methods: {
dismissAutoDevopsEnabledAlert() {
const dismissedProjects = new Set(this.autoDevopsEnabledAlertDismissedProjects);
@@ -251,10 +244,7 @@ export default {
>
<section-layout :heading="$options.i18n.securityTraining">
<template #features>
- <training-provider-list
- :loading="$apollo.queries.securityTrainingProviders.loading"
- :providers="securityTrainingProviders"
- />
+ <training-provider-list />
</template>
</section-layout>
</gl-tab>
diff --git a/app/assets/javascripts/security_configuration/components/training_provider_list.vue b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
index 4310ee3615e..509377a63e8 100644
--- a/app/assets/javascripts/security_configuration/components/training_provider_list.vue
+++ b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
@@ -1,5 +1,6 @@
<script>
import { GlCard, GlToggle, GlLink, GlSkeletonLoader } from '@gitlab/ui';
+import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
export default {
components: {
@@ -8,15 +9,19 @@ export default {
GlLink,
GlSkeletonLoader,
},
- props: {
- providers: {
- type: Array,
- required: true,
+ apollo: {
+ securityTrainingProviders: {
+ query: securityTrainingProvidersQuery,
},
- loading: {
- type: Boolean,
- required: false,
- default: false,
+ },
+ data() {
+ return {
+ securityTrainingProviders: [],
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.securityTrainingProviders.loading;
},
},
};
@@ -24,7 +29,7 @@ export default {
<template>
<div
- v-if="loading"
+ v-if="isLoading"
class="gl-bg-white gl-py-6 gl-rounded-base gl-border-1 gl-border-solid gl-border-gray-100"
>
<gl-skeleton-loader :width="350" :height="44">
@@ -34,7 +39,11 @@ export default {
</gl-skeleton-loader>
</div>
<ul v-else class="gl-list-style-none gl-m-0 gl-p-0">
- <li v-for="{ id, isEnabled, name, description, url } in providers" :key="id" class="gl-mb-6">
+ <li
+ v-for="{ id, isEnabled, name, description, url } in securityTrainingProviders"
+ :key="id"
+ class="gl-mb-6"
+ >
<gl-card>
<div class="gl-display-flex">
<gl-toggle :value="isEnabled" :label="__('Training mode')" label-position="hidden" />
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
index aed5bc303ee..57ee816c4c7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
@@ -1,10 +1,15 @@
<script>
-import { GlLabel } from '@gitlab/ui';
+import { GlIcon, GlLabel, GlTooltipDirective } from '@gitlab/ui';
import { sortBy } from 'lodash';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import { s__, sprintf } from '~/locale';
export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
components: {
+ GlIcon,
GlLabel,
},
inject: ['allowScopedLabels'],
@@ -35,6 +40,23 @@ export default {
sortedSelectedLabels() {
return sortBy(this.selectedLabels, (label) => (isScopedLabel(label) ? 0 : 1));
},
+ labelsList() {
+ const labelsString = this.selectedLabels.length
+ ? this.selectedLabels
+ .slice(0, 5)
+ .map((label) => label.title)
+ .join(', ')
+ : s__('LabelSelect|Labels');
+
+ if (this.selectedLabels.length > 5) {
+ return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
+ labelsString,
+ remainingLabelCount: this.selectedLabels.length - 5,
+ });
+ }
+
+ return labelsString;
+ },
},
methods: {
labelFilterUrl(label) {
@@ -48,6 +70,9 @@ export default {
removeLabel(labelId) {
this.$emit('onLabelRemove', labelId);
},
+ handleCollapsedClick() {
+ this.$emit('onCollapsedValueClick');
+ },
},
};
</script>
@@ -57,16 +82,30 @@ export default {
:class="{
'has-labels': selectedLabels.length,
}"
- class="hide-collapsed value issuable-show-labels js-value"
+ class="value issuable-show-labels js-value"
data-testid="value-wrapper"
>
- <span v-if="!selectedLabels.length" class="text-secondary" data-testid="empty-placeholder">
+ <div
+ v-gl-tooltip.left.viewport
+ :title="labelsList"
+ class="sidebar-collapsed-icon"
+ @click="handleCollapsedClick"
+ >
+ <gl-icon name="labels" />
+ <span class="gl-font-base gl-line-height-24">{{ selectedLabels.length }}</span>
+ </div>
+ <span
+ v-if="!selectedLabels.length"
+ class="text-secondary hide-collapsed"
+ data-testid="empty-placeholder"
+ >
<slot></slot>
</span>
<template v-else>
<gl-label
v-for="label in sortedSelectedLabels"
:key="label.id"
+ class="hide-collapsed"
data-qa-selector="selected_label_content"
:data-qa-label-name="label.title"
:title="label.title"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue
deleted file mode 100644
index 122250d1ce7..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
-
-export default {
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: {
- GlIcon,
- },
- props: {
- labels: {
- type: Array,
- required: true,
- },
- },
- computed: {
- labelsList() {
- const labelsString = this.labels.length
- ? this.labels
- .slice(0, 5)
- .map((label) => label.title)
- .join(', ')
- : s__('LabelSelect|Labels');
-
- if (this.labels.length > 5) {
- return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
- labelsString,
- remainingLabelCount: this.labels.length - 5,
- });
- }
-
- return labelsString;
- },
- },
- methods: {
- handleClick() {
- this.$emit('onValueClick');
- },
- },
-};
-</script>
-
-<template>
- <div
- v-gl-tooltip.left.viewport
- :title="labelsList"
- class="sidebar-collapsed-icon"
- @click="handleClick"
- >
- <gl-icon name="labels" />
- <span>{{ labels.length }}</span>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
index 2ef0d4fd9e6..3adda69b892 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
@@ -9,7 +9,6 @@ import { issuableLabelsQueries } from '~/sidebar/constants';
import { DEBOUNCE_DROPDOWN_DELAY, DropdownVariant } from './constants';
import DropdownContents from './dropdown_contents.vue';
import DropdownValue from './dropdown_value.vue';
-import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
import {
isDropdownVariantSidebar,
isDropdownVariantStandalone,
@@ -20,7 +19,6 @@ export default {
components: {
DropdownValue,
DropdownContents,
- DropdownValueCollapsed,
SidebarEditableItem,
},
inject: {
@@ -294,11 +292,6 @@ export default {
data-qa-selector="labels_block"
>
<template v-if="isDropdownVariantSidebar(variant)">
- <dropdown-value-collapsed
- ref="dropdownButtonCollapsed"
- :labels="issuableLabels"
- @onValueClick="handleCollapsedValueClick"
- />
<sidebar-editable-item
ref="editable"
:title="__('Labels')"
@@ -314,6 +307,7 @@ export default {
:labels-filter-base-path="labelsFilterBasePath"
:labels-filter-param="labelsFilterParam"
@onLabelRemove="handleLabelRemove"
+ @onCollapsedValueClick="handleCollapsedValueClick"
>
<slot></slot>
</dropdown-value>