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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-21 02:50:22 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-21 02:50:22 +0300
commit9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch)
tree70467ae3692a0e35e5ea56bcb803eb512a10bedb /app/assets/javascripts/projects
parent4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff)
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'app/assets/javascripts/projects')
-rw-r--r--app/assets/javascripts/projects/commit/components/commit_comments_button.vue42
-rw-r--r--app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue107
-rw-r--r--app/assets/javascripts/projects/commit/components/form_modal.vue8
-rw-r--r--app/assets/javascripts/projects/commit/components/form_trigger.vue35
-rw-r--r--app/assets/javascripts/projects/commit/constants.js2
-rw-r--r--app/assets/javascripts/projects/commit/index.js8
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js1
-rw-r--r--app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js20
-rw-r--r--app/assets/javascripts/projects/commit/init_commit_comments_button.js18
-rw-r--r--app/assets/javascripts/projects/commit/init_commit_options_dropdown.js35
-rw-r--r--app/assets/javascripts/projects/commit/init_revert_commit_trigger.js20
-rw-r--r--app/assets/javascripts/projects/commit/store/actions.js4
-rw-r--r--app/assets/javascripts/projects/commit_box/info/index.js16
-rw-r--r--app/assets/javascripts/projects/commit_box/info/load_branches.js3
-rw-r--r--app/assets/javascripts/projects/compare/components/app_legacy.vue27
-rw-r--r--app/assets/javascripts/projects/compare/components/repo_dropdown.vue9
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown.vue59
-rw-r--r--app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue13
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue32
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue3
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/constants.js1
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue36
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue6
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue4
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js6
25 files changed, 363 insertions, 152 deletions
diff --git a/app/assets/javascripts/projects/commit/components/commit_comments_button.vue b/app/assets/javascripts/projects/commit/components/commit_comments_button.vue
new file mode 100644
index 00000000000..67b5e1e512c
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/commit_comments_button.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { n__ } from '~/locale';
+
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ GlButton,
+ },
+ props: {
+ commentsCount: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ tooltipText() {
+ return n__('%d comment on this commit', '%d comments on this commit', this.commentsCount);
+ },
+ showCommentButton() {
+ return this.commentsCount > 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <span
+ v-if="showCommentButton"
+ v-gl-tooltip
+ class="gl-display-none gl-sm-display-inline-block"
+ tabindex="0"
+ :title="tooltipText"
+ data-testid="comment-button-wrapper"
+ >
+ <gl-button icon="comment" class="gl-mr-3" disabled>
+ {{ commentsCount }}
+ </gl-button>
+ </span>
+</template>
diff --git a/app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue b/app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue
new file mode 100644
index 00000000000..d96d1035ed0
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/components/commit_options_dropdown.vue
@@ -0,0 +1,107 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlDropdownDivider, GlDropdownSectionHeader } from '@gitlab/ui';
+import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '../constants';
+import eventHub from '../event_hub';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ },
+ inject: {
+ newProjectTagPath: {
+ default: '',
+ },
+ emailPatchesPath: {
+ default: '',
+ },
+ plainDiffPath: {
+ default: '',
+ },
+ },
+ props: {
+ canRevert: {
+ type: Boolean,
+ required: true,
+ },
+ canCherryPick: {
+ type: Boolean,
+ required: true,
+ },
+ canTag: {
+ type: Boolean,
+ required: true,
+ },
+ canEmailPatches: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ showDivider() {
+ return this.canRevert || this.canCherryPick || this.canTag;
+ },
+ },
+ methods: {
+ showModal(modalId) {
+ eventHub.$emit(modalId);
+ },
+ },
+ openRevertModal: OPEN_REVERT_MODAL,
+ openCherryPickModal: OPEN_CHERRY_PICK_MODAL,
+};
+</script>
+
+<template>
+ <gl-dropdown
+ :text="__('Options')"
+ right
+ data-testid="commit-options-dropdown"
+ data-qa-selector="options_button"
+ class="gl-xs-w-full"
+ >
+ <gl-dropdown-item
+ v-if="canRevert"
+ data-testid="revert-link"
+ @click="showModal($options.openRevertModal)"
+ >
+ {{ s__('ChangeTypeAction|Revert') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canCherryPick"
+ data-testid="cherry-pick-link"
+ data-qa-selector="cherry_pick_button"
+ @click="showModal($options.openCherryPickModal)"
+ >
+ {{ s__('ChangeTypeAction|Cherry-pick') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canTag" :href="newProjectTagPath" data-testid="tag-link">
+ {{ s__('CreateTag|Tag') }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider v-if="showDivider" />
+ <gl-dropdown-section-header>
+ {{ __('Download') }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-if="canEmailPatches"
+ :href="emailPatchesPath"
+ download
+ rel="nofollow"
+ data-testid="email-patches-link"
+ data-qa-selector="email_patches"
+ >
+ {{ s__('DownloadCommit|Email Patches') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ :href="plainDiffPath"
+ download
+ rel="nofollow"
+ data-testid="plain-diff-link"
+ data-qa-selector="plain_diff"
+ >
+ {{ s__('DownloadCommit|Plain Diff') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/projects/commit/components/form_modal.vue b/app/assets/javascripts/projects/commit/components/form_modal.vue
index 30968d29cde..6eefa5f55e4 100644
--- a/app/assets/javascripts/projects/commit/components/form_modal.vue
+++ b/app/assets/javascripts/projects/commit/components/form_modal.vue
@@ -37,6 +37,11 @@ export default {
type: String,
required: true,
},
+ isCherryPick: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -47,6 +52,7 @@ export default {
{ variant: 'success' },
{ category: 'primary' },
{ 'data-testid': 'submit-commit' },
+ { 'data-qa-selector': 'submit_commit_button' },
],
},
actionCancel: {
@@ -110,7 +116,7 @@ export default {
<input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
<gl-form-group
- v-if="glFeatures.pickIntoProject"
+ v-if="glFeatures.pickIntoProject && isCherryPick"
:label="i18n.projectLabel"
label-for="start_project"
data-testid="dropdown-group"
diff --git a/app/assets/javascripts/projects/commit/components/form_trigger.vue b/app/assets/javascripts/projects/commit/components/form_trigger.vue
deleted file mode 100644
index 3561b5c2473..00000000000
--- a/app/assets/javascripts/projects/commit/components/form_trigger.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<script>
-import { GlLink } from '@gitlab/ui';
-import eventHub from '../event_hub';
-
-export default {
- components: {
- GlLink,
- },
- inject: {
- displayText: {
- default: '',
- },
- testId: {
- default: '',
- },
- },
- props: {
- openModal: {
- type: String,
- required: true,
- },
- },
- methods: {
- showModal() {
- eventHub.$emit(this.openModal);
- },
- },
-};
-</script>
-
-<template>
- <gl-link data-is-link="true" :data-testid="testId" @click="showModal">
- {{ displayText }}
- </gl-link>
-</template>
diff --git a/app/assets/javascripts/projects/commit/constants.js b/app/assets/javascripts/projects/commit/constants.js
index d6bb4e9483f..d553bca360e 100644
--- a/app/assets/javascripts/projects/commit/constants.js
+++ b/app/assets/javascripts/projects/commit/constants.js
@@ -2,10 +2,8 @@ import { s__, __ } from '~/locale';
export const OPEN_REVERT_MODAL = 'openRevertModal';
export const REVERT_MODAL_ID = 'revert-commit-modal';
-export const REVERT_LINK_TEST_ID = 'revert-commit-link';
export const OPEN_CHERRY_PICK_MODAL = 'openCherryPickModal';
export const CHERRY_PICK_MODAL_ID = 'cherry-pick-commit-modal';
-export const CHERRY_PICK_LINK_TEST_ID = 'cherry-pick-commit-link';
export const I18N_MODAL = {
startMergeRequest: s__('ChangeTypeAction|Start a %{newMergeRequest} with these changes'),
diff --git a/app/assets/javascripts/projects/commit/index.js b/app/assets/javascripts/projects/commit/index.js
index b5fdfc25236..d8d30c4332c 100644
--- a/app/assets/javascripts/projects/commit/index.js
+++ b/app/assets/javascripts/projects/commit/index.js
@@ -1,11 +1,11 @@
import initCherryPickCommitModal from './init_cherry_pick_commit_modal';
-import initCherryPickCommitTrigger from './init_cherry_pick_commit_trigger';
+import initCommitCommentsButton from './init_commit_comments_button';
+import initCommitOptionsDropdown from './init_commit_options_dropdown';
import initRevertCommitModal from './init_revert_commit_modal';
-import initRevertCommitTrigger from './init_revert_commit_trigger';
export default () => {
initRevertCommitModal();
- initRevertCommitTrigger();
initCherryPickCommitModal();
- initCherryPickCommitTrigger();
+ initCommitCommentsButton();
+ initCommitOptionsDropdown();
};
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
index ad31ad14b2a..47ee8237fea 100644
--- a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
+++ b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_modal.js
@@ -51,6 +51,7 @@ export default function initInviteMembersModal() {
i18n: { ...I18N_CHERRY_PICK_MODAL, ...I18N_MODAL },
openModal: OPEN_CHERRY_PICK_MODAL,
modalId: CHERRY_PICK_MODAL_ID,
+ isCherryPick: true,
},
}),
});
diff --git a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js b/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js
deleted file mode 100644
index 942451dc96a..00000000000
--- a/app/assets/javascripts/projects/commit/init_cherry_pick_commit_trigger.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Vue from 'vue';
-import CommitFormTrigger from './components/form_trigger.vue';
-import { OPEN_CHERRY_PICK_MODAL, CHERRY_PICK_LINK_TEST_ID } from './constants';
-
-export default function initInviteMembersTrigger() {
- const el = document.querySelector('.js-cherry-pick-commit-trigger');
-
- if (!el) {
- return false;
- }
-
- const { displayText } = el.dataset;
-
- return new Vue({
- el,
- provide: { displayText, testId: CHERRY_PICK_LINK_TEST_ID },
- render: (createElement) =>
- createElement(CommitFormTrigger, { props: { openModal: OPEN_CHERRY_PICK_MODAL } }),
- });
-}
diff --git a/app/assets/javascripts/projects/commit/init_commit_comments_button.js b/app/assets/javascripts/projects/commit/init_commit_comments_button.js
new file mode 100644
index 00000000000..d70f7cb65f3
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_commit_comments_button.js
@@ -0,0 +1,18 @@
+import Vue from 'vue';
+import CommitCommentsButton from './components/commit_comments_button.vue';
+
+export default function initCommitCommentsButton() {
+ const el = document.querySelector('#js-commit-comments-button');
+
+ if (!el) {
+ return false;
+ }
+
+ const { commentsCount } = el.dataset;
+
+ return new Vue({
+ el,
+ render: (createElement) =>
+ createElement(CommitCommentsButton, { props: { commentsCount: Number(commentsCount) } }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_commit_options_dropdown.js b/app/assets/javascripts/projects/commit/init_commit_options_dropdown.js
new file mode 100644
index 00000000000..339918e7661
--- /dev/null
+++ b/app/assets/javascripts/projects/commit/init_commit_options_dropdown.js
@@ -0,0 +1,35 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import CommitOptionsDropdown from './components/commit_options_dropdown.vue';
+
+export default function initCommitOptionsDropdown() {
+ const el = document.querySelector('#js-commit-options-dropdown');
+
+ if (!el) {
+ return false;
+ }
+
+ const {
+ newProjectTagPath,
+ emailPatchesPath,
+ plainDiffPath,
+ canRevert,
+ canCherryPick,
+ canTag,
+ canEmailPatches,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: { newProjectTagPath, emailPatchesPath, plainDiffPath },
+ render: (createElement) =>
+ createElement(CommitOptionsDropdown, {
+ props: {
+ canRevert: parseBoolean(canRevert),
+ canCherryPick: parseBoolean(canCherryPick),
+ canTag: parseBoolean(canTag),
+ canEmailPatches: parseBoolean(canEmailPatches),
+ },
+ }),
+ });
+}
diff --git a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js b/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
deleted file mode 100644
index dc5168524ca..00000000000
--- a/app/assets/javascripts/projects/commit/init_revert_commit_trigger.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Vue from 'vue';
-import CommitFormTrigger from './components/form_trigger.vue';
-import { OPEN_REVERT_MODAL, REVERT_LINK_TEST_ID } from './constants';
-
-export default function initInviteMembersTrigger() {
- const el = document.querySelector('.js-revert-commit-trigger');
-
- if (!el) {
- return false;
- }
-
- const { displayText } = el.dataset;
-
- return new Vue({
- el,
- provide: { displayText, testId: REVERT_LINK_TEST_ID },
- render: (createElement) =>
- createElement(CommitFormTrigger, { props: { openModal: OPEN_REVERT_MODAL } }),
- });
-}
diff --git a/app/assets/javascripts/projects/commit/store/actions.js b/app/assets/javascripts/projects/commit/store/actions.js
index c72704303ca..2b25082eced 100644
--- a/app/assets/javascripts/projects/commit/store/actions.js
+++ b/app/assets/javascripts/projects/commit/store/actions.js
@@ -22,8 +22,8 @@ export const fetchBranches = ({ commit, dispatch, state }, query) => {
.get(state.branchesEndpoint, {
params: { search: query },
})
- .then(({ data }) => {
- commit(types.RECEIVE_BRANCHES_SUCCESS, data.Branches || []);
+ .then(({ data = [] }) => {
+ commit(types.RECEIVE_BRANCHES_SUCCESS, data.Branches?.length ? data.Branches : data);
})
.catch(() => {
createFlash({ message: PROJECT_BRANCHES_ERROR });
diff --git a/app/assets/javascripts/projects/commit_box/info/index.js b/app/assets/javascripts/projects/commit_box/info/index.js
index 17c63ecf66b..69fe2d30489 100644
--- a/app/assets/javascripts/projects/commit_box/info/index.js
+++ b/app/assets/javascripts/projects/commit_box/info/index.js
@@ -1,27 +1,17 @@
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
-import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
import { initCommitPipelineMiniGraph } from './init_commit_pipeline_mini_graph';
import { initDetailsButton } from './init_details_button';
import { loadBranches } from './load_branches';
-export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') => {
- const containerEl = document.querySelector(containerSelector);
-
+export const initCommitBoxInfo = () => {
// Display commit related branches
- loadBranches(containerEl);
+ loadBranches();
// Related merge requests to this commit
fetchCommitMergeRequests();
// Display pipeline mini graph for this commit
- // Feature flag ci_commit_pipeline_mini_graph_vue
- if (gon.features.ciCommitPipelineMiniGraphVue) {
- initCommitPipelineMiniGraph();
- } else {
- new MiniPipelineGraph({
- container: '.js-commit-pipeline-graph',
- }).bindEvents();
- }
+ initCommitPipelineMiniGraph();
initDetailsButton();
};
diff --git a/app/assets/javascripts/projects/commit_box/info/load_branches.js b/app/assets/javascripts/projects/commit_box/info/load_branches.js
index 8a0b2c30abe..d1136817cb3 100644
--- a/app/assets/javascripts/projects/commit_box/info/load_branches.js
+++ b/app/assets/javascripts/projects/commit_box/info/load_branches.js
@@ -2,7 +2,8 @@ import axios from 'axios';
import { sanitize } from '~/lib/dompurify';
import { __ } from '~/locale';
-export const loadBranches = (containerEl) => {
+export const loadBranches = (containerSelector = '.js-commit-box-info') => {
+ const containerEl = document.querySelector(containerSelector);
if (!containerEl) {
return;
}
diff --git a/app/assets/javascripts/projects/compare/components/app_legacy.vue b/app/assets/javascripts/projects/compare/components/app_legacy.vue
index c0ff58ee074..d3f09f7d69f 100644
--- a/app/assets/javascripts/projects/compare/components/app_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/app_legacy.vue
@@ -37,10 +37,22 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ from: this.paramsFrom,
+ to: this.paramsTo,
+ };
+ },
methods: {
onSubmit() {
this.$refs.form.submit();
},
+ onSwapRevision() {
+ [this.from, this.to] = [this.to, this.from]; // swaps 'from' and 'to'
+ },
+ onSelectRevision({ direction, revision }) {
+ this[direction] = revision; // direction is either 'from' or 'to'
+ },
},
};
</script>
@@ -57,19 +69,30 @@ export default {
:refs-project-path="refsProjectPath"
revision-text="Source"
params-name="to"
- :params-branch="paramsTo"
+ :params-branch="to"
+ data-testid="sourceRevisionDropdown"
+ @selectRevision="onSelectRevision"
/>
<div class="compare-ellipsis gl-display-inline" data-testid="ellipsis">...</div>
<revision-dropdown
:refs-project-path="refsProjectPath"
revision-text="Target"
params-name="from"
- :params-branch="paramsFrom"
+ :params-branch="from"
+ data-testid="targetRevisionDropdown"
+ @selectRevision="onSelectRevision"
/>
<gl-button category="primary" variant="success" class="gl-ml-3" @click="onSubmit">
{{ s__('CompareRevisions|Compare') }}
</gl-button>
<gl-button
+ data-testid="swapRevisionsButton"
+ class="btn btn-default gl-button gl-ml-3"
+ @click="onSwapRevision"
+ >
+ {{ s__('CompareRevisions|Swap revisions') }}
+ </gl-button>
+ <gl-button
v-if="projectMergeRequestPath"
:href="projectMergeRequestPath"
data-testid="projectMrButton"
diff --git a/app/assets/javascripts/projects/compare/components/repo_dropdown.vue b/app/assets/javascripts/projects/compare/components/repo_dropdown.vue
index 822dfc09d81..cb9d8b64b33 100644
--- a/app/assets/javascripts/projects/compare/components/repo_dropdown.vue
+++ b/app/assets/javascripts/projects/compare/components/repo_dropdown.vue
@@ -46,14 +46,7 @@ export default {
this.emitTargetProject(repo.name);
},
setDefaultRepo() {
- if (this.isSourceRevision) {
- this.selectedRepo = this.projectTo;
- return;
- }
-
- const [defaultTargetProject] = this.projectsFrom;
- this.emitTargetProject(defaultTargetProject.name);
- this.selectedRepo = defaultTargetProject;
+ this.selectedRepo = this.projectTo;
},
emitTargetProject(name) {
if (!this.isSourceRevision) {
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
index a175af2f32e..d0b69344c12 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue
@@ -1,10 +1,12 @@
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui';
+import { debounce } from 'lodash';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
-const emptyDropdownText = s__('CompareRevisions|Select branch/tag');
+const EMPTY_DROPDOWN_TEXT = s__('CompareRevisions|Select branch/tag');
+const SEARCH_DEBOUNCE_MS = 300;
export default {
components: {
@@ -38,19 +40,11 @@ export default {
};
},
computed: {
- filteredBranches() {
- return this.branches.filter((branch) =>
- branch.toLowerCase().includes(this.searchTerm.toLowerCase()),
- );
+ hasBranches() {
+ return Boolean(this.branches?.length);
},
- hasFilteredBranches() {
- return this.filteredBranches.length;
- },
- filteredTags() {
- return this.tags.filter((tag) => tag.toLowerCase().includes(this.searchTerm.toLowerCase()));
- },
- hasFilteredTags() {
- return this.filteredTags.length;
+ hasTags() {
+ return Boolean(this.tags?.length);
},
},
watch: {
@@ -59,13 +53,34 @@ export default {
this.fetchBranchesAndTags(true);
}
},
+ searchTerm: debounce(function debounceSearch() {
+ this.searchBranchesAndTags();
+ }, SEARCH_DEBOUNCE_MS),
},
mounted() {
this.fetchBranchesAndTags();
},
methods: {
+ searchBranchesAndTags() {
+ return axios
+ .get(this.refsProjectPath, {
+ params: {
+ search: this.searchTerm,
+ },
+ })
+ .then(({ data }) => {
+ this.branches = data.Branches || [];
+ this.tags = data.Tags || [];
+ })
+ .catch(() => {
+ createFlash({
+ message: s__(
+ 'CompareRevisions|There was an error while searching the branch/tag list. Please try again.',
+ ),
+ });
+ });
+ },
fetchBranchesAndTags(reset = false) {
- const endpoint = this.refsProjectPath;
this.loading = true;
if (reset) {
@@ -73,7 +88,7 @@ export default {
}
return axios
- .get(endpoint)
+ .get(this.refsProjectPath)
.then(({ data }) => {
this.branches = data.Branches || [];
this.tags = data.Tags || [];
@@ -90,7 +105,7 @@ export default {
});
},
getDefaultBranch() {
- return this.paramsBranch || emptyDropdownText;
+ return this.paramsBranch || EMPTY_DROPDOWN_TEXT;
},
onClick(revision) {
this.selectedRevision = revision;
@@ -119,24 +134,24 @@ export default {
@keyup.enter="onSearchEnter"
/>
</template>
- <gl-dropdown-section-header v-if="hasFilteredBranches">
+ <gl-dropdown-section-header v-if="hasBranches">
{{ s__('CompareRevisions|Branches') }}
</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(branch, index) in filteredBranches"
- :key="`branch${index}`"
+ v-for="branch in branches"
+ :key="branch"
is-check-item
:is-checked="selectedRevision === branch"
@click="onClick(branch)"
>
{{ branch }}
</gl-dropdown-item>
- <gl-dropdown-section-header v-if="hasFilteredTags">
+ <gl-dropdown-section-header v-if="hasTags">
{{ s__('CompareRevisions|Tags') }}
</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(tag, index) in filteredTags"
- :key="`tag${index}`"
+ v-for="tag in tags"
+ :key="tag"
is-check-item
:is-checked="selectedRevision === tag"
@click="onClick(tag)"
diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
index 13d80b5ae0b..f57a8942a77 100644
--- a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
+++ b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue
@@ -55,6 +55,11 @@ export default {
return this.filteredTags.length;
},
},
+ watch: {
+ paramsBranch(newBranch) {
+ this.setSelectedRevision(newBranch);
+ },
+ },
mounted() {
this.fetchBranchesAndTags();
},
@@ -83,10 +88,14 @@ export default {
return this.paramsBranch || s__('CompareRevisions|Select branch/tag');
},
onClick(revision) {
- this.selectedRevision = revision;
+ this.setSelectedRevision(revision);
},
onSearchEnter() {
- this.selectedRevision = this.searchTerm;
+ this.setSelectedRevision(this.searchTerm);
+ },
+ setSelectedRevision(revision) {
+ this.selectedRevision = revision || s__('CompareRevisions|Select branch/tag');
+ this.$emit('selectRevision', { direction: this.paramsName, revision });
},
},
};
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
index ef61fba88fe..1060b37067e 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue
@@ -1,8 +1,9 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlBreadcrumb, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { experiment } from '~/experimentation/utils';
import { __, s__ } from '~/locale';
-
+import { NEW_REPO_EXPERIMENT } from '../constants';
import blankProjectIllustration from '../illustrations/blank-project.svg';
import ciCdProjectIllustration from '../illustrations/ci-cd-project.svg';
import createFromTemplateIllustration from '../illustrations/create-from-template.svg';
@@ -13,8 +14,10 @@ import WelcomePage from './welcome.vue';
const BLANK_PANEL = 'blank_project';
const CI_CD_PANEL = 'cicd_for_external_repo';
const LAST_ACTIVE_TAB_KEY = 'new_project_last_active_tab';
+
const PANELS = [
{
+ key: 'blank',
name: BLANK_PANEL,
selector: '#blank-project-pane',
title: s__('ProjectsNew|Create blank project'),
@@ -24,6 +27,7 @@ const PANELS = [
illustration: blankProjectIllustration,
},
{
+ key: 'template',
name: 'create_from_template',
selector: '#create-from-template-pane',
title: s__('ProjectsNew|Create from template'),
@@ -33,6 +37,7 @@ const PANELS = [
illustration: createFromTemplateIllustration,
},
{
+ key: 'import',
name: 'import_project',
selector: '#import-project-pane',
title: s__('ProjectsNew|Import project'),
@@ -42,6 +47,7 @@ const PANELS = [
illustration: importProjectIllustration,
},
{
+ key: 'ci',
name: CI_CD_PANEL,
selector: '#ci-cd-project-pane',
title: s__('ProjectsNew|Run CI/CD for external repository'),
@@ -85,16 +91,34 @@ export default {
},
computed: {
+ decoratedPanels() {
+ const PANEL_TITLES = experiment(NEW_REPO_EXPERIMENT, {
+ use: () => ({
+ blank: s__('ProjectsNew|Create blank project'),
+ import: s__('ProjectsNew|Import project'),
+ }),
+ try: () => ({
+ blank: s__('ProjectsNew|Create blank project/repository'),
+ import: s__('ProjectsNew|Import project/repository'),
+ }),
+ });
+
+ return PANELS.map(({ key, title, ...el }) => ({
+ ...el,
+ title: PANEL_TITLES[key] !== undefined ? PANEL_TITLES[key] : title,
+ }));
+ },
+
availablePanels() {
if (this.isCiCdAvailable) {
- return PANELS;
+ return this.decoratedPanels;
}
- return PANELS.filter((p) => p.name !== CI_CD_PANEL);
+ return this.decoratedPanels.filter((p) => p.name !== CI_CD_PANEL);
},
activePanel() {
- return PANELS.find((p) => p.name === this.activeTab);
+ return this.decoratedPanels.find((p) => p.name === this.activeTab);
},
breadcrumbs() {
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
index ed82a635b1f..d342ce4c9c2 100644
--- a/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue
@@ -1,9 +1,10 @@
<script>
/* eslint-disable vue/no-v-html */
import Tracking from '~/tracking';
+import { NEW_REPO_EXPERIMENT } from '../constants';
import NewProjectPushTipPopover from './new_project_push_tip_popover.vue';
-const trackingMixin = Tracking.mixin(gon.tracking_data);
+const trackingMixin = Tracking.mixin({ ...gon.tracking_data, experiment: NEW_REPO_EXPERIMENT });
export default {
components: {
diff --git a/app/assets/javascripts/projects/experiment_new_project_creation/constants.js b/app/assets/javascripts/projects/experiment_new_project_creation/constants.js
new file mode 100644
index 00000000000..402ca887cf1
--- /dev/null
+++ b/app/assets/javascripts/projects/experiment_new_project_creation/constants.js
@@ -0,0 +1 @@
+export const NEW_REPO_EXPERIMENT = 'new_repo';
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 4a8e1424fa8..8d005373508 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -3,8 +3,6 @@ import { GlTabs, GlTab } from '@gitlab/ui';
import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import PipelineCharts from './pipeline_charts.vue';
-const charts = ['pipelines', 'deployments'];
-
export default {
components: {
GlTabs,
@@ -12,9 +10,11 @@ export default {
PipelineCharts,
DeploymentFrequencyCharts: () =>
import('ee_component/projects/pipelines/charts/components/deployment_frequency_charts.vue'),
+ LeadTimeCharts: () =>
+ import('ee_component/projects/pipelines/charts/components/lead_time_charts.vue'),
},
inject: {
- shouldRenderDeploymentFrequencyCharts: {
+ shouldRenderDoraCharts: {
type: Boolean,
default: false,
},
@@ -24,20 +24,31 @@ export default {
selectedTab: 0,
};
},
+ computed: {
+ charts() {
+ const chartsToShow = ['pipelines'];
+
+ if (this.shouldRenderDoraCharts) {
+ chartsToShow.push('deployments', 'lead-time');
+ }
+
+ return chartsToShow;
+ },
+ },
created() {
this.selectTab();
window.addEventListener('popstate', this.selectTab);
},
methods: {
selectTab() {
- const [chart] = getParameterValues('chart') || charts;
- const tab = charts.indexOf(chart);
+ const [chart] = getParameterValues('chart') || this.charts;
+ const tab = this.charts.indexOf(chart);
this.selectedTab = tab >= 0 ? tab : 0;
},
onTabChange(index) {
if (index !== this.selectedTab) {
this.selectedTab = index;
- const path = mergeUrlParams({ chart: charts[index] }, window.location.pathname);
+ const path = mergeUrlParams({ chart: this.charts[index] }, window.location.pathname);
updateHistory({ url: path, title: window.title });
}
},
@@ -46,13 +57,18 @@ export default {
</script>
<template>
<div>
- <gl-tabs v-if="shouldRenderDeploymentFrequencyCharts" :value="selectedTab" @input="onTabChange">
+ <gl-tabs v-if="charts.length > 1" :value="selectedTab" @input="onTabChange">
<gl-tab :title="__('Pipelines')">
<pipeline-charts />
</gl-tab>
- <gl-tab :title="__('Deployments')">
- <deployment-frequency-charts />
- </gl-tab>
+ <template v-if="shouldRenderDoraCharts">
+ <gl-tab :title="__('Deployments')">
+ <deployment-frequency-charts />
+ </gl-tab>
+ <gl-tab :title="__('Lead Time')">
+ <lead-time-charts />
+ </gl-tab>
+ </template>
</gl-tabs>
<pipeline-charts v-else />
</div>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
index 3590e2c4632..ad3e6713e45 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_area_chart.vue
@@ -30,12 +30,16 @@ export default {
<resizable-chart-container>
<gl-area-chart
slot-scope="{ width }"
+ v-bind="$attrs"
:width="width"
:height="$options.chartContainerHeight"
:data="chartData"
:include-legend-avg-max="false"
:option="areaChartOptions"
- />
+ >
+ <slot slot="tooltip-title" name="tooltip-title"></slot>
+ <slot slot="tooltip-content" name="tooltip-content"></slot>
+ </gl-area-chart>
</resizable-chart-container>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
index 43b36da8b2c..f4fd57e4cdc 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/ci_cd_analytics_charts.vue
@@ -41,10 +41,14 @@ export default {
<gl-segmented-control v-model="selectedChart" :options="chartRanges" class="gl-mb-4" />
<ci-cd-analytics-area-chart
v-if="chart"
+ v-bind="$attrs"
:chart-data="chart.data"
:area-chart-options="chartOptions"
>
{{ dateRange }}
+
+ <slot slot="tooltip-title" name="tooltip-title"></slot>
+ <slot slot="tooltip-content" name="tooltip-content"></slot>
</ci-cd-analytics-area-chart>
</div>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 7e746423b6a..5f5ee44c204 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -13,9 +13,7 @@ const apolloProvider = new VueApollo({
const mountPipelineChartsApp = (el) => {
const { projectPath } = el.dataset;
- const shouldRenderDeploymentFrequencyCharts = parseBoolean(
- el.dataset.shouldRenderDeploymentFrequencyCharts,
- );
+ const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
return new Vue({
el,
@@ -26,7 +24,7 @@ const mountPipelineChartsApp = (el) => {
apolloProvider,
provide: {
projectPath,
- shouldRenderDeploymentFrequencyCharts,
+ shouldRenderDoraCharts,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});