Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/issuable')
-rw-r--r--app/assets/javascripts/issuable/components/csv_export_modal.vue4
-rw-r--r--app/assets/javascripts/issuable/components/csv_import_export_buttons.vue2
-rw-r--r--app/assets/javascripts/issuable/components/issuable_header_warnings.vue87
-rw-r--r--app/assets/javascripts/issuable/components/issue_assignees.vue4
-rw-r--r--app/assets/javascripts/issuable/components/issue_milestone.vue3
-rw-r--r--app/assets/javascripts/issuable/components/status_badge.vue98
-rw-r--r--app/assets/javascripts/issuable/components/status_box.vue146
-rw-r--r--app/assets/javascripts/issuable/index.js19
-rw-r--r--app/assets/javascripts/issuable/issuable_context.js23
-rw-r--r--app/assets/javascripts/issuable/popover/components/issue_popover.vue13
10 files changed, 134 insertions, 265 deletions
diff --git a/app/assets/javascripts/issuable/components/csv_export_modal.vue b/app/assets/javascripts/issuable/components/csv_export_modal.vue
index c1de507cd80..fd279a6a451 100644
--- a/app/assets/javascripts/issuable/components/csv_export_modal.vue
+++ b/app/assets/javascripts/issuable/components/csv_export_modal.vue
@@ -47,7 +47,7 @@ export default {
href: this.exportCsvPath,
variant: 'confirm',
'data-method': 'post',
- 'data-qa-selector': `export_issues_button`,
+ 'data-testid': 'export-issues-button',
'data-track-action': 'click_button',
'data-track-label': this.dataTrackLabel,
},
@@ -78,7 +78,7 @@ export default {
:action-cancel="$options.actionCancel"
body-class="gl-p-0!"
:title="exportText"
- data-qa-selector="export_issuable_modal"
+ data-testid="export-issuable-modal"
>
<div
class="gl-justify-content-start gl-align-items-center gl-p-4 gl-border-b-solid gl-border-1 gl-border-gray-50"
diff --git a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
index 872e1d4269d..8e2ed63613d 100644
--- a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
@@ -76,7 +76,6 @@ export default {
v-if="showExportButton"
v-gl-modal="exportModalId"
data-testid="export-as-csv-button"
- data-qa-selector="export_as_csv_button"
:item="dropdownItems.exportAsCSV"
/>
<gl-disclosure-dropdown-item
@@ -88,7 +87,6 @@ export default {
<gl-disclosure-dropdown-item
v-if="showImportButton && canEdit"
data-testid="import-from-jira-link"
- data-qa-selector="import_from_jira_link"
:item="dropdownItems.importFromJIRA"
/>
diff --git a/app/assets/javascripts/issuable/components/issuable_header_warnings.vue b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
deleted file mode 100644
index a0854be099d..00000000000
--- a/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-// eslint-disable-next-line no-restricted-imports
-import { mapGetters } from 'vuex';
-import { sprintf, __ } from '~/locale';
-import { TYPE_ISSUE, TYPE_MERGE_REQUEST, WORKSPACE_PROJECT } from '~/issues/constants';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
-
-const noteableTypeText = {
- issue: __('issue'),
- merge_request: __('merge request'),
-};
-
-export default {
- TYPE_ISSUE,
- WORKSPACE_PROJECT,
- components: {
- GlIcon,
- ConfidentialityBadge,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [glFeatureFlagMixin()],
- inject: ['hidden'],
- computed: {
- ...mapGetters(['getNoteableData']),
- isLocked() {
- return this.getNoteableData.discussion_locked;
- },
- isConfidential() {
- return this.getNoteableData.confidential;
- },
- isMergeRequest() {
- return this.getNoteableData.targetType === TYPE_MERGE_REQUEST;
- },
- warningIconsMeta() {
- return [
- {
- iconName: 'lock',
- visible: this.isLocked,
- dataTestId: 'locked',
- tooltip: sprintf(__('This %{issuable} is locked. Only project members can comment.'), {
- issuable: noteableTypeText[this.getNoteableData.targetType],
- }),
- },
- {
- iconName: 'spam',
- visible: this.hidden,
- dataTestId: 'hidden',
- tooltip: sprintf(__('This %{issuable} is hidden because its author has been banned'), {
- issuable: noteableTypeText[this.getNoteableData.targetType],
- }),
- },
- ];
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-display-inline-block">
- <confidentiality-badge
- v-if="isConfidential"
- data-testid="confidential"
- :workspace-type="$options.WORKSPACE_PROJECT"
- :issuable-type="$options.TYPE_ISSUE"
- />
- <template v-for="meta in warningIconsMeta">
- <div
- v-if="meta.visible"
- :key="meta.iconName"
- v-gl-tooltip.bottom
- :data-testid="meta.dataTestId"
- :title="meta.tooltip || null"
- :class="{
- 'gl-mr-3 gl-mt-2 gl-display-flex gl-justify-content-center gl-align-items-center': isMergeRequest,
- 'gl-display-inline-block': !isMergeRequest,
- }"
- class="issuable-warning-icon"
- >
- <gl-icon :name="meta.iconName" class="icon" />
- </div>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuable/components/issue_assignees.vue b/app/assets/javascripts/issuable/components/issue_assignees.vue
index d8cbc45684b..2181b4e1a40 100644
--- a/app/assets/javascripts/issuable/components/issue_assignees.vue
+++ b/app/assets/javascripts/issuable/components/issue_assignees.vue
@@ -89,7 +89,7 @@ export default {
:img-size="iconSize"
class="js-no-trigger author-link"
tooltip-placement="bottom"
- data-qa-selector="assignee_link"
+ data-testid="assignee-link"
>
<span class="js-assignee-tooltip">
<span class="bold d-block">{{ s__('Label|Assignee') }}</span> {{ assignee.name }}
@@ -101,7 +101,7 @@ export default {
v-gl-tooltip.bottom
:title="assigneesCounterTooltip"
class="avatar-counter"
- data-qa-selector="avatar_counter_content"
+ data-testid="avatar-counter-content"
>{{ assigneeCounterLabel }}</span
>
</div>
diff --git a/app/assets/javascripts/issuable/components/issue_milestone.vue b/app/assets/javascripts/issuable/components/issue_milestone.vue
index c7da3e59098..3340ef2338c 100644
--- a/app/assets/javascripts/issuable/components/issue_milestone.vue
+++ b/app/assets/javascripts/issuable/components/issue_milestone.vue
@@ -42,7 +42,8 @@ export default {
milestoneDatesAbsolute() {
if (this.milestoneDue) {
return `(${dateInWords(this.milestoneDue)})`;
- } else if (this.milestoneStart) {
+ }
+ if (this.milestoneStart) {
return `(${dateInWords(this.milestoneStart)})`;
}
return '';
diff --git a/app/assets/javascripts/issuable/components/status_badge.vue b/app/assets/javascripts/issuable/components/status_badge.vue
new file mode 100644
index 00000000000..949fb3c1ce5
--- /dev/null
+++ b/app/assets/javascripts/issuable/components/status_badge.vue
@@ -0,0 +1,98 @@
+<script>
+import { GlBadge, GlIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import {
+ STATUS_CLOSED,
+ STATUS_LOCKED,
+ STATUS_MERGED,
+ STATUS_OPEN,
+ TYPE_EPIC,
+ TYPE_ISSUE,
+ TYPE_MERGE_REQUEST,
+} from '~/issues/constants';
+
+const badgePropertiesMap = {
+ [TYPE_EPIC]: {
+ [STATUS_OPEN]: {
+ icon: 'epic',
+ text: __('Open'),
+ variant: 'success',
+ },
+ [STATUS_CLOSED]: {
+ icon: 'epic-closed',
+ text: __('Closed'),
+ variant: 'info',
+ },
+ },
+ [TYPE_ISSUE]: {
+ [STATUS_OPEN]: {
+ icon: 'issues',
+ text: __('Open'),
+ variant: 'success',
+ },
+ [STATUS_CLOSED]: {
+ icon: 'issue-closed',
+ text: __('Closed'),
+ variant: 'info',
+ },
+ [STATUS_LOCKED]: {
+ icon: 'issues',
+ text: __('Open'),
+ variant: 'success',
+ },
+ },
+ [TYPE_MERGE_REQUEST]: {
+ [STATUS_OPEN]: {
+ icon: 'merge-request-open',
+ text: __('Open'),
+ variant: 'success',
+ },
+ [STATUS_CLOSED]: {
+ icon: 'merge-request-close',
+ text: __('Closed'),
+ variant: 'danger',
+ },
+ [STATUS_MERGED]: {
+ icon: 'merge',
+ text: __('Merged'),
+ variant: 'info',
+ },
+ [STATUS_LOCKED]: {
+ icon: 'merge-request-open',
+ text: __('Open'),
+ variant: 'success',
+ },
+ },
+};
+
+export default {
+ components: {
+ GlBadge,
+ GlIcon,
+ },
+ props: {
+ issuableType: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ state: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ computed: {
+ badgeProperties() {
+ return badgePropertiesMap[this.issuableType][this.state];
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-badge :variant="badgeProperties.variant" :aria-label="badgeProperties.text">
+ <gl-icon :name="badgeProperties.icon" />
+ <span class="gl-display-none gl-sm-display-block gl-ml-2">{{ badgeProperties.text }}</span>
+ </gl-badge>
+</template>
diff --git a/app/assets/javascripts/issuable/components/status_box.vue b/app/assets/javascripts/issuable/components/status_box.vue
deleted file mode 100644
index 0d7d0f020dd..00000000000
--- a/app/assets/javascripts/issuable/components/status_box.vue
+++ /dev/null
@@ -1,146 +0,0 @@
-<script>
-import { GlBadge, GlIcon } from '@gitlab/ui';
-import Vue from 'vue';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { fetchPolicies } from '~/lib/graphql';
-import { __ } from '~/locale';
-import {
- STATUS_CLOSED,
- STATUS_OPEN,
- TYPE_ISSUE,
- TYPE_MERGE_REQUEST,
- TYPE_EPIC,
-} from '~/issues/constants';
-
-export const badgeState = Vue.observable({
- state: '',
- updateStatus: null,
-});
-
-const CLASSES = {
- opened: 'issuable-status-badge-open',
- locked: 'issuable-status-badge-open',
- closed: 'issuable-status-badge-closed',
- merged: 'issuable-status-badge-merged',
-};
-
-const ICONS = {
- [TYPE_EPIC]: {
- opened: 'epic',
- closed: 'epic-closed',
- },
- [TYPE_ISSUE]: {
- opened: 'issues',
- locked: 'issues',
- closed: 'issue-closed',
- },
- [TYPE_MERGE_REQUEST]: {
- opened: 'merge-request-open',
- locked: 'merge-request-open',
- closed: 'merge-request-close',
- merged: 'merge',
- },
-};
-
-const STATUS = {
- opened: __('Open'),
- locked: __('Open'),
- closed: __('Closed'),
- merged: __('Merged'),
-};
-
-export default {
- components: {
- GlBadge,
- GlIcon,
- },
- mixins: [glFeatureFlagMixin()],
- inject: {
- query: { default: null },
- projectPath: { default: null },
- iid: { default: null },
- },
- props: {
- initialState: {
- type: String,
- required: false,
- default: null,
- },
- issuableType: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- if (!this.iid) return { state: this.initialState };
-
- if (this.initialState && !badgeState.state) {
- badgeState.state = this.initialState;
- }
-
- return badgeState;
- },
- computed: {
- badgeClass() {
- return [
- CLASSES[this.state],
- {
- 'gl-vertical-align-bottom': this.issuableType === TYPE_MERGE_REQUEST,
- },
- ];
- },
- badgeVariant() {
- if (this.state === STATUS_OPEN) {
- return 'success';
- } else if (this.state === STATUS_CLOSED) {
- return this.issuableType === TYPE_MERGE_REQUEST ? 'danger' : 'info';
- }
- return 'info';
- },
- badgeText() {
- return STATUS[this.state];
- },
- badgeIcon() {
- const type = this.issuableType || TYPE_MERGE_REQUEST;
- return ICONS[type][this.state];
- },
- },
- created() {
- if (!badgeState.updateStatus) {
- badgeState.updateStatus = this.fetchState;
- }
- },
- beforeDestroy() {
- if (badgeState.updateStatus && this.query) {
- badgeState.updateStatus = null;
- }
- },
- methods: {
- async fetchState() {
- const { data } = await this.$apollo.query({
- query: this.query,
- variables: {
- projectPath: this.projectPath,
- iid: this.iid,
- },
- fetchPolicy: fetchPolicies.NO_CACHE,
- });
-
- badgeState.state = data?.workspace?.issuable?.state;
- },
- },
-};
-</script>
-
-<template>
- <gl-badge
- class="issuable-status-badge gl-mr-3 gl-align-self-center"
- :class="badgeClass"
- :variant="badgeVariant"
- :aria-label="badgeText"
- >
- <gl-icon :name="badgeIcon" class="gl-badge-icon" />
- <span class="gl-display-none gl-sm-display-block gl-ml-2">{{ badgeText }}</span>
- </gl-badge>
-</template>
diff --git a/app/assets/javascripts/issuable/index.js b/app/assets/javascripts/issuable/index.js
index acc0161bf6a..40f92763b29 100644
--- a/app/assets/javascripts/issuable/index.js
+++ b/app/assets/javascripts/issuable/index.js
@@ -5,7 +5,6 @@ import Sidebar from '~/right_sidebar';
import { getSidebarOptions } from '~/sidebar/mount_sidebar';
import CsvImportExportButtons from './components/csv_import_export_buttons.vue';
import IssuableByEmail from './components/issuable_by_email.vue';
-import IssuableHeaderWarnings from './components/issuable_header_warnings.vue';
import issuableBulkUpdateActions from './issuable_bulk_update_actions';
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
import IssuableContext from './issuable_context';
@@ -97,24 +96,6 @@ export function initIssuableByEmail() {
});
}
-export function initIssuableHeaderWarnings(store) {
- const el = document.getElementById('js-issuable-header-warnings');
-
- if (!el) {
- return null;
- }
-
- const { hidden } = el.dataset;
-
- return new Vue({
- el,
- name: 'IssuableHeaderWarningsRoot',
- store,
- provide: { hidden: parseBoolean(hidden) },
- render: (createElement) => createElement(IssuableHeaderWarnings),
- });
-}
-
export function initIssuableSidebar() {
const el = document.querySelector('.js-sidebar-options');
diff --git a/app/assets/javascripts/issuable/issuable_context.js b/app/assets/javascripts/issuable/issuable_context.js
index 8c2e2a5df67..ef49bd29a40 100644
--- a/app/assets/javascripts/issuable/issuable_context.js
+++ b/app/assets/javascripts/issuable/issuable_context.js
@@ -8,6 +8,29 @@ export default class IssuableContext {
this.userSelect = new UsersSelect(currentUser);
this.reviewersSelect = new UsersSelect(currentUser, '.js-reviewer-search');
+ this.reviewersSelect.dropdowns.forEach((glDropdownInstance) => {
+ const jQueryWrapper = glDropdownInstance.dropdown;
+ const domElement = jQueryWrapper[0];
+ const content = domElement.querySelector('.dropdown-content');
+ const loader = domElement.querySelector('.dropdown-loading');
+ const spinner = loader.querySelector('.gl-spinner-container');
+ const realParent = loader.parentNode;
+
+ domElement.classList.add('non-blocking-loader');
+ spinner.classList.remove('gl-mt-7');
+ spinner.classList.add('gl-mt-2');
+
+ jQueryWrapper.on('shown.bs.dropdown', () => {
+ glDropdownInstance.filterInput.focus();
+ });
+ jQueryWrapper.on('toggle.on.loading.gl.dropdown filtering.gl.dropdown', () => {
+ content.appendChild(loader);
+ });
+ jQueryWrapper.on('done.remote.loading.gl.dropdown done.filtering.gl.dropdown', () => {
+ realParent.appendChild(loader);
+ });
+ });
+
$('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
return $(this).submit();
});
diff --git a/app/assets/javascripts/issuable/popover/components/issue_popover.vue b/app/assets/javascripts/issuable/popover/components/issue_popover.vue
index 044a1bba7ad..12d76ec4b54 100644
--- a/app/assets/javascripts/issuable/popover/components/issue_popover.vue
+++ b/app/assets/javascripts/issuable/popover/components/issue_popover.vue
@@ -3,12 +3,13 @@ import { GlIcon, GlPopover, GlSkeletonLoader, GlTooltipDirective } from '@gitlab
import query from 'ee_else_ce/issuable/popover/queries/issue.query.graphql';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import IssueMilestone from '~/issuable/components/issue_milestone.vue';
-import StatusBox from '~/issuable/components/status_box.vue';
-import { STATUS_CLOSED } from '~/issues/constants';
+import StatusBadge from '~/issuable/components/status_badge.vue';
+import { STATUS_CLOSED, TYPE_ISSUE } from '~/issues/constants';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
export default {
+ TYPE_ISSUE,
components: {
GlIcon,
GlPopover,
@@ -16,7 +17,7 @@ export default {
IssueDueDate,
IssueMilestone,
IssueWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
- StatusBox,
+ StatusBadge,
WorkItemTypeIcon,
},
directives: {
@@ -82,14 +83,14 @@ export default {
<gl-skeleton-loader v-if="$apollo.queries.issue.loading" :height="15">
<rect width="250" height="15" rx="4" />
</gl-skeleton-loader>
- <div v-else-if="showDetails" class="gl-display-flex gl-align-items-center">
- <status-box issuable-type="issue" :initial-state="issue.state" />
+ <div v-else-if="showDetails" class="gl-display-flex gl-align-items-center gl-gap-2">
+ <status-badge :issuable-type="$options.TYPE_ISSUE" :state="issue.state" />
<gl-icon
v-if="issue.confidential"
v-gl-tooltip
name="eye-slash"
:title="__('Confidential')"
- class="gl-text-orange-500 gl-mr-2"
+ class="gl-text-orange-500"
:aria-label="__('Confidential')"
/>
<span class="gl-text-secondary">