diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-17 10:07:47 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-17 10:07:47 +0000 |
commit | d670c3006e6e44901bce0d53cc4768d1d80ffa92 (patch) | |
tree | 8f65743c232e5b76850c4cc264ba15e1185815ff /app/assets/javascripts/vue_shared | |
parent | a5f4bba440d7f9ea47046a0a561d49adf0a1e6d4 (diff) | |
download | gitlab-ce-d670c3006e6e44901bce0d53cc4768d1d80ffa92.tar.gz |
Add latest changes from gitlab-org/gitlab@14-0-stable-ee
Diffstat (limited to 'app/assets/javascripts/vue_shared')
14 files changed, 191 insertions, 128 deletions
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue index 2e7b3e149b2..3b261f5ac25 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue @@ -71,9 +71,9 @@ export default { <template> <base-token - :token-config="config" - :token-value="value" - :token-active="active" + :config="config" + :value="value" + :active="active" :tokens-list-loading="loading" :token-values="authors" :fn-active-token-value="getActiveAuthor" @@ -81,6 +81,7 @@ export default { :preloaded-token-values="preloadedAuthors" :recent-token-values-storage-key="config.recentTokenValuesStorageKey" @fetch-token-values="fetchAuthorBySearchTerm" + v-on="$listeners" > <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }"> <gl-avatar diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue index fb6b9e4bc0d..bda6b340871 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue @@ -19,29 +19,34 @@ export default { GlLoadingIcon, }, props: { - tokenConfig: { + config: { type: Object, required: true, }, - tokenValue: { + value: { type: Object, required: true, }, - tokenActive: { + active: { type: Boolean, required: true, }, tokensListLoading: { type: Boolean, - required: true, + required: false, + default: false, }, tokenValues: { type: Array, - required: true, + required: false, + default: () => [], }, fnActiveTokenValue: { type: Function, - required: true, + required: false, + default: (tokenValues, currentTokenValue) => { + return tokenValues.find(({ value }) => value === currentTokenValue); + }, }, defaultTokenValues: { type: Array, @@ -90,9 +95,9 @@ export default { }, currentTokenValue() { if (this.fnCurrentTokenValue) { - return this.fnCurrentTokenValue(this.tokenValue.data); + return this.fnCurrentTokenValue(this.value.data); } - return this.tokenValue.data.toLowerCase(); + return this.value.data.toLowerCase(); }, activeTokenValue() { return this.fnActiveTokenValue(this.tokenValues, this.currentTokenValue); @@ -113,11 +118,11 @@ export default { }, }, watch: { - tokenActive: { + active: { immediate: true, handler(newValue) { if (!newValue && !this.tokenValues.length) { - this.$emit('fetch-token-values', this.tokenValue.data); + this.$emit('fetch-token-values', this.value.data); } }, }, @@ -148,9 +153,11 @@ export default { <template> <gl-filtered-search-token - :config="tokenConfig" - v-bind="{ ...this.$parent.$props, ...this.$parent.$attrs }" - v-on="this.$parent.$listeners" + :config="config" + :value="value" + :active="active" + v-bind="$attrs" + v-on="$listeners" @input="handleInput" @select="handleTokenValueSelected(activeTokenValue)" > @@ -177,7 +184,7 @@ export default { <gl-dropdown-divider /> </template> <slot - v-if="preloadedTokenValues.length" + v-if="preloadedTokenValues.length && !searchKey" name="token-values-list" :token-values="preloadedTokenValues" ></slot> diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue index 20b8cbfe933..e496d099a42 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue @@ -93,15 +93,16 @@ export default { <template> <base-token - :token-config="config" - :token-value="value" - :token-active="active" + :config="config" + :value="value" + :active="active" :tokens-list-loading="loading" :token-values="labels" :fn-active-token-value="getActiveLabel" :default-token-values="defaultLabels" :recent-token-values-storage-key="config.recentTokenValuesStorageKey" @fetch-token-values="fetchLabelBySearchTerm" + v-on="$listeners" > <template #view-token="{ viewTokenProps: { inputValue, cssClasses, listeners, activeTokenValue } }" diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue index d80b66fd9be..1f0704f7308 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue @@ -1,5 +1,6 @@ <script> -import { mapGetters, mapState } from 'vuex'; +import { GlButton } from '@gitlab/ui'; +import { mapActions, mapGetters, mapState } from 'vuex'; import DropdownContentsCreateView from './dropdown_contents_create_view.vue'; import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue'; @@ -8,6 +9,7 @@ export default { components: { DropdownContentsLabelsView, DropdownContentsCreateView, + GlButton, }, props: { renderOnTop: { @@ -15,10 +17,14 @@ export default { required: false, default: false, }, + labelsCreateTitle: { + type: String, + required: true, + }, }, computed: { - ...mapState(['showDropdownContentsCreateView']), - ...mapGetters(['isDropdownVariantSidebar']), + ...mapState(['showDropdownContentsCreateView', 'labelsListTitle']), + ...mapGetters(['isDropdownVariantSidebar', 'isDropdownVariantEmbedded']), dropdownContentsView() { if (this.showDropdownContentsCreateView) { return 'dropdown-contents-create-view'; @@ -29,6 +35,12 @@ export default { const bottom = this.isDropdownVariantSidebar ? '3rem' : '2rem'; return this.renderOnTop ? { bottom } : {}; }, + dropdownTitle() { + return this.showDropdownContentsCreateView ? this.labelsCreateTitle : this.labelsListTitle; + }, + }, + methods: { + ...mapActions(['toggleDropdownContentsCreateView', 'toggleDropdownContents']), }, }; </script> @@ -39,6 +51,30 @@ export default { data-qa-selector="labels_dropdown_content" :style="directionStyle" > - <component :is="dropdownContentsView" /> + <div + v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded" + class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!" + data-testid="dropdown-title" + > + <gl-button + v-if="showDropdownContentsCreateView" + :aria-label="__('Go back')" + variant="link" + size="small" + class="js-btn-back dropdown-header-button p-0" + icon="arrow-left" + @click="toggleDropdownContentsCreateView" + /> + <span class="flex-grow-1">{{ dropdownTitle }}</span> + <gl-button + :aria-label="__('Close')" + variant="link" + size="small" + class="dropdown-header-button gl-p-0!" + icon="close" + @click="toggleDropdownContents" + /> + </div> + <component :is="dropdownContentsView" @hideCreateView="toggleDropdownContentsCreateView" /> </div> </template> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue index f8cc981ba3d..a7f20fbe851 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue @@ -1,6 +1,10 @@ <script> import { GlTooltipDirective, GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui'; -import { mapState, mapActions } from 'vuex'; +import createFlash from '~/flash'; +import { __ } from '~/locale'; +import createLabelMutation from './graphql/create_label.mutation.graphql'; + +const errorMessage = __('Error creating label.'); export default { components: { @@ -12,14 +16,19 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, + inject: { + projectPath: { + default: '', + }, + }, data() { return { labelTitle: '', selectedColor: '', + labelCreateInProgress: false, }; }, computed: { - ...mapState(['labelsCreateTitle', 'labelCreateInProgress']), disableCreate() { return !this.labelTitle.length || !this.selectedColor.length || this.labelCreateInProgress; }, @@ -29,7 +38,6 @@ export default { }, }, methods: { - ...mapActions(['toggleDropdownContents', 'toggleDropdownContentsCreateView', 'createLabel']), getColorCode(color) { return Object.keys(color).pop(); }, @@ -39,11 +47,27 @@ export default { handleColorClick(color) { this.selectedColor = this.getColorCode(color); }, - handleCreateClick() { - this.createLabel({ - title: this.labelTitle, - color: this.selectedColor, - }); + async createLabel() { + this.labelCreateInProgress = true; + try { + const { + data: { labelCreate }, + } = await this.$apollo.mutate({ + mutation: createLabelMutation, + variables: { + title: this.labelTitle, + color: this.selectedColor, + projectPath: this.projectPath, + }, + }); + if (labelCreate.errors.length) { + createFlash({ message: errorMessage }); + } + } catch { + createFlash({ message: errorMessage }); + } + this.labelCreateInProgress = false; + this.$emit('hideCreateView'); }, }, }; @@ -51,34 +75,16 @@ export default { <template> <div class="labels-select-contents-create js-labels-create"> - <div class="dropdown-title d-flex align-items-center pt-0 pb-2"> - <gl-button - :aria-label="__('Go back')" - variant="link" - size="small" - class="js-btn-back dropdown-header-button p-0" - icon="arrow-left" - @click="toggleDropdownContentsCreateView" - /> - <span class="flex-grow-1">{{ labelsCreateTitle }}</span> - <gl-button - :aria-label="__('Close')" - variant="link" - size="small" - class="dropdown-header-button p-0" - icon="close" - @click="toggleDropdownContents" - /> - </div> <div class="dropdown-input"> <gl-form-input v-model.trim="labelTitle" :placeholder="__('Name new label')" :autofocus="true" + data-testid="label-title-input" /> </div> - <div class="dropdown-content px-2"> - <div class="suggest-colors suggest-colors-dropdown mt-0 mb-2"> + <div class="dropdown-content gl-px-3"> + <div class="suggest-colors suggest-colors-dropdown gl-mt-0! gl-mb-3!"> <gl-link v-for="(color, index) in suggestedColors" :key="index" @@ -90,28 +96,35 @@ export default { </div> <div class="color-input-container gl-display-flex"> <span - class="dropdown-label-color-preview position-relative position-relative d-inline-block" + 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" :placeholder="__('Use custom color #FF0000')" + data-testid="selected-color-text" /> </div> </div> - <div class="dropdown-actions clearfix pt-2 px-2"> + <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="success" - class="float-left d-flex align-items-center" - @click="handleCreateClick" + class="gl-display-flex gl-align-items-center" + data-testid="create-button" + @click="createLabel" > - <gl-loading-icon v-show="labelCreateInProgress" :inline="true" class="mr-1" /> + <gl-loading-icon v-if="labelCreateInProgress" :inline="true" class="mr-1" /> {{ __('Create') }} </gl-button> - <gl-button class="float-right js-btn-cancel-create" @click="toggleDropdownContentsCreateView"> + <gl-button + class="js-btn-cancel-create" + data-testid="cancel-button" + @click="$emit('hideCreateView')" + > {{ __('Cancel') }} </gl-button> </div> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue index 86788a84260..bff34743344 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue @@ -1,11 +1,5 @@ <script> -import { - GlIntersectionObserver, - GlLoadingIcon, - GlButton, - GlSearchBoxByType, - GlLink, -} from '@gitlab/ui'; +import { GlIntersectionObserver, GlLoadingIcon, GlSearchBoxByType, GlLink } from '@gitlab/ui'; import fuzzaldrinPlus from 'fuzzaldrin-plus'; import { mapState, mapGetters, mapActions } from 'vuex'; @@ -17,7 +11,6 @@ export default { components: { GlIntersectionObserver, GlLoadingIcon, - GlButton, GlSearchBoxByType, GlLink, LabelItem, @@ -149,21 +142,6 @@ export default { <template> <gl-intersection-observer @appear="handleComponentAppear" @disappear="handleComponentDisappear"> <div class="labels-select-contents-list js-labels-list" @keydown="handleKeyDown"> - <div - v-if="isDropdownVariantSidebar || isDropdownVariantEmbedded" - class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!" - data-testid="dropdown-title" - > - <span class="flex-grow-1">{{ labelsListTitle }}</span> - <gl-button - :aria-label="__('Close')" - variant="link" - size="small" - class="dropdown-header-button gl-p-0!" - icon="close" - @click="toggleDropdownContents" - /> - </div> <div class="dropdown-input" @click.stop="() => {}"> <gl-search-box-by-type ref="searchInput" 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 new file mode 100644 index 00000000000..122250d1ce7 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue @@ -0,0 +1,55 @@ +<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/graphql/create_label.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql new file mode 100644 index 00000000000..9aa4f5d165e --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/create_label.mutation.graphql @@ -0,0 +1,15 @@ +mutation createLabel($title: String!, $color: String, $projectPath: ID, $groupPath: ID) { + labelCreate( + input: { title: $title, color: $color, projectPath: $projectPath, groupPath: $groupPath } + ) { + label { + id + color + description + descriptionHtml + title + textColor + } + errors + } +} 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 bf30e3cfac5..7728c758e18 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 @@ -5,13 +5,12 @@ import Vuex, { mapState, mapActions, mapGetters } from 'vuex'; import { isInViewport } from '~/lib/utils/common_utils'; import { __ } from '~/locale'; -import DropdownValueCollapsed from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value_collapsed.vue'; - import { DropdownVariant } from './constants'; import DropdownButton from './dropdown_button.vue'; import DropdownContents from './dropdown_contents.vue'; import DropdownTitle from './dropdown_title.vue'; import DropdownValue from './dropdown_value.vue'; +import DropdownValueCollapsed from './dropdown_value_collapsed.vue'; import labelsSelectModule from './store'; Vue.use(Vuex); @@ -163,7 +162,6 @@ export default { labelsFilterBasePath: this.labelsFilterBasePath, labelsFilterParam: this.labelsFilterParam, labelsListTitle: this.labelsListTitle, - labelsCreateTitle: this.labelsCreateTitle, footerCreateLabelTitle: this.footerCreateLabelTitle, footerManageLabelTitle: this.footerManageLabelTitle, }); @@ -313,6 +311,7 @@ export default { v-show="dropdownButtonVisible && showDropdownContents" ref="dropdownContents" :render-on-top="!contentIsOnViewport" + :labels-create-title="labelsCreateTitle" /> </template> <template v-if="isDropdownVariantStandalone || isDropdownVariantEmbedded"> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js index 89f96ab916b..2b96b159ca3 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/actions.js @@ -28,31 +28,5 @@ export const fetchLabels = ({ state, dispatch }) => { .catch(() => dispatch('receiveLabelsFailure')); }; -export const requestCreateLabel = ({ commit }) => commit(types.REQUEST_CREATE_LABEL); -export const receiveCreateLabelSuccess = ({ commit }) => commit(types.RECEIVE_CREATE_LABEL_SUCCESS); -export const receiveCreateLabelFailure = ({ commit }) => { - commit(types.RECEIVE_CREATE_LABEL_FAILURE); - flash(__('Error creating label.')); -}; -export const createLabel = ({ state, dispatch }, label) => { - dispatch('requestCreateLabel'); - axios - .post(state.labelsManagePath, { - label, - }) - .then(({ data }) => { - if (data.id) { - dispatch('receiveCreateLabelSuccess'); - dispatch('toggleDropdownContentsCreateView'); - } else { - // eslint-disable-next-line @gitlab/require-i18n-strings - throw new Error('Error Creating Label'); - } - }) - .catch(() => { - dispatch('receiveCreateLabelFailure'); - }); -}; - export const updateSelectedLabels = ({ commit }, labels) => commit(types.UPDATE_SELECTED_LABELS, { labels }); diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js index 2e044dc3b3c..b8da7a90b36 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutation_types.js @@ -8,10 +8,6 @@ export const REQUEST_SET_LABELS = 'REQUEST_SET_LABELS'; export const RECEIVE_SET_LABELS_SUCCESS = 'RECEIVE_SET_LABELS_SUCCESS'; export const RECEIVE_SET_LABELS_FAILURE = 'RECEIVE_SET_LABELS_FAILURE'; -export const REQUEST_CREATE_LABEL = 'REQUEST_CREATE_LABEL'; -export const RECEIVE_CREATE_LABEL_SUCCESS = 'RECEIVE_CREATE_LABEL_SUCCESS'; -export const RECEIVE_CREATE_LABEL_FAILURE = 'RECEIVE_CREATE_LABEL_FAILURE'; - export const TOGGLE_DROPDOWN_BUTTON = 'TOGGLE_DROPDOWN_VISIBILITY'; export const TOGGLE_DROPDOWN_CONTENTS = 'TOGGLE_DROPDOWN_CONTENTS'; diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js index 55716e1105e..131c6e6fb57 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/mutations.js @@ -46,17 +46,6 @@ export default { [types.RECEIVE_SET_LABELS_FAILURE](state) { state.labelsFetchInProgress = false; }, - - [types.REQUEST_CREATE_LABEL](state) { - state.labelCreateInProgress = true; - }, - [types.RECEIVE_CREATE_LABEL_SUCCESS](state) { - state.labelCreateInProgress = false; - }, - [types.RECEIVE_CREATE_LABEL_FAILURE](state) { - state.labelCreateInProgress = false; - }, - [types.UPDATE_SELECTED_LABELS](state, { labels }) { // Find the label to update from all the labels // and change `set` prop value to represent their current state. diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js index d66cfed4163..220bab05ed2 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/store/state.js @@ -3,7 +3,6 @@ export default () => ({ labels: [], selectedLabels: [], labelsListTitle: '', - labelsCreateTitle: '', footerCreateLabelTitle: '', footerManageLabelTitle: '', dropdownButtonText: '', diff --git a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue index 9e941087da2..5d39d740c07 100644 --- a/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue +++ b/app/assets/javascripts/vue_shared/security_reports/components/security_report_download_dropdown.vue @@ -35,7 +35,7 @@ export default { <template> <gl-dropdown v-gl-tooltip - :title="s__('SecurityReports|Download results')" + :text="s__('SecurityReports|Download results')" :loading="loading" icon="download" size="small" |