diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /app/assets/javascripts/projects/compare | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'app/assets/javascripts/projects/compare')
7 files changed, 536 insertions, 92 deletions
diff --git a/app/assets/javascripts/projects/compare/components/app.vue b/app/assets/javascripts/projects/compare/components/app.vue index 05bd0f1370b..d2fb524489e 100644 --- a/app/assets/javascripts/projects/compare/components/app.vue +++ b/app/assets/javascripts/projects/compare/components/app.vue @@ -1,12 +1,12 @@ <script> import { GlButton } from '@gitlab/ui'; import csrf from '~/lib/utils/csrf'; -import RevisionDropdown from './revision_dropdown.vue'; +import RevisionCard from './revision_card.vue'; export default { csrf, components: { - RevisionDropdown, + RevisionCard, GlButton, }, props: { @@ -48,42 +48,53 @@ export default { <template> <form ref="form" - class="form-inline js-requires-input js-signature-container" + class="js-requires-input js-signature-container" method="POST" :action="projectCompareIndexPath" > <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> - <revision-dropdown - :refs-project-path="refsProjectPath" - revision-text="Source" - params-name="to" - :params-branch="paramsTo" - /> - <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" - /> - <gl-button category="primary" variant="success" class="gl-ml-3" @click="onSubmit"> - {{ s__('CompareRevisions|Compare') }} - </gl-button> - <a - v-if="projectMergeRequestPath" - :href="projectMergeRequestPath" - data-testid="projectMrButton" - class="btn btn-default gl-button gl-ml-3" + <div + class="gl-lg-flex-direction-row gl-lg-display-flex gl-align-items-center compare-revision-cards" > - {{ s__('CompareRevisions|View open merge request') }} - </a> - <a - v-else-if="createMrPath" - :href="createMrPath" - data-testid="createMrButton" - class="btn btn-default gl-button gl-ml-3" - > - {{ s__('CompareRevisions|Create merge request') }} - </a> + <revision-card + :refs-project-path="refsProjectPath" + revision-text="Source" + params-name="to" + :params-branch="paramsTo" + /> + <div + class="compare-ellipsis gl-display-flex gl-justify-content-center gl-align-items-center gl-my-4 gl-md-my-0" + data-testid="ellipsis" + > + ... + </div> + <revision-card + :refs-project-path="refsProjectPath" + revision-text="Target" + params-name="from" + :params-branch="paramsFrom" + /> + </div> + <div class="gl-mt-4"> + <gl-button category="primary" variant="success" @click="onSubmit"> + {{ s__('CompareRevisions|Compare') }} + </gl-button> + <gl-button + v-if="projectMergeRequestPath" + :href="projectMergeRequestPath" + data-testid="projectMrButton" + class="btn btn-default gl-button" + > + {{ s__('CompareRevisions|View open merge request') }} + </gl-button> + <gl-button + v-else-if="createMrPath" + :href="createMrPath" + data-testid="createMrButton" + class="btn btn-default gl-button" + > + {{ s__('CompareRevisions|Create merge request') }} + </gl-button> + </div> </form> </template> diff --git a/app/assets/javascripts/projects/compare/components/app_legacy.vue b/app/assets/javascripts/projects/compare/components/app_legacy.vue new file mode 100644 index 00000000000..c0ff58ee074 --- /dev/null +++ b/app/assets/javascripts/projects/compare/components/app_legacy.vue @@ -0,0 +1,89 @@ +<script> +import { GlButton } from '@gitlab/ui'; +import csrf from '~/lib/utils/csrf'; +import RevisionDropdown from './revision_dropdown_legacy.vue'; + +export default { + csrf, + components: { + RevisionDropdown, + GlButton, + }, + props: { + projectCompareIndexPath: { + type: String, + required: true, + }, + refsProjectPath: { + type: String, + required: true, + }, + paramsFrom: { + type: String, + required: false, + default: null, + }, + paramsTo: { + type: String, + required: false, + default: null, + }, + projectMergeRequestPath: { + type: String, + required: true, + }, + createMrPath: { + type: String, + required: true, + }, + }, + methods: { + onSubmit() { + this.$refs.form.submit(); + }, + }, +}; +</script> + +<template> + <form + ref="form" + class="form-inline js-requires-input js-signature-container" + method="POST" + :action="projectCompareIndexPath" + > + <input :value="$options.csrf.token" type="hidden" name="authenticity_token" /> + <revision-dropdown + :refs-project-path="refsProjectPath" + revision-text="Source" + params-name="to" + :params-branch="paramsTo" + /> + <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" + /> + <gl-button category="primary" variant="success" class="gl-ml-3" @click="onSubmit"> + {{ s__('CompareRevisions|Compare') }} + </gl-button> + <gl-button + v-if="projectMergeRequestPath" + :href="projectMergeRequestPath" + data-testid="projectMrButton" + class="btn btn-default gl-button gl-ml-3" + > + {{ s__('CompareRevisions|View open merge request') }} + </gl-button> + <gl-button + v-else-if="createMrPath" + :href="createMrPath" + data-testid="createMrButton" + class="btn btn-default gl-button gl-ml-3" + > + {{ s__('CompareRevisions|Create merge request') }} + </gl-button> + </form> +</template> diff --git a/app/assets/javascripts/projects/compare/components/repo_dropdown.vue b/app/assets/javascripts/projects/compare/components/repo_dropdown.vue new file mode 100644 index 00000000000..822dfc09d81 --- /dev/null +++ b/app/assets/javascripts/projects/compare/components/repo_dropdown.vue @@ -0,0 +1,93 @@ +<script> +import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui'; + +const SOURCE_PARAM_NAME = 'to'; + +export default { + components: { + GlDropdown, + GlDropdownItem, + GlSearchBoxByType, + }, + inject: ['projectTo', 'projectsFrom'], + props: { + paramsName: { + type: String, + required: true, + }, + }, + data() { + return { + searchTerm: '', + selectedRepo: {}, + }; + }, + computed: { + filteredRepos() { + const lowerCaseSearchTerm = this.searchTerm.toLowerCase(); + + return this?.projectsFrom.filter(({ name }) => + name.toLowerCase().includes(lowerCaseSearchTerm), + ); + }, + isSourceRevision() { + return this.paramsName === SOURCE_PARAM_NAME; + }, + inputName() { + return `${this.paramsName}_project_id`; + }, + }, + mounted() { + this.setDefaultRepo(); + }, + methods: { + onClick(repo) { + this.selectedRepo = repo; + this.emitTargetProject(repo.name); + }, + setDefaultRepo() { + if (this.isSourceRevision) { + this.selectedRepo = this.projectTo; + return; + } + + const [defaultTargetProject] = this.projectsFrom; + this.emitTargetProject(defaultTargetProject.name); + this.selectedRepo = defaultTargetProject; + }, + emitTargetProject(name) { + if (!this.isSourceRevision) { + this.$emit('changeTargetProject', name); + } + }, + }, +}; +</script> + +<template> + <div> + <input type="hidden" :name="inputName" :value="selectedRepo.id" /> + <gl-dropdown + :text="selectedRepo.name" + :header-text="s__(`CompareRevisions|Select target project`)" + class="gl-w-full gl-font-monospace gl-sm-pr-3" + toggle-class="gl-min-w-0" + :disabled="isSourceRevision" + > + <template #header> + <gl-search-box-by-type v-if="!isSourceRevision" v-model.trim="searchTerm" /> + </template> + <template v-if="!isSourceRevision"> + <gl-dropdown-item + v-for="repo in filteredRepos" + :key="repo.id" + is-check-item + :is-checked="selectedRepo.id === repo.id" + @click="onClick(repo)" + > + {{ repo.name }} + </gl-dropdown-item> + </template> + </gl-dropdown> + </div> +</template> diff --git a/app/assets/javascripts/projects/compare/components/revision_card.vue b/app/assets/javascripts/projects/compare/components/revision_card.vue new file mode 100644 index 00000000000..15d24792310 --- /dev/null +++ b/app/assets/javascripts/projects/compare/components/revision_card.vue @@ -0,0 +1,65 @@ +<script> +import { GlCard } from '@gitlab/ui'; +import RepoDropdown from './repo_dropdown.vue'; +import RevisionDropdown from './revision_dropdown.vue'; + +export default { + components: { + RepoDropdown, + RevisionDropdown, + GlCard, + }, + props: { + refsProjectPath: { + type: String, + required: true, + }, + revisionText: { + type: String, + required: true, + }, + paramsName: { + type: String, + required: true, + }, + paramsBranch: { + type: String, + required: false, + default: null, + }, + }, + data() { + return { + selectedRefsProjectPath: this.refsProjectPath, + }; + }, + methods: { + onChangeTargetProject(targetProjectName) { + if (this.paramsName === 'from') { + this.selectedRefsProjectPath = `/${targetProjectName}/refs`; + } + }, + }, +}; +</script> + +<template> + <gl-card header-class="gl-py-2 gl-px-3 gl-font-weight-bold" body-class="gl-px-3"> + <template #header> + {{ s__(`CompareRevisions|${revisionText}`) }} + </template> + <div class="gl-sm-display-flex gl-align-items-center"> + <repo-dropdown + class="gl-sm-w-half" + :params-name="paramsName" + @changeTargetProject="onChangeTargetProject" + /> + <revision-dropdown + class="gl-sm-w-half gl-mt-3 gl-sm-mt-0" + :refs-project-path="selectedRefsProjectPath" + :params-name="paramsName" + :params-branch="paramsBranch" + /> + </div> + </gl-card> +</template> diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue index 13d80b5ae0b..a175af2f32e 100644 --- a/app/assets/javascripts/projects/compare/components/revision_dropdown.vue +++ b/app/assets/javascripts/projects/compare/components/revision_dropdown.vue @@ -4,6 +4,8 @@ import createFlash from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { s__ } from '~/locale'; +const emptyDropdownText = s__('CompareRevisions|Select branch/tag'); + export default { components: { GlDropdown, @@ -16,10 +18,6 @@ export default { type: String, required: true, }, - revisionText: { - type: String, - required: true, - }, paramsName: { type: String, required: true, @@ -55,12 +53,24 @@ export default { return this.filteredTags.length; }, }, + watch: { + refsProjectPath(newRefsProjectPath, oldRefsProjectPath) { + if (newRefsProjectPath !== oldRefsProjectPath) { + this.fetchBranchesAndTags(true); + } + }, + }, mounted() { this.fetchBranchesAndTags(); }, methods: { - fetchBranchesAndTags() { + fetchBranchesAndTags(reset = false) { const endpoint = this.refsProjectPath; + this.loading = true; + + if (reset) { + this.selectedRevision = this.getDefaultBranch(); + } return axios .get(endpoint) @@ -70,9 +80,9 @@ export default { }) .catch(() => { createFlash({ - message: `${s__( - 'CompareRevisions|There was an error while updating the branch/tag list. Please try again.', - )}`, + message: s__( + 'CompareRevisions|There was an error while loading the branch/tag list. Please try again.', + ), }); }) .finally(() => { @@ -80,7 +90,7 @@ export default { }); }, getDefaultBranch() { - return this.paramsBranch || s__('CompareRevisions|Select branch/tag'); + return this.paramsBranch || emptyDropdownText; }, onClick(revision) { this.selectedRevision = revision; @@ -93,53 +103,46 @@ export default { </script> <template> - <div class="form-group compare-form-group" :class="`js-compare-${paramsName}-dropdown`"> - <div class="input-group inline-input-group"> - <span class="input-group-prepend"> - <div class="input-group-text"> - {{ revisionText }} - </div> - </span> - <input type="hidden" :name="paramsName" :value="selectedRevision" /> - <gl-dropdown - class="gl-flex-grow-1 gl-flex-basis-0 gl-min-w-0 gl-font-monospace" - toggle-class="form-control compare-dropdown-toggle js-compare-dropdown gl-min-w-0 gl-rounded-top-left-none! gl-rounded-bottom-left-none!" - :text="selectedRevision" - header-text="Select Git revision" - :loading="loading" + <div :class="`js-compare-${paramsName}-dropdown`"> + <input type="hidden" :name="paramsName" :value="selectedRevision" /> + <gl-dropdown + class="gl-w-full gl-font-monospace" + toggle-class="form-control compare-dropdown-toggle js-compare-dropdown gl-min-w-0" + :text="selectedRevision" + :header-text="s__('CompareRevisions|Select Git revision')" + :loading="loading" + > + <template #header> + <gl-search-box-by-type + v-model.trim="searchTerm" + :placeholder="s__('CompareRevisions|Filter by Git revision')" + @keyup.enter="onSearchEnter" + /> + </template> + <gl-dropdown-section-header v-if="hasFilteredBranches"> + {{ s__('CompareRevisions|Branches') }} + </gl-dropdown-section-header> + <gl-dropdown-item + v-for="(branch, index) in filteredBranches" + :key="`branch${index}`" + is-check-item + :is-checked="selectedRevision === branch" + @click="onClick(branch)" + > + {{ branch }} + </gl-dropdown-item> + <gl-dropdown-section-header v-if="hasFilteredTags"> + {{ s__('CompareRevisions|Tags') }} + </gl-dropdown-section-header> + <gl-dropdown-item + v-for="(tag, index) in filteredTags" + :key="`tag${index}`" + is-check-item + :is-checked="selectedRevision === tag" + @click="onClick(tag)" > - <template #header> - <gl-search-box-by-type - v-model.trim="searchTerm" - :placeholder="s__('CompareRevisions|Filter by Git revision')" - @keyup.enter="onSearchEnter" - /> - </template> - <gl-dropdown-section-header v-if="hasFilteredBranches"> - {{ s__('CompareRevisions|Branches') }} - </gl-dropdown-section-header> - <gl-dropdown-item - v-for="(branch, index) in filteredBranches" - :key="`branch${index}`" - is-check-item - :is-checked="selectedRevision === branch" - @click="onClick(branch)" - > - {{ branch }} - </gl-dropdown-item> - <gl-dropdown-section-header v-if="hasFilteredTags"> - {{ s__('CompareRevisions|Tags') }} - </gl-dropdown-section-header> - <gl-dropdown-item - v-for="(tag, index) in filteredTags" - :key="`tag${index}`" - is-check-item - :is-checked="selectedRevision === tag" - @click="onClick(tag)" - > - {{ tag }} - </gl-dropdown-item> - </gl-dropdown> - </div> + {{ tag }} + </gl-dropdown-item> + </gl-dropdown> </div> </template> diff --git a/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue new file mode 100644 index 00000000000..13d80b5ae0b --- /dev/null +++ b/app/assets/javascripts/projects/compare/components/revision_dropdown_legacy.vue @@ -0,0 +1,145 @@ +<script> +import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlDropdownSectionHeader } from '@gitlab/ui'; +import createFlash from '~/flash'; +import axios from '~/lib/utils/axios_utils'; +import { s__ } from '~/locale'; + +export default { + components: { + GlDropdown, + GlDropdownItem, + GlDropdownSectionHeader, + GlSearchBoxByType, + }, + props: { + refsProjectPath: { + type: String, + required: true, + }, + revisionText: { + type: String, + required: true, + }, + paramsName: { + type: String, + required: true, + }, + paramsBranch: { + type: String, + required: false, + default: null, + }, + }, + data() { + return { + branches: [], + tags: [], + loading: true, + searchTerm: '', + selectedRevision: this.getDefaultBranch(), + }; + }, + computed: { + filteredBranches() { + return this.branches.filter((branch) => + branch.toLowerCase().includes(this.searchTerm.toLowerCase()), + ); + }, + hasFilteredBranches() { + return this.filteredBranches.length; + }, + filteredTags() { + return this.tags.filter((tag) => tag.toLowerCase().includes(this.searchTerm.toLowerCase())); + }, + hasFilteredTags() { + return this.filteredTags.length; + }, + }, + mounted() { + this.fetchBranchesAndTags(); + }, + methods: { + fetchBranchesAndTags() { + const endpoint = this.refsProjectPath; + + return axios + .get(endpoint) + .then(({ data }) => { + this.branches = data.Branches || []; + this.tags = data.Tags || []; + }) + .catch(() => { + createFlash({ + message: `${s__( + 'CompareRevisions|There was an error while updating the branch/tag list. Please try again.', + )}`, + }); + }) + .finally(() => { + this.loading = false; + }); + }, + getDefaultBranch() { + return this.paramsBranch || s__('CompareRevisions|Select branch/tag'); + }, + onClick(revision) { + this.selectedRevision = revision; + }, + onSearchEnter() { + this.selectedRevision = this.searchTerm; + }, + }, +}; +</script> + +<template> + <div class="form-group compare-form-group" :class="`js-compare-${paramsName}-dropdown`"> + <div class="input-group inline-input-group"> + <span class="input-group-prepend"> + <div class="input-group-text"> + {{ revisionText }} + </div> + </span> + <input type="hidden" :name="paramsName" :value="selectedRevision" /> + <gl-dropdown + class="gl-flex-grow-1 gl-flex-basis-0 gl-min-w-0 gl-font-monospace" + toggle-class="form-control compare-dropdown-toggle js-compare-dropdown gl-min-w-0 gl-rounded-top-left-none! gl-rounded-bottom-left-none!" + :text="selectedRevision" + header-text="Select Git revision" + :loading="loading" + > + <template #header> + <gl-search-box-by-type + v-model.trim="searchTerm" + :placeholder="s__('CompareRevisions|Filter by Git revision')" + @keyup.enter="onSearchEnter" + /> + </template> + <gl-dropdown-section-header v-if="hasFilteredBranches"> + {{ s__('CompareRevisions|Branches') }} + </gl-dropdown-section-header> + <gl-dropdown-item + v-for="(branch, index) in filteredBranches" + :key="`branch${index}`" + is-check-item + :is-checked="selectedRevision === branch" + @click="onClick(branch)" + > + {{ branch }} + </gl-dropdown-item> + <gl-dropdown-section-header v-if="hasFilteredTags"> + {{ s__('CompareRevisions|Tags') }} + </gl-dropdown-section-header> + <gl-dropdown-item + v-for="(tag, index) in filteredTags" + :key="`tag${index}`" + is-check-item + :is-checked="selectedRevision === tag" + @click="onClick(tag)" + > + {{ tag }} + </gl-dropdown-item> + </gl-dropdown> + </div> + </div> +</template> diff --git a/app/assets/javascripts/projects/compare/index.js b/app/assets/javascripts/projects/compare/index.js index 4337eecb667..4ba4e308cd4 100644 --- a/app/assets/javascripts/projects/compare/index.js +++ b/app/assets/javascripts/projects/compare/index.js @@ -1,8 +1,46 @@ import Vue from 'vue'; import CompareApp from './components/app.vue'; +import CompareAppLegacy from './components/app_legacy.vue'; export default function init() { const el = document.getElementById('js-compare-selector'); + + if (gon.features?.compareRepoDropdown) { + const { + refsProjectPath, + paramsFrom, + paramsTo, + projectCompareIndexPath, + projectMergeRequestPath, + createMrPath, + projectTo, + projectsFrom, + } = el.dataset; + + return new Vue({ + el, + components: { + CompareApp, + }, + provide: { + projectTo: JSON.parse(projectTo), + projectsFrom: JSON.parse(projectsFrom), + }, + render(createElement) { + return createElement(CompareApp, { + props: { + refsProjectPath, + paramsFrom, + paramsTo, + projectCompareIndexPath, + projectMergeRequestPath, + createMrPath, + }, + }); + }, + }); + } + const { refsProjectPath, paramsFrom, @@ -15,10 +53,10 @@ export default function init() { return new Vue({ el, components: { - CompareApp, + CompareAppLegacy, }, render(createElement) { - return createElement(CompareApp, { + return createElement(CompareAppLegacy, { props: { refsProjectPath, paramsFrom, |