summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/batch_comments/components/review_bar.vue3
-rw-r--r--app/assets/javascripts/batch_comments/index.js13
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js9
-rw-r--r--app/assets/javascripts/commit/pipelines/utils.js11
-rw-r--r--app/assets/javascripts/content_editor/content_editor.stories.js27
-rw-r--r--app/assets/javascripts/diffs/components/pre_renderer.vue1
-rw-r--r--app/assets/javascripts/diffs/index.js96
-rw-r--r--app/assets/javascripts/init_issuable_sidebar.js10
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js9
-rw-r--r--app/assets/javascripts/merge_request.js27
-rw-r--r--app/assets/javascripts/mr_notes/index.js36
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js8
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/show/index.js11
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue9
-rw-r--r--app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue5
-rw-r--r--app/assets/javascripts/pipelines/components/parsing_utils.js52
-rw-r--r--app/assets/javascripts/pipelines/utils.js52
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/app.vue79
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/storage_table.vue74
-rw-r--r--app/assets/javascripts/projects/storage_counter/constants.js61
-rw-r--r--app/assets/javascripts/projects/storage_counter/index.js22
-rw-r--r--app/assets/javascripts/projects/storage_counter/utils.js49
-rw-r--r--app/assets/javascripts/reports/components/issue_body.js16
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js56
-rw-r--r--app/assets/javascripts/sidebar/sidebar_bundle.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue15
28 files changed, 462 insertions, 302 deletions
diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue
index 080a5543e53..158b5f45d1c 100644
--- a/app/assets/javascripts/batch_comments/components/review_bar.vue
+++ b/app/assets/javascripts/batch_comments/components/review_bar.vue
@@ -10,7 +10,6 @@ export default {
},
computed: {
...mapGetters(['isNotesFetched']),
- ...mapGetters('batchComments', ['draftsCount']),
},
watch: {
isNotesFetched() {
@@ -25,7 +24,7 @@ export default {
};
</script>
<template>
- <div v-show="draftsCount > 0">
+ <div>
<nav class="review-bar-component" data-testid="review_bar_component">
<div
class="review-bar-content d-flex gl-justify-content-end"
diff --git a/app/assets/javascripts/batch_comments/index.js b/app/assets/javascripts/batch_comments/index.js
index 9c763e70d63..65fd34dcb00 100644
--- a/app/assets/javascripts/batch_comments/index.js
+++ b/app/assets/javascripts/batch_comments/index.js
@@ -1,7 +1,6 @@
import Vue from 'vue';
-import { mapActions } from 'vuex';
+import { mapActions, mapGetters } from 'vuex';
import store from '~/mr_notes/stores';
-import ReviewBar from './components/review_bar.vue';
export const initReviewBar = () => {
const el = document.getElementById('js-review-bar');
@@ -10,6 +9,12 @@ export const initReviewBar = () => {
new Vue({
el,
store,
+ components: {
+ ReviewBar: () => import('./components/review_bar.vue'),
+ },
+ computed: {
+ ...mapGetters('batchComments', ['draftsCount']),
+ },
mounted() {
this.fetchDrafts();
},
@@ -17,7 +22,9 @@ export const initReviewBar = () => {
...mapActions('batchComments', ['fetchDrafts']),
},
render(createElement) {
- return createElement(ReviewBar);
+ if (this.draftsCount === 0) return null;
+
+ return createElement('review-bar');
},
});
};
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index 8d88b682df2..2109aecdf03 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { initPipelineCountListener } from './utils';
/**
* Used in:
@@ -12,13 +13,7 @@ export default () => {
if (pipelineTableViewEl) {
// Update MR and Commits tabs
- pipelineTableViewEl.addEventListener('update-pipelines-count', (event) => {
- if (event.detail.pipelineCount) {
- const badge = document.querySelector('.js-pipelines-mr-count');
-
- badge.textContent = event.detail.pipelineCount;
- }
- });
+ initPipelineCountListener(pipelineTableViewEl);
if (pipelineTableViewEl.dataset.disableInitialization === undefined) {
const table = new Vue({
diff --git a/app/assets/javascripts/commit/pipelines/utils.js b/app/assets/javascripts/commit/pipelines/utils.js
new file mode 100644
index 00000000000..52cbe52fa9b
--- /dev/null
+++ b/app/assets/javascripts/commit/pipelines/utils.js
@@ -0,0 +1,11 @@
+export function initPipelineCountListener(el) {
+ if (!el) return;
+
+ el.addEventListener('update-pipelines-count', (event) => {
+ if (event.detail.pipelineCount) {
+ const badge = document.querySelector('.js-pipelines-mr-count');
+
+ badge.textContent = event.detail.pipelineCount;
+ }
+ });
+}
diff --git a/app/assets/javascripts/content_editor/content_editor.stories.js b/app/assets/javascripts/content_editor/content_editor.stories.js
new file mode 100644
index 00000000000..8f2ce8feb5d
--- /dev/null
+++ b/app/assets/javascripts/content_editor/content_editor.stories.js
@@ -0,0 +1,27 @@
+import { ContentEditor } from './index';
+
+export default {
+ component: ContentEditor,
+ title: 'Components/Content Editor',
+};
+
+const Template = (_, { argTypes }) => ({
+ components: { ContentEditor },
+ props: Object.keys(argTypes),
+ template: '<content-editor v-bind="$props" @initialized="loadContent" />',
+ methods: {
+ loadContent(contentEditor) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ contentEditor.setSerializedContent('Hello content editor');
+ },
+ },
+});
+
+export const Default = Template.bind({});
+
+Default.args = {
+ renderMarkdown: () => '<p>Hello content editor</p>',
+ uploadsPath: '/uploads/',
+ serializerConfig: {},
+ extensions: [],
+};
diff --git a/app/assets/javascripts/diffs/components/pre_renderer.vue b/app/assets/javascripts/diffs/components/pre_renderer.vue
index c357aa2d924..e4320c40d2c 100644
--- a/app/assets/javascripts/diffs/components/pre_renderer.vue
+++ b/app/assets/javascripts/diffs/components/pre_renderer.vue
@@ -17,7 +17,6 @@ export default {
},
mounted() {
this.width = this.$el.parentNode.offsetWidth;
- window.test = this;
this.$_itemsWithSizeWatcher = this.$watch('vscrollParent.itemsWithSize', async () => {
await this.$nextTick();
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index bddc28c4758..1b1ab59b2b4 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -3,7 +3,6 @@ import Vue from 'vue';
import { mapActions, mapState, mapGetters } from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
import { getParameterValues } from '~/lib/utils/url_utility';
-import FindFile from '~/vue_shared/components/file_finder/index.vue';
import eventHub from '../notes/event_hub';
import diffsApp from './components/app.vue';
@@ -12,51 +11,7 @@ import { getReviewsForMergeRequest } from './utils/file_reviews';
import { getDerivedMergeRequestInformation } from './utils/merge_request';
export default function initDiffsApp(store) {
- const fileFinderEl = document.getElementById('js-diff-file-finder');
-
- if (fileFinderEl) {
- // eslint-disable-next-line no-new
- new Vue({
- el: fileFinderEl,
- store,
- computed: {
- ...mapState('diffs', ['fileFinderVisible', 'isLoading']),
- ...mapGetters('diffs', ['flatBlobsList']),
- },
- watch: {
- fileFinderVisible(newVal, oldVal) {
- if (newVal && !oldVal && !this.flatBlobsList.length) {
- eventHub.$emit('fetchDiffData');
- }
- },
- },
- methods: {
- ...mapActions('diffs', ['toggleFileFinder', 'scrollToFile']),
- openFile(file) {
- window.mrTabs.tabShown('diffs');
- this.scrollToFile(file.path);
- },
- },
- render(createElement) {
- return createElement(FindFile, {
- props: {
- files: this.flatBlobsList,
- visible: this.fileFinderVisible,
- loading: this.isLoading,
- showDiffStats: true,
- clearSearchOnClose: false,
- },
- on: {
- toggle: this.toggleFileFinder,
- click: this.openFile,
- },
- class: ['diff-file-finder'],
- });
- },
- });
- }
-
- return new Vue({
+ const vm = new Vue({
el: '#js-diffs-app',
name: 'MergeRequestDiffs',
components: {
@@ -157,4 +112,53 @@ export default function initDiffsApp(store) {
});
},
});
+
+ const fileFinderEl = document.getElementById('js-diff-file-finder');
+
+ if (fileFinderEl) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: fileFinderEl,
+ store,
+ components: {
+ FindFile: () => import('~/vue_shared/components/file_finder/index.vue'),
+ },
+ computed: {
+ ...mapState('diffs', ['fileFinderVisible', 'isLoading']),
+ ...mapGetters('diffs', ['flatBlobsList']),
+ },
+ watch: {
+ fileFinderVisible(newVal, oldVal) {
+ if (newVal && !oldVal && !this.flatBlobsList.length) {
+ eventHub.$emit('fetchDiffData');
+ }
+ },
+ },
+ methods: {
+ ...mapActions('diffs', ['toggleFileFinder', 'scrollToFile']),
+ openFile(file) {
+ window.mrTabs.tabShown('diffs');
+ this.scrollToFile(file.path);
+ },
+ },
+ render(createElement) {
+ return createElement('find-file', {
+ props: {
+ files: this.flatBlobsList,
+ visible: this.fileFinderVisible,
+ loading: this.isLoading,
+ showDiffStats: true,
+ clearSearchOnClose: false,
+ },
+ on: {
+ toggle: this.toggleFileFinder,
+ click: this.openFile,
+ },
+ class: ['diff-file-finder'],
+ });
+ },
+ });
+ }
+
+ return vm;
}
diff --git a/app/assets/javascripts/init_issuable_sidebar.js b/app/assets/javascripts/init_issuable_sidebar.js
index 17c73fdf1c3..7a70d893008 100644
--- a/app/assets/javascripts/init_issuable_sidebar.js
+++ b/app/assets/javascripts/init_issuable_sidebar.js
@@ -1,9 +1,7 @@
/* eslint-disable no-new */
-import { mountSidebarLabels, getSidebarOptions } from '~/sidebar/mount_sidebar';
+import { getSidebarOptions } from '~/sidebar/mount_sidebar';
import IssuableContext from './issuable_context';
-import LabelsSelect from './labels_select';
-import MilestoneSelect from './milestone_select';
import Sidebar from './right_sidebar';
export default () => {
@@ -13,12 +11,6 @@ export default () => {
const sidebarOptions = getSidebarOptions(sidebarOptEl);
- new MilestoneSelect({
- full_path: sidebarOptions.fullPath,
- });
- new LabelsSelect();
new IssuableContext(sidebarOptions.currentUser);
Sidebar.initialize();
-
- mountSidebarLabels();
};
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index f3dedb7726a..f46263c0e4d 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -69,19 +69,20 @@ export function bytesToGiB(number) {
* representation (e.g., giving it 1500 yields 1.5 KB).
*
* @param {Number} size
+ * @param {Number} digits - The number of digits to appear after the decimal point
* @returns {String}
*/
-export function numberToHumanSize(size) {
+export function numberToHumanSize(size, digits = 2) {
const abs = Math.abs(size);
if (abs < BYTES_IN_KIB) {
return sprintf(__('%{size} bytes'), { size });
} else if (abs < BYTES_IN_KIB ** 2) {
- return sprintf(__('%{size} KiB'), { size: bytesToKiB(size).toFixed(2) });
+ return sprintf(__('%{size} KiB'), { size: bytesToKiB(size).toFixed(digits) });
} else if (abs < BYTES_IN_KIB ** 3) {
- return sprintf(__('%{size} MiB'), { size: bytesToMiB(size).toFixed(2) });
+ return sprintf(__('%{size} MiB'), { size: bytesToMiB(size).toFixed(digits) });
}
- return sprintf(__('%{size} GiB'), { size: bytesToGiB(size).toFixed(2) });
+ return sprintf(__('%{size} GiB'), { size: bytesToGiB(size).toFixed(digits) });
}
/**
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 0ddb2c2334c..e89b886df83 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -19,11 +19,9 @@ function MergeRequest(opts) {
this.opts = opts != null ? opts : {};
this.submitNoteForm = this.submitNoteForm.bind(this);
this.$el = $('.merge-request');
- this.$('.show-all-commits').on('click', () => this.showAllCommits());
this.initTabs();
this.initMRBtnListeners();
- this.initCommitMessageListeners();
if ($('.description.js-task-list-container').length) {
this.taskList = new TaskList({
@@ -59,11 +57,6 @@ MergeRequest.prototype.initTabs = function () {
window.mrTabs = new MergeRequestTabs(this.opts);
};
-MergeRequest.prototype.showAllCommits = function () {
- this.$('.first-commits').remove();
- return this.$('.all-commits').removeClass('hide');
-};
-
MergeRequest.prototype.initMRBtnListeners = function () {
const _this = this;
const draftToggles = document.querySelectorAll('.js-draft-toggle-button');
@@ -128,26 +121,6 @@ MergeRequest.prototype.submitNoteForm = function (form, $button) {
}
};
-MergeRequest.prototype.initCommitMessageListeners = function () {
- $(document).on('click', 'a.js-with-description-link', (e) => {
- const textarea = $('textarea.js-commit-message');
- e.preventDefault();
-
- textarea.val(textarea.data('messageWithDescription'));
- $('.js-with-description-hint').hide();
- $('.js-without-description-hint').show();
- });
-
- $(document).on('click', 'a.js-without-description-link', (e) => {
- const textarea = $('textarea.js-commit-message');
- e.preventDefault();
-
- textarea.val(textarea.data('messageWithoutDescription'));
- $('.js-with-description-hint').show();
- $('.js-without-description-hint').hide();
- });
-};
-
MergeRequest.decreaseCounter = function (by = 1) {
const $el = $('.js-merge-counter');
const count = Math.max(parseInt($el.text().replace(/[^\d]/, ''), 10) - by, 0);
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index a7696a716d0..ea3e4e5604c 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -19,6 +19,7 @@ export default function initMrNotes() {
action: mrShowNode.dataset.mrAction,
});
+ initDiffsApp(store);
initNotesApp();
document.addEventListener('merged:UpdateActions', () => {
@@ -26,20 +27,25 @@ export default function initMrNotes() {
initCherryPickCommitModal();
});
- // eslint-disable-next-line no-new
- new Vue({
- el: '#js-vue-discussion-counter',
- name: 'DiscussionCounter',
- components: {
- discussionCounter,
- },
- store,
- render(createElement) {
- return createElement('discussion-counter');
- },
- });
+ requestIdleCallback(() => {
+ const el = document.getElementById('js-vue-discussion-counter');
- initDiscussionFilters(store);
- initSortDiscussions(store);
- initDiffsApp(store);
+ if (el) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ name: 'DiscussionCounter',
+ components: {
+ discussionCounter,
+ },
+ store,
+ render(createElement) {
+ return createElement('discussion-counter');
+ },
+ });
+ }
+
+ initDiscussionFilters(store);
+ initSortDiscussions(store);
+ });
}
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
index e4f99d1e7fd..1282d2aa303 100644
--- a/app/assets/javascripts/pages/projects/issues/show/index.js
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -1,7 +1,8 @@
+import { store } from '~/notes/stores';
import initRelatedIssues from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initShow from '../show';
initShow();
-initSidebarBundle();
+initSidebarBundle(store);
initRelatedIssues();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
index 25864149378..dadf0988582 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js
@@ -2,11 +2,10 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
-import initPipelines from '~/commit/pipelines/pipelines_bundle';
+import { initPipelineCountListener } from '~/commit/pipelines/utils';
import initIssuableSidebar from '~/init_issuable_sidebar';
import StatusBox from '~/issuable/components/status_box.vue';
import createDefaultClient from '~/lib/graphql';
-import { handleLocationHash } from '~/lib/utils/common_utils';
import initSourcegraph from '~/sourcegraph';
import ZenMode from '~/zen_mode';
import getStateQuery from './queries/get_state.query.graphql';
@@ -15,11 +14,10 @@ export default function initMergeRequestShow() {
const awardEmojiEl = document.getElementById('js-vue-awards-block');
new ZenMode(); // eslint-disable-line no-new
- initIssuableSidebar();
- initPipelines();
+ initPipelineCountListener(document.querySelector('#commit-pipeline-table-view'));
new ShortcutsIssuable(true); // eslint-disable-line no-new
- handleLocationHash();
initSourcegraph();
+ initIssuableSidebar();
if (awardEmojiEl) {
import('~/emoji/awards_app')
.then((m) => m.default(awardEmojiEl))
diff --git a/app/assets/javascripts/pages/projects/merge_requests/show/index.js b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
index 546fa66eda6..25dede33880 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/show/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
@@ -5,8 +5,11 @@ import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import initShow from '../init_merge_request_show';
-initShow();
-initSidebarBundle();
initMrNotes();
-initReviewBar();
-initIssuableHeaderWarning(store);
+initShow();
+
+requestIdleCallback(() => {
+ initSidebarBundle(store);
+ initReviewBar();
+ initIssuableHeaderWarning(store);
+});
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
index ebe73bdcec3..551a0430fbf 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
@@ -1,21 +1,14 @@
<script>
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import BranchSwitcher from './branch_switcher.vue';
export default {
components: {
BranchSwitcher,
},
- mixins: [glFeatureFlagsMixin()],
- computed: {
- showBranchSwitcher() {
- return this.glFeatures.pipelineEditorBranchSwitcher;
- },
- },
};
</script>
<template>
<div class="gl-mb-4">
- <branch-switcher v-if="showBranchSwitcher" v-on="$listeners" />
+ <branch-switcher v-on="$listeners" />
</div>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue
index 0ac4a40ff4a..fbb66231f16 100644
--- a/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue
+++ b/app/assets/javascripts/pipeline_editor/components/ui/pipeline_editor_empty_state.vue
@@ -24,9 +24,6 @@ export default {
},
},
computed: {
- showFileNav() {
- return this.glFeatures.pipelineEditorBranchSwitcher;
- },
showCTAButton() {
return this.glFeatures.pipelineEditorEmptyStateAction;
},
@@ -40,7 +37,7 @@ export default {
</script>
<template>
<div>
- <pipeline-editor-file-nav v-if="showFileNav" v-on="$listeners" />
+ <pipeline-editor-file-nav v-on="$listeners" />
<div class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-mt-11">
<img :src="emptyStateIllustrationPath" />
<h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1>
diff --git a/app/assets/javascripts/pipelines/components/parsing_utils.js b/app/assets/javascripts/pipelines/components/parsing_utils.js
index 48658c7ffe0..fa7330ce890 100644
--- a/app/assets/javascripts/pipelines/components/parsing_utils.js
+++ b/app/assets/javascripts/pipelines/components/parsing_utils.js
@@ -1,58 +1,8 @@
import { memoize } from 'lodash';
+import { createNodeDict } from '../utils';
import { createSankey } from './dag/drawing_utils';
/*
- The following functions are the main engine in transforming the data as
- received from the endpoint into the format the d3 graph expects.
-
- Input is of the form:
- [nodes]
- nodes: [{category, name, jobs, size}]
- category is the stage name
- name is a group name; in the case that the group has one job, it is
- also the job name
- size is the number of parallel jobs
- jobs: [{ name, needs}]
- job name is either the same as the group name or group x/y
- needs: [job-names]
- needs is an array of job-name strings
-
- Output is of the form:
- { nodes: [node], links: [link] }
- node: { name, category }, + unused info passed through
- link: { source, target, value }, with source & target being node names
- and value being a constant
-
- We create nodes in the GraphQL update function, and then here we create the node dictionary,
- then create links, and then dedupe the links, so that in the case where
- job 4 depends on job 1 and job 2, and job 2 depends on job 1, we show only a single link
- from job 1 to job 2 then another from job 2 to job 4.
-
- CREATE LINKS
- nodes.name -> target
- nodes.name.needs.each -> source (source is the name of the group, not the parallel job)
- 10 -> value (constant)
- */
-
-export const createNodeDict = (nodes) => {
- return nodes.reduce((acc, node) => {
- const newNode = {
- ...node,
- needs: node.jobs.map((job) => job.needs || []).flat(),
- };
-
- if (node.size > 1) {
- node.jobs.forEach((job) => {
- acc[job.name] = newNode;
- });
- }
-
- acc[node.name] = newNode;
- return acc;
- }, {});
-};
-
-/*
A peformant alternative to lodash's isEqual. Because findIndex always finds
the first instance of a match, if the found index is not the first, we know
it is in fact a duplicate.
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 02a9e5b7fc6..e28eb74fb1b 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -1,8 +1,58 @@
import * as Sentry from '@sentry/browser';
import { pickBy } from 'lodash';
-import { createNodeDict } from './components/parsing_utils';
import { SUPPORTED_FILTER_PARAMETERS } from './constants';
+/*
+ The following functions are the main engine in transforming the data as
+ received from the endpoint into the format the d3 graph expects.
+
+ Input is of the form:
+ [nodes]
+ nodes: [{category, name, jobs, size}]
+ category is the stage name
+ name is a group name; in the case that the group has one job, it is
+ also the job name
+ size is the number of parallel jobs
+ jobs: [{ name, needs}]
+ job name is either the same as the group name or group x/y
+ needs: [job-names]
+ needs is an array of job-name strings
+
+ Output is of the form:
+ { nodes: [node], links: [link] }
+ node: { name, category }, + unused info passed through
+ link: { source, target, value }, with source & target being node names
+ and value being a constant
+
+ We create nodes in the GraphQL update function, and then here we create the node dictionary,
+ then create links, and then dedupe the links, so that in the case where
+ job 4 depends on job 1 and job 2, and job 2 depends on job 1, we show only a single link
+ from job 1 to job 2 then another from job 2 to job 4.
+
+ CREATE LINKS
+ nodes.name -> target
+ nodes.name.needs.each -> source (source is the name of the group, not the parallel job)
+ 10 -> value (constant)
+ */
+
+export const createNodeDict = (nodes) => {
+ return nodes.reduce((acc, node) => {
+ const newNode = {
+ ...node,
+ needs: node.jobs.map((job) => job.needs || []).flat(),
+ };
+
+ if (node.size > 1) {
+ node.jobs.forEach((job) => {
+ acc[job.name] = newNode;
+ });
+ }
+
+ acc[node.name] = newNode;
+ return acc;
+ }, {});
+};
+
export const validateParams = (params) => {
return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val);
};
diff --git a/app/assets/javascripts/projects/storage_counter/components/app.vue b/app/assets/javascripts/projects/storage_counter/components/app.vue
index cfb08c11f0e..1a911ea3d9b 100644
--- a/app/assets/javascripts/projects/storage_counter/components/app.vue
+++ b/app/assets/javascripts/projects/storage_counter/components/app.vue
@@ -1,17 +1,30 @@
<script>
-import { GlAlert } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { GlAlert, GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { sprintf } from '~/locale';
import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
+import {
+ ERROR_MESSAGE,
+ LEARN_MORE_LABEL,
+ USAGE_QUOTAS_LABEL,
+ TOTAL_USAGE_TITLE,
+ TOTAL_USAGE_SUBTITLE,
+ TOTAL_USAGE_DEFAULT_TEXT,
+ HELP_LINK_ARIA_LABEL,
+} from '../constants';
import getProjectStorageCount from '../queries/project_storage.query.graphql';
import { parseGetProjectStorageResults } from '../utils';
+import StorageTable from './storage_table.vue';
export default {
name: 'StorageCounterApp',
components: {
GlAlert,
+ GlLink,
+ GlLoadingIcon,
+ StorageTable,
UsageGraph,
},
- inject: ['projectPath'],
+ inject: ['projectPath', 'helpLinks'],
apollo: {
project: {
query: getProjectStorageCount,
@@ -20,11 +33,11 @@ export default {
fullPath: this.projectPath,
};
},
- update: parseGetProjectStorageResults,
+ update(data) {
+ return parseGetProjectStorageResults(data, this.helpLinks);
+ },
error() {
- this.error = s__(
- 'UsageQuota|Something went wrong while fetching project storage statistics',
- );
+ this.error = ERROR_MESSAGE;
},
},
},
@@ -34,24 +47,60 @@ export default {
error: '',
};
},
+ computed: {
+ totalUsage() {
+ return this.project?.storage?.totalUsage || TOTAL_USAGE_DEFAULT_TEXT;
+ },
+ storageTypes() {
+ return this.project?.storage?.storageTypes || [];
+ },
+ },
methods: {
clearError() {
this.error = '';
},
+ helpLinkAriaLabel(linkTitle) {
+ return sprintf(HELP_LINK_ARIA_LABEL, {
+ linkTitle,
+ });
+ },
},
- i18n: {
- placeholder: s__('UsageQuota|Usage'),
- },
+ LEARN_MORE_LABEL,
+ USAGE_QUOTAS_LABEL,
+ TOTAL_USAGE_TITLE,
+ TOTAL_USAGE_SUBTITLE,
};
</script>
<template>
- <div>
- <gl-alert v-if="error" variant="danger" @dismiss="clearError">
- {{ error }}
- </gl-alert>
- <div v-else>{{ $options.i18n.placeholder }}</div>
+ <gl-loading-icon v-if="$apollo.queries.project.loading" class="gl-mt-5" size="md" />
+ <gl-alert v-else-if="error" variant="danger" @dismiss="clearError">
+ {{ error }}
+ </gl-alert>
+ <div v-else>
+ <div class="gl-pt-5 gl-px-3">
+ <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
+ <div>
+ <p class="gl-m-0 gl-font-lg gl-font-weight-bold">{{ $options.TOTAL_USAGE_TITLE }}</p>
+ <p class="gl-m-0 gl-text-gray-400">
+ {{ $options.TOTAL_USAGE_SUBTITLE }}
+ <gl-link
+ :href="helpLinks.usageQuotasHelpPagePath"
+ target="_blank"
+ :aria-label="helpLinkAriaLabel($options.USAGE_QUOTAS_LABEL)"
+ data-testid="usage-quotas-help-link"
+ >
+ {{ $options.LEARN_MORE_LABEL }}
+ </gl-link>
+ </p>
+ </div>
+ <p class="gl-m-0 gl-font-size-h-display gl-font-weight-bold" data-testid="total-usage">
+ {{ totalUsage }}
+ </p>
+ </div>
+ </div>
<div v-if="project.statistics" class="gl-w-full">
<usage-graph :root-storage-statistics="project.statistics" :limit="0" />
</div>
+ <storage-table :storage-types="storageTypes" />
</div>
</template>
diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue b/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
new file mode 100644
index 00000000000..50aa70ecc9d
--- /dev/null
+++ b/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
@@ -0,0 +1,74 @@
+<script>
+import { GlLink, GlIcon, GlTable, GlSprintf } from '@gitlab/ui';
+import { thWidthClass } from '~/lib/utils/table_utility';
+import { sprintf } from '~/locale';
+import { PROJECT_TABLE_LABELS, HELP_LINK_ARIA_LABEL } from '../constants';
+
+export default {
+ name: 'StorageTable',
+ components: {
+ GlLink,
+ GlIcon,
+ GlTable,
+ GlSprintf,
+ },
+ props: {
+ storageTypes: {
+ type: Array,
+ required: true,
+ },
+ },
+ methods: {
+ helpLinkAriaLabel(linkTitle) {
+ return sprintf(HELP_LINK_ARIA_LABEL, {
+ linkTitle,
+ });
+ },
+ },
+ projectTableFields: [
+ {
+ key: 'storageType',
+ label: PROJECT_TABLE_LABELS.STORAGE_TYPE,
+ thClass: thWidthClass(90),
+ sortable: true,
+ },
+ {
+ key: 'value',
+ label: PROJECT_TABLE_LABELS.VALUE,
+ thClass: thWidthClass(10),
+ sortable: true,
+ },
+ ],
+};
+</script>
+<template>
+ <gl-table :items="storageTypes" :fields="$options.projectTableFields">
+ <template #cell(storageType)="{ item }">
+ <p class="gl-font-weight-bold gl-mb-0" :data-testid="`${item.storageType.id}-name`">
+ {{ item.storageType.name }}
+ <gl-link
+ v-if="item.storageType.helpPath"
+ :href="item.storageType.helpPath"
+ target="_blank"
+ :aria-label="helpLinkAriaLabel(item.storageType.name)"
+ :data-testid="`${item.storageType.id}-help-link`"
+ >
+ <gl-icon name="question" :size="12" />
+ </gl-link>
+ </p>
+ <p class="gl-mb-0" :data-testid="`${item.storageType.id}-description`">
+ {{ item.storageType.description }}
+ </p>
+ <p v-if="item.storageType.warningMessage" class="gl-mb-0 gl-font-sm">
+ <gl-icon name="warning" :size="12" />
+ <gl-sprintf :message="item.storageType.warningMessage">
+ <template #warningLink="{ content }">
+ <gl-link :href="item.storageType.warningLink" target="_blank" class="gl-font-sm">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </template>
+ </gl-table>
+</template>
diff --git a/app/assets/javascripts/projects/storage_counter/constants.js b/app/assets/javascripts/projects/storage_counter/constants.js
new file mode 100644
index 00000000000..d9b28abfbe7
--- /dev/null
+++ b/app/assets/javascripts/projects/storage_counter/constants.js
@@ -0,0 +1,61 @@
+import { s__, __ } from '~/locale';
+
+export const PROJECT_STORAGE_TYPES = [
+ {
+ id: 'buildArtifactsSize',
+ name: s__('UsageQuota|Artifacts'),
+ description: s__('UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD.'),
+ warningMessage: s__(
+ 'UsageQuota|There is a known issue with Artifact storage where the total could be incorrect for some projects. More details and progress are available in %{warningLinkStart}the epic%{warningLinkEnd}.',
+ ),
+ warningLink: 'https://gitlab.com/groups/gitlab-org/-/epics/5380',
+ },
+ {
+ id: 'lfsObjectsSize',
+ name: s__('UsageQuota|LFS Storage'),
+ description: s__('UsageQuota|Audio samples, videos, datasets, and graphics.'),
+ },
+ {
+ id: 'packagesSize',
+ name: s__('UsageQuota|Packages'),
+ description: s__('UsageQuota|Code packages and container images.'),
+ },
+ {
+ id: 'repositorySize',
+ name: s__('UsageQuota|Repository'),
+ description: s__('UsageQuota|Git repository, managed by the Gitaly service.'),
+ },
+ {
+ id: 'snippetsSize',
+ name: s__('UsageQuota|Snippets'),
+ description: s__('UsageQuota|Shared bits of code and text.'),
+ },
+ {
+ id: 'uploadsSize',
+ name: s__('UsageQuota|Uploads'),
+ description: s__('UsageQuota|File attachments and smaller design graphics.'),
+ },
+ {
+ id: 'wikiSize',
+ name: s__('UsageQuota|Wiki'),
+ description: s__('UsageQuota|Wiki content.'),
+ },
+];
+
+export const PROJECT_TABLE_LABELS = {
+ STORAGE_TYPE: s__('UsageQuota|Storage type'),
+ VALUE: s__('UsageQuota|Usage'),
+};
+
+export const ERROR_MESSAGE = s__(
+ 'UsageQuota|Something went wrong while fetching project storage statistics',
+);
+
+export const LEARN_MORE_LABEL = s__('Learn more.');
+export const USAGE_QUOTAS_LABEL = s__('UsageQuota|Usage Quotas');
+export const HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
+export const TOTAL_USAGE_DEFAULT_TEXT = __('N/A');
+export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage Breakdown');
+export const TOTAL_USAGE_SUBTITLE = s__(
+ 'UsageQuota|Includes project registry, artifacts, packages, wiki, uploads and other items.',
+);
diff --git a/app/assets/javascripts/projects/storage_counter/index.js b/app/assets/javascripts/projects/storage_counter/index.js
index 8812bfb56a2..10668f08402 100644
--- a/app/assets/javascripts/projects/storage_counter/index.js
+++ b/app/assets/javascripts/projects/storage_counter/index.js
@@ -12,7 +12,17 @@ export default (containerId = 'js-project-storage-count-app') => {
return false;
}
- const { projectPath } = el.dataset;
+ const {
+ projectPath,
+ usageQuotasHelpPagePath,
+ buildArtifactsHelpPagePath,
+ lfsObjectsHelpPagePath,
+ packagesHelpPagePath,
+ repositoryHelpPagePath,
+ snippetsHelpPagePath,
+ uploadsHelpPagePath,
+ wikiHelpPagePath,
+ } = el.dataset;
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
@@ -23,6 +33,16 @@ export default (containerId = 'js-project-storage-count-app') => {
apolloProvider,
provide: {
projectPath,
+ helpLinks: {
+ usageQuotasHelpPagePath,
+ buildArtifactsHelpPagePath,
+ lfsObjectsHelpPagePath,
+ packagesHelpPagePath,
+ repositoryHelpPagePath,
+ snippetsHelpPagePath,
+ uploadsHelpPagePath,
+ wikiHelpPagePath,
+ },
},
render(createElement) {
return createElement(StorageCounterApp);
diff --git a/app/assets/javascripts/projects/storage_counter/utils.js b/app/assets/javascripts/projects/storage_counter/utils.js
index cfc5f14b26a..7b7182cbbf0 100644
--- a/app/assets/javascripts/projects/storage_counter/utils.js
+++ b/app/assets/javascripts/projects/storage_counter/utils.js
@@ -1,36 +1,5 @@
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { s__ } from '~/locale';
-
-const projectStorageTypes = [
- {
- id: 'buildArtifactsSize',
- name: s__('UsageQuota|Artifacts'),
- },
- {
- id: 'lfsObjectsSize',
- name: s__('UsageQuota|LFS Storage'),
- },
- {
- id: 'packagesSize',
- name: s__('UsageQuota|Packages'),
- },
- {
- id: 'repositorySize',
- name: s__('UsageQuota|Repository'),
- },
- {
- id: 'snippetsSize',
- name: s__('UsageQuota|Snippets'),
- },
- {
- id: 'uploadsSize',
- name: s__('UsageQuota|Uploads'),
- },
- {
- id: 'wikiSize',
- name: s__('UsageQuota|Wiki'),
- },
-];
+import { PROJECT_STORAGE_TYPES } from './constants';
/**
* This method parses the results from `getProjectStorageCount` call.
@@ -38,26 +7,32 @@ const projectStorageTypes = [
* @param {Object} data graphql result
* @returns {Object}
*/
-export const parseGetProjectStorageResults = (data) => {
+export const parseGetProjectStorageResults = (data, helpLinks) => {
const projectStatistics = data?.project?.statistics;
if (!projectStatistics) {
return {};
}
const { storageSize, ...storageStatistics } = projectStatistics;
- const storageTypes = projectStorageTypes.reduce((types, currentType) => {
+ const storageTypes = PROJECT_STORAGE_TYPES.reduce((types, currentType) => {
if (!storageStatistics[currentType.id]) {
return types;
}
+ const helpPathKey = currentType.id.replace(`Size`, `HelpPagePath`);
+ const helpPath = helpLinks[helpPathKey];
+
return types.concat({
- ...currentType,
- value: numberToHumanSize(storageStatistics[currentType.id]),
+ storageType: {
+ ...currentType,
+ helpPath,
+ },
+ value: numberToHumanSize(storageStatistics[currentType.id], 1),
});
}, []);
return {
storage: {
- totalUsage: numberToHumanSize(storageSize),
+ totalUsage: numberToHumanSize(storageSize, 1),
storageTypes,
},
statistics: projectStatistics,
diff --git a/app/assets/javascripts/reports/components/issue_body.js b/app/assets/javascripts/reports/components/issue_body.js
index 6014d9d6ad8..04e72809e62 100644
--- a/app/assets/javascripts/reports/components/issue_body.js
+++ b/app/assets/javascripts/reports/components/issue_body.js
@@ -1,18 +1,16 @@
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
-import AccessibilityIssueBody from '../accessibility_report/components/accessibility_issue_body.vue';
-import CodequalityIssueBody from '../codequality_report/components/codequality_issue_body.vue';
-import TestIssueBody from '../grouped_test_report/components/test_issue_body.vue';
export const components = {
- AccessibilityIssueBody,
- CodequalityIssueBody,
- TestIssueBody,
+ AccessibilityIssueBody: () =>
+ import('../accessibility_report/components/accessibility_issue_body.vue'),
+ CodequalityIssueBody: () => import('../codequality_report/components/codequality_issue_body.vue'),
+ TestIssueBody: () => import('../grouped_test_report/components/test_issue_body.vue'),
};
export const componentNames = {
- AccessibilityIssueBody: AccessibilityIssueBody.name,
- CodequalityIssueBody: CodequalityIssueBody.name,
- TestIssueBody: TestIssueBody.name,
+ AccessibilityIssueBody: 'AccessibilityIssueBody',
+ CodequalityIssueBody: 'CodequalityIssueBody',
+ TestIssueBody: 'TestIssueBody',
};
export const iconComponents = {
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 12d9d9ab222..10ab80f4ec2 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -1,7 +1,6 @@
import $ from 'jquery';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import createFlash from '~/flash';
import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
@@ -13,7 +12,6 @@ import {
isInIncidentPage,
parseBoolean,
} from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue';
import SidebarAssigneesWidget from '~/sidebar/components/assignees/sidebar_assignees_widget.vue';
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
@@ -363,10 +361,10 @@ function mountReferenceComponent() {
});
}
-function mountLockComponent() {
+function mountLockComponent(store) {
const el = document.getElementById('js-lock-entry-point');
- if (!el) {
+ if (!el || !store) {
return;
}
@@ -375,37 +373,20 @@ function mountLockComponent() {
const dataNode = document.getElementById('js-lock-issue-data');
const initialData = JSON.parse(dataNode.innerHTML);
- let importStore;
- if (isInIssuePage() || isInIncidentPage()) {
- importStore = import(/* webpackChunkName: 'notesStore' */ '~/notes/stores').then(
- ({ store }) => store,
- );
- } else {
- importStore = import(/* webpackChunkName: 'mrNotesStore' */ '~/mr_notes/stores').then(
- (store) => store.default,
- );
- }
-
- importStore
- .then(
- (store) =>
- new Vue({
- el,
- store,
- provide: {
- fullPath,
- },
- render: (createElement) =>
- createElement(IssuableLockForm, {
- props: {
- isEditable: initialData.is_editable,
- },
- }),
- }),
- )
- .catch(() => {
- createFlash({ message: __('Failed to load sidebar lock status') });
- });
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ store,
+ provide: {
+ fullPath,
+ },
+ render: (createElement) =>
+ createElement(IssuableLockForm, {
+ props: {
+ isEditable: initialData.is_editable,
+ },
+ }),
+ });
}
function mountParticipantsComponent() {
@@ -537,7 +518,7 @@ function mountCopyEmailComponent() {
const isAssigneesWidgetShown =
(isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget;
-export function mountSidebar(mediator) {
+export function mountSidebar(mediator, store) {
initInviteMembersModal();
initInviteMembersTrigger();
@@ -548,11 +529,12 @@ export function mountSidebar(mediator) {
mountAssigneesComponentDeprecated(mediator);
}
mountReviewersComponent(mediator);
+ mountSidebarLabels();
mountMilestoneSelect();
mountConfidentialComponent(mediator);
mountDueDateComponent(mediator);
mountReferenceComponent(mediator);
- mountLockComponent();
+ mountLockComponent(store);
mountParticipantsComponent();
mountSubscriptionsComponent();
mountCopyEmailComponent();
diff --git a/app/assets/javascripts/sidebar/sidebar_bundle.js b/app/assets/javascripts/sidebar/sidebar_bundle.js
index 063e3313a3c..1be670f7590 100644
--- a/app/assets/javascripts/sidebar/sidebar_bundle.js
+++ b/app/assets/javascripts/sidebar/sidebar_bundle.js
@@ -1,9 +1,9 @@
-import { mountSidebar, getSidebarOptions } from './mount_sidebar';
+import { mountSidebar, getSidebarOptions } from 'ee_else_ce/sidebar/mount_sidebar';
import Mediator from './sidebar_mediator';
-export default () => {
+export default (store) => {
const mediator = new Mediator(getSidebarOptions());
mediator.fetch();
- mountSidebar(mediator);
+ mountSidebar(mediator, store);
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index 3a3a1329483..b10e0e2bc88 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -7,8 +7,6 @@ import VueApollo from 'vue-apollo';
import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_options.vue';
import createDefaultClient from '~/lib/graphql';
import Translate from '../vue_shared/translate';
-import { registerExtension } from './components/extensions';
-import issueExtension from './extensions/issues';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -28,8 +26,6 @@ export default () => {
gl.mrWidgetData.gitlabLogo = gon.gitlab_logo;
gl.mrWidgetData.defaultAvatarUrl = gon.default_avatar_url;
- registerExtension(issueExtension);
-
const vm = new Vue({
el: '#js-vue-mr-widget',
provide: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index c17fdbe1e47..f8e6dcf7ec0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -12,9 +12,6 @@ import { sprintf, s__, __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
import { setFaviconOverlay } from '../lib/utils/favicon';
-import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
-import GroupedCodequalityReportsApp from '../reports/codequality_report/grouped_codequality_reports_app.vue';
-import GroupedTestReportsApp from '../reports/grouped_test_report/grouped_test_reports_app.vue';
import Loading from './components/loading.vue';
import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue';
import WidgetHeader from './components/mr_widget_header.vue';
@@ -42,7 +39,6 @@ import ShaMismatch from './components/states/sha_mismatch.vue';
import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
import WorkInProgressState from './components/states/work_in_progress.vue';
// import ExtensionsContainer from './components/extensions/container';
-import TerraformPlan from './components/terraform/mr_widget_terraform_container.vue';
import eventHub from './event_hub';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
import getStateQuery from './queries/get_state.query.graphql';
@@ -84,10 +80,13 @@ export default {
'mr-widget-auto-merge-failed': AutoMergeFailed,
'mr-widget-rebase': RebaseState,
SourceBranchRemovalStatus,
- GroupedCodequalityReportsApp,
- GroupedTestReportsApp,
- TerraformPlan,
- GroupedAccessibilityReportsApp,
+ GroupedCodequalityReportsApp: () =>
+ import('../reports/codequality_report/grouped_codequality_reports_app.vue'),
+ GroupedTestReportsApp: () =>
+ import('../reports/grouped_test_report/grouped_test_reports_app.vue'),
+ TerraformPlan: () => import('./components/terraform/mr_widget_terraform_container.vue'),
+ GroupedAccessibilityReportsApp: () =>
+ import('../reports/accessibility_report/grouped_accessibility_reports_app.vue'),
MrWidgetApprovals,
SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'),
},