diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-19 15:09:04 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-19 15:09:04 +0300 |
commit | c6af94ea4ea649171ff930b6bf94c73a5d03edb9 (patch) | |
tree | ceef77238b3a275a3a32b4e9f982b6d2f27e0c6b /app/assets/javascripts | |
parent | 3257ae3af07a4ad026be3c868e74ff82866fc400 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
13 files changed, 275 insertions, 130 deletions
diff --git a/app/assets/javascripts/batch_comments/mixins/resolved_status.js b/app/assets/javascripts/batch_comments/mixins/resolved_status.js index 85bdf6b7a36..bec360e3b2e 100644 --- a/app/assets/javascripts/batch_comments/mixins/resolved_status.js +++ b/app/assets/javascripts/batch_comments/mixins/resolved_status.js @@ -50,12 +50,18 @@ export default { return this.resolveDiscussion ? 'is-resolving-discussion' : 'is-unresolving-discussion'; }, resolveButtonTitle() { + const escapeParameters = false; + if (this.isDraft || this.discussionId) return this.resolvedStatusMessage; let title = __('Resolve thread'); if (this.resolvedBy) { - title = sprintf(__('Resolved by %{name}'), { name: this.resolvedBy.name }); + title = sprintf( + __('Resolved by %{name}'), + { name: this.resolvedBy.name }, + escapeParameters, + ); } return title; diff --git a/app/assets/javascripts/invite_member/init_invite_member_modal.js b/app/assets/javascripts/invite_member/init_invite_member_modal.js index 108f636ee3e..a50d31c9e7a 100644 --- a/app/assets/javascripts/invite_member/init_invite_member_modal.js +++ b/app/assets/javascripts/invite_member/init_invite_member_modal.js @@ -5,10 +5,13 @@ import InviteMemberModal from './components/invite_member_modal.vue'; Vue.use(GlToast); +const isAssigneesWidgetShown = + (isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget; + export default function initInviteMembersModal() { const el = document.querySelector('.js-invite-member-modal'); - if (!el || isInDesignPage() || isInIssuePage()) { + if (!el || isAssigneesWidgetShown) { return false; } diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index a25862a587b..a70bac94b71 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -390,7 +390,7 @@ export default { <gl-button :disabled="isDisabled" category="primary" - variant="success" + variant="confirm" class="gl-mr-3" data-qa-selector="start_review_button" @click="handleAddToReview" diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue index d61136cda8d..455990f2791 100644 --- a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue +++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue @@ -1,29 +1,19 @@ <script> -import { GlAlert, GlIcon } from '@gitlab/ui'; +import { GlIcon } from '@gitlab/ui'; import { uniqueId } from 'lodash'; -import { __, s__ } from '~/locale'; -import { DEFAULT, INVALID_CI_CONFIG } from '~/pipelines/constants'; +import { s__ } from '~/locale'; import EditorLite from '~/vue_shared/components/editor_lite.vue'; export default { i18n: { viewOnlyMessage: s__('Pipelines|Merged YAML is view only'), }, - errorTexts: { - [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'), - [DEFAULT]: __('An unknown error occurred.'), - }, components: { EditorLite, - GlAlert, GlIcon, }, inject: ['ciConfigPath'], props: { - isValid: { - type: Boolean, - required: true, - }, ciConfigData: { type: Object, required: true, @@ -35,66 +25,30 @@ export default { }; }, computed: { - failure() { - switch (this.failureType) { - case INVALID_CI_CONFIG: - return this.$options.errorTexts[INVALID_CI_CONFIG]; - default: - return this.$options.errorTexts[DEFAULT]; - } - }, fileGlobalId() { return `${this.ciConfigPath}-${uniqueId()}`; }, - hasError() { - return this.failureType; - }, mergedYaml() { return this.ciConfigData.mergedYaml; }, }, - watch: { - ciConfigData: { - immediate: true, - handler() { - if (!this.isValid) { - this.reportFailure(INVALID_CI_CONFIG); - } else if (this.hasError) { - this.resetFailure(); - } - }, - }, - }, - methods: { - reportFailure(errorType) { - this.failureType = errorType; - }, - resetFailure() { - this.failureType = null; - }, - }, }; </script> <template> <div> - <gl-alert v-if="hasError" variant="danger" :dismissible="false"> - {{ failure }} - </gl-alert> - <div v-else> - <div class="gl-display-flex gl-align-items-center"> - <gl-icon :size="16" name="lock" class="gl-text-gray-500 gl-mr-3" /> - {{ $options.i18n.viewOnlyMessage }} - </div> - <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1"> - <editor-lite - ref="editor" - :value="mergedYaml" - :file-name="ciConfigPath" - :file-global-id="fileGlobalId" - :editor-options="{ readOnly: true }" - v-on="$listeners" - /> - </div> + <div class="gl-display-flex gl-align-items-center"> + <gl-icon :size="16" name="lock" class="gl-text-gray-500 gl-mr-3" /> + {{ $options.i18n.viewOnlyMessage }} + </div> + <div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1"> + <editor-lite + ref="editor" + :value="mergedYaml" + :file-name="ciConfigPath" + :file-global-id="fileGlobalId" + :editor-options="{ readOnly: true }" + v-on="$listeners" + /> </div> </div> </template> 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 760d395ff2c..5acb3355b23 100644 --- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue +++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue @@ -1,11 +1,13 @@ <script> -import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui'; +import { GlAlert, GlLoadingIcon, GlTabs } from '@gitlab/ui'; import { s__ } from '~/locale'; import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { CREATE_TAB, + EDITOR_APP_STATUS_EMPTY, EDITOR_APP_STATUS_ERROR, + EDITOR_APP_STATUS_INVALID, EDITOR_APP_STATUS_LOADING, EDITOR_APP_STATUS_VALID, LINT_TAB, @@ -24,6 +26,17 @@ export default { tabGraph: s__('Pipelines|Visualize'), tabLint: s__('Pipelines|Lint'), tabMergedYaml: s__('Pipelines|View merged YAML'), + empty: { + visualization: s__( + 'PipelineEditor|The pipeline visualization is displayed when the CI/CD configuration file has valid syntax.', + ), + lint: s__( + 'PipelineEditor|The CI/CD configuration is continuously validated. Errors and warnings are displayed when the CI/CD configuration file is not empty.', + ), + merge: s__( + 'PipelineEditor|The merged YAML view is displayed when the CI/CD configuration file has valid syntax.', + ), + }, }, errorTexts: { loadMergedYaml: s__('Pipelines|Could not load merged YAML content'), @@ -40,7 +53,6 @@ export default { EditorTab, GlAlert, GlLoadingIcon, - GlTab, GlTabs, PipelineGraph, TextEditor, @@ -66,6 +78,12 @@ export default { // Not an invalid config and with `mergedYaml` data missing return this.appStatus === EDITOR_APP_STATUS_ERROR; }, + isEmpty() { + return this.appStatus === EDITOR_APP_STATUS_EMPTY; + }, + isInvalid() { + return this.appStatus === EDITOR_APP_STATUS_INVALID; + }, isValid() { return this.appStatus === EDITOR_APP_STATUS_VALID; }, @@ -91,9 +109,12 @@ export default { > <text-editor :value="ciFileContent" v-on="$listeners" /> </editor-tab> - <gl-tab + <editor-tab v-if="glFeatures.ciConfigVisualizationTab" class="gl-mb-3" + :empty-message="$options.i18n.empty.visualization" + :is-empty="isEmpty" + :is-invalid="isInvalid" :title="$options.i18n.tabGraph" lazy data-testid="visualization-tab" @@ -101,9 +122,11 @@ export default { > <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" /> <pipeline-graph v-else :pipeline-data="ciConfigData" /> - </gl-tab> + </editor-tab> <editor-tab class="gl-mb-3" + :empty-message="$options.i18n.empty.lint" + :is-empty="isEmpty" :title="$options.i18n.tabLint" data-testid="lint-tab" @click="setCurrentTab($options.tabConstants.LINT_TAB)" @@ -111,9 +134,13 @@ export default { <gl-loading-icon v-if="isLoading" size="lg" class="gl-m-3" /> <ci-lint v-else :is-valid="isValid" :ci-config="ciConfigData" /> </editor-tab> - <gl-tab + <editor-tab v-if="glFeatures.ciConfigMergedTab" class="gl-mb-3" + :empty-message="$options.i18n.empty.merge" + :keep-component-mounted="false" + :is-empty="isEmpty" + :is-invalid="isInvalid" :title="$options.i18n.tabMergedYaml" lazy data-testid="merged-tab" @@ -123,12 +150,7 @@ export default { <gl-alert v-else-if="hasAppError" variant="danger" :dismissible="false"> {{ $options.errorTexts.loadMergedYaml }} </gl-alert> - <ci-config-merged-preview - v-else - :is-valid="isValid" - :ci-config-data="ciConfigData" - v-on="$listeners" - /> - </gl-tab> + <ci-config-merged-preview v-else :ci-config-data="ciConfigData" v-on="$listeners" /> + </editor-tab> </gl-tabs> </template> diff --git a/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue index ce8ee7493fe..7c032441a04 100644 --- a/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue +++ b/app/assets/javascripts/pipeline_editor/components/ui/editor_tab.vue @@ -1,6 +1,6 @@ <script> -import { GlTab } from '@gitlab/ui'; - +import { GlAlert, GlTab } from '@gitlab/ui'; +import { __, s__ } from '~/locale'; /** * Wrapper of <gl-tab> to optionally lazily render this tab's content * when its shown **without dismounting after its hidden**. @@ -10,10 +10,10 @@ import { GlTab } from '@gitlab/ui'; * API is the same as <gl-tab>, for example: * * <gl-tabs> - * <editor-tab title="Tab 1" :lazy="true"> + * <editor-tab title="Tab 1" lazy> * lazily mounted content (gets mounted if this is first tab) * </editor-tab> - * <editor-tab title="Tab 2" :lazy="true"> + * <editor-tab title="Tab 2" lazy> * lazily mounted content * </editor-tab> * <editor-tab title="Tab 3"> @@ -25,10 +25,26 @@ import { GlTab } from '@gitlab/ui'; * so it's contents are not dismounted. * * lazy is "false" by default, as in <gl-tab>. + * + * It is also possible to pass the `isEmpty` and or `isInvalid` to let + * the tab component handle that state on its own. For example: + * + * * <gl-tabs> + * <editor-tab-with-status title="Tab 1" :is-empty="isEmpty" :is-invalid="isInvalid"> + * ... + * </editor-tab-with-status> + * Will be the same as normal, except it will only render the slot component + * if the status is not empty and not invalid. In any of these 2 cases, it will render + * a generic component and avoid mounting whatever it received in the slot. + * </gl-tabs> */ export default { + i18n: { + invalid: __('Your CI/CD configuration syntax is invalid. View Lint tab for more details.'), + }, components: { + GlAlert, GlTab, // Use a small renderless component to know when the tab content mounts because: // - gl-tab always gets mounted, even if lazy is `true`. See: @@ -40,29 +56,63 @@ export default { }, inheritAttrs: false, props: { + emptyMessage: { + type: String, + required: false, + default: s__( + 'PipelineEditor|This tab will be usable when the CI/CD configuration file is populated with valid syntax.', + ), + }, + isEmpty: { + type: Boolean, + required: false, + default: null, + }, + isInvalid: { + type: Boolean, + required: false, + default: null, + }, lazy: { type: Boolean, required: false, default: false, }, + keepComponentMounted: { + type: Boolean, + required: false, + default: true, + }, }, data() { return { isLazy: this.lazy, }; }, + computed: { + slots() { + return Object.keys(this.$slots); + }, + }, methods: { onContentMounted() { // When a child is first mounted make the entire tab - // permanently mounted by setting 'lazy' to false. - this.isLazy = false; + // permanently mounted by setting 'lazy' to false unless + // explicitly opted out. + if (this.keepComponentMounted) { + this.isLazy = false; + } }, }, }; </script> <template> <gl-tab :lazy="isLazy" v-bind="$attrs" v-on="$listeners"> - <slot v-for="slot in Object.keys($slots)" :name="slot"></slot> - <mount-spy @hook:mounted="onContentMounted" /> + <gl-alert v-if="isEmpty" variant="tip">{{ emptyMessage }}</gl-alert> + <gl-alert v-else-if="isInvalid" variant="danger">{{ $options.i18n.invalid }}</gl-alert> + <template v-else> + <slot v-for="slot in slots" :name="slot"></slot> + <mount-spy @hook:mounted="onContentMounted" /> + </template> </gl-tab> </template> diff --git a/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue b/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue new file mode 100644 index 00000000000..6982586ab12 --- /dev/null +++ b/app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue @@ -0,0 +1,90 @@ +<script> +import { GlBanner, GlLink, GlSprintf } from '@gitlab/ui'; +import createFlash from '~/flash'; +import { __ } from '~/locale'; +import DismissPipelineNotification from '../../graphql/mutations/dismiss_pipeline_notification.graphql'; +import getUserCallouts from '../../graphql/queries/get_user_callouts.query.graphql'; + +const featureName = 'pipeline_needs_banner'; +const enumFeatureName = featureName.toUpperCase(); + +export default { + i18n: { + title: __('View job dependencies in the pipeline graph!'), + description: __( + 'You can now group jobs in the pipeline graph based on which jobs are configured to run first, if you use the %{codeStart}needs:%{codeEnd} keyword to establish job dependencies in your CI/CD pipelines. %{linkStart}Learn how to speed up your pipeline with needs.%{linkEnd}', + ), + buttonText: __('Provide feedback'), + }, + components: { + GlBanner, + GlLink, + GlSprintf, + }, + apollo: { + callouts: { + query: getUserCallouts, + update(data) { + return data?.currentUser?.callouts?.nodes.map((c) => c.featureName); + }, + error() { + this.hasError = true; + }, + }, + }, + inject: ['dagDocPath'], + data() { + return { + callouts: [], + dismissedAlert: false, + hasError: false, + }; + }, + computed: { + showBanner() { + return ( + !this.$apollo.queries.callouts?.loading && + !this.hasError && + !this.dismissedAlert && + !this.callouts.includes(enumFeatureName) + ); + }, + }, + methods: { + handleClose() { + this.dismissedAlert = true; + try { + this.$apollo.mutate({ + mutation: DismissPipelineNotification, + variables: { + featureName, + }, + }); + } catch { + createFlash(__('There was a problem dismissing this notification.')); + } + }, + }, +}; +</script> +<template> + <gl-banner + v-if="showBanner" + :title="$options.i18n.title" + :button-text="$options.i18n.buttonText" + button-link="https://gitlab.com/gitlab-org/gitlab/-/issues/327688" + variant="introduction" + @close="handleClose" + > + <p> + <gl-sprintf :message="$options.i18n.description"> + <template #link="{ content }"> + <gl-link :href="dagDocPath" target="_blank"> {{ content }}</gl-link> + </template> + <template #code="{ content }"> + <code>{{ content }}</code> + </template> + </gl-sprintf> + </p> + </gl-banner> +</template> diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue index 1f8c4a9aa8b..3ba0d7d0120 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue @@ -1,8 +1,7 @@ <script> import { GlAlert } from '@gitlab/ui'; import { __ } from '~/locale'; -import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants'; -import { DRAW_FAILURE, DEFAULT, INVALID_CI_CONFIG, EMPTY_PIPELINE_DATA } from '../../constants'; +import { DRAW_FAILURE, DEFAULT } from '../../constants'; import LinksLayer from '../graph_shared/links_layer.vue'; import JobPill from './job_pill.vue'; import StagePill from './stage_pill.vue'; @@ -21,10 +20,6 @@ export default { errorTexts: { [DRAW_FAILURE]: __('Could not draw the lines for job relationships'), [DEFAULT]: __('An unknown error occurred.'), - [EMPTY_PIPELINE_DATA]: __( - 'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.', - ), - [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'), }, props: { pipelineData: { @@ -55,18 +50,6 @@ export default { variant: 'danger', dismissible: true, }; - case EMPTY_PIPELINE_DATA: - return { - text: this.$options.errorTexts[EMPTY_PIPELINE_DATA], - variant: 'tip', - dismissible: false, - }; - case INVALID_CI_CONFIG: - return { - text: this.$options.errorTexts[INVALID_CI_CONFIG], - variant: 'danger', - dismissible: false, - }; default: return { text: this.$options.errorTexts[DEFAULT], @@ -81,18 +64,6 @@ export default { hasHighlightedJob() { return Boolean(this.highlightedJob); }, - hideGraph() { - // We won't even try to render the graph with these condition - // because it would cause additional errors down the line for the user - // which is confusing. - return this.isPipelineDataEmpty || this.isInvalidCiConfig; - }, - isInvalidCiConfig() { - return this.pipelineData?.status === CI_CONFIG_STATUS_INVALID; - }, - isPipelineDataEmpty() { - return !this.isInvalidCiConfig && this.pipelineStages.length === 0; - }, pipelineStages() { return this.pipelineData?.stages || []; }, @@ -101,15 +72,9 @@ export default { pipelineData: { immediate: true, handler() { - if (this.isPipelineDataEmpty) { - this.reportFailure(EMPTY_PIPELINE_DATA); - } else if (this.isInvalidCiConfig) { - this.reportFailure(INVALID_CI_CONFIG); - } else { - this.$nextTick(() => { - this.computeGraphDimensions(); - }); - } + this.$nextTick(() => { + this.computeGraphDimensions(); + }); }, }, }, @@ -172,12 +137,7 @@ export default { > {{ failure.text }} </gl-alert> - <div - v-if="!hideGraph" - :id="containerId" - :ref="$options.CONTAINER_REF" - data-testid="graph-container" - > + <div :id="containerId" :ref="$options.CONTAINER_REF" data-testid="graph-container"> <links-layer :pipeline-data="pipelineStages" :pipeline-id="$options.PIPELINE_ID" diff --git a/app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql b/app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql new file mode 100644 index 00000000000..e4fd55a28be --- /dev/null +++ b/app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql @@ -0,0 +1,5 @@ +mutation DismissPipelineNotification($featureName: String!) { + userCalloutCreate(input: { featureName: $featureName }) { + errors + } +} diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql new file mode 100644 index 00000000000..12b391e41ac --- /dev/null +++ b/app/assets/javascripts/pipelines/graphql/queries/get_user_callouts.query.graphql @@ -0,0 +1,13 @@ +query getUser { + currentUser { + id + __typename + callouts { + __typename + nodes { + __typename + featureName + } + } + } +} diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js index cc53532b554..a2bc049c3c7 100644 --- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js +++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js @@ -8,6 +8,7 @@ import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin'; import createDagApp from './pipeline_details_dag'; import { createPipelinesDetailApp } from './pipeline_details_graph'; import { createPipelineHeaderApp } from './pipeline_details_header'; +import { createPipelineNotificationApp } from './pipeline_details_notification'; import { apolloProvider } from './pipeline_shared_client'; import createTestReportsStore from './stores/test_reports'; import { reportToSentry } from './utils'; @@ -18,6 +19,7 @@ const SELECTORS = { PIPELINE_DETAILS: '.js-pipeline-details-vue', PIPELINE_GRAPH: '#js-pipeline-graph-vue', PIPELINE_HEADER: '#js-pipeline-header-vue', + PIPELINE_NOTIFICATION: '#js-pipeline-notification', PIPELINE_TESTS: '#js-pipeline-tests-detail', }; @@ -93,6 +95,14 @@ export default async function initPipelineDetailsBundle() { Flash(__('An error occurred while loading a section of this page.')); } + if (gon.features.pipelineGraphLayersView) { + try { + createPipelineNotificationApp(SELECTORS.PIPELINE_NOTIFICATION, apolloProvider); + } catch { + Flash(__('An error occurred while loading a section of this page.')); + } + } + if (canShowNewPipelineDetails) { try { createPipelinesDetailApp(SELECTORS.PIPELINE_GRAPH, apolloProvider, dataset); diff --git a/app/assets/javascripts/pipelines/pipeline_details_notification.js b/app/assets/javascripts/pipelines/pipeline_details_notification.js new file mode 100644 index 00000000000..be234e8972d --- /dev/null +++ b/app/assets/javascripts/pipelines/pipeline_details_notification.js @@ -0,0 +1,29 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import PipelineNotification from './components/notification/pipeline_notification.vue'; + +Vue.use(VueApollo); + +export const createPipelineNotificationApp = (elSelector, apolloProvider) => { + const el = document.querySelector(elSelector); + + if (!el) { + return; + } + + const { dagDocPath } = el?.dataset; + // eslint-disable-next-line no-new + new Vue({ + el, + components: { + PipelineNotification, + }, + provide: { + dagDocPath, + }, + apolloProvider, + render(createElement) { + return createElement('pipeline-notification'); + }, + }); +}; diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js index 643a57bf6a8..1304e84814b 100644 --- a/app/assets/javascripts/sidebar/mount_sidebar.js +++ b/app/assets/javascripts/sidebar/mount_sidebar.js @@ -410,8 +410,11 @@ function mountCopyEmailComponent() { }); } +const isAssigneesWidgetShown = + (isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget; + export function mountSidebar(mediator) { - if (isInIssuePage() || isInDesignPage()) { + if (isAssigneesWidgetShown) { mountAssigneesComponent(); } else { mountAssigneesComponentDeprecated(mediator); |