diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-12 18:09:17 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-01-12 18:09:17 +0300 |
commit | d549d413bb69f87ec26661ec96287bb4b25c32ff (patch) | |
tree | ac50717d0e3db25fd64bd36c1090496c42b24556 /app/assets/javascripts/repository | |
parent | 1caab68312013cae5083460ec8e03796daef9341 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/repository')
3 files changed, 179 insertions, 0 deletions
diff --git a/app/assets/javascripts/repository/components/fork_info.vue b/app/assets/javascripts/repository/components/fork_info.vue new file mode 100644 index 00000000000..980fa140eb5 --- /dev/null +++ b/app/assets/javascripts/repository/components/fork_info.vue @@ -0,0 +1,146 @@ +<script> +import { GlIcon, GlLink, GlSkeletonLoader } from '@gitlab/ui'; +import { s__, sprintf, n__ } from '~/locale'; +import { createAlert } from '~/flash'; +import forkDetailsQuery from '../queries/fork_details.query.graphql'; + +export const i18n = { + forkedFrom: s__('ForkedFromProjectPath|Forked from'), + inaccessibleProject: s__('ForkedFromProjectPath|Forked from an inaccessible project.'), + upToDate: s__('ForksDivergence|Up to date with the upstream repository.'), + unknown: s__('ForksDivergence|This fork has diverged from the upstream repository.'), + behind: s__('ForksDivergence|%{behind} %{commit_word} behind'), + ahead: s__('ForksDivergence|%{ahead} %{commit_word} ahead of'), + behindAndAhead: s__('ForksDivergence|%{messages} the upstream repository.'), + error: s__('ForksDivergence|Failed to fetch fork details. Try again later.'), +}; + +export default { + i18n, + components: { + GlIcon, + GlLink, + GlSkeletonLoader, + }, + apollo: { + project: { + query: forkDetailsQuery, + variables() { + return { + projectPath: this.projectPath, + ref: this.selectedRef, + }; + }, + skip() { + return !this.sourceName; + }, + error(error) { + createAlert({ + message: this.$options.i18n.error, + captureError: true, + error, + }); + }, + }, + }, + props: { + projectPath: { + type: String, + required: true, + }, + selectedRef: { + type: String, + required: true, + }, + sourceName: { + type: String, + required: false, + default: '', + }, + sourcePath: { + type: String, + required: false, + default: '', + }, + }, + data() { + return { + project: { + forkDetails: { + ahead: null, + behind: null, + }, + }, + }; + }, + computed: { + isLoading() { + return this.$apollo.queries.project.loading; + }, + ahead() { + return this.project?.forkDetails?.ahead; + }, + behind() { + return this.project?.forkDetails?.behind; + }, + behindText() { + return sprintf(this.$options.i18n.behind, { + behind: this.behind, + commit_word: n__('commit', 'commits', this.behind), + }); + }, + aheadText() { + return sprintf(this.$options.i18n.ahead, { + ahead: this.ahead, + commit_word: n__('commit', 'commits', this.ahead), + }); + }, + isUnknownDivergence() { + return (!this.ahead && this.ahead !== 0) || (!this.behind && this.behind !== 0); + }, + behindAheadMessage() { + const messages = []; + if (this.behind > 0) { + messages.push(this.behindText); + } + if (this.ahead > 0) { + messages.push(this.aheadText); + } + return messages.join(', '); + }, + hasBehindAheadMessage() { + return this.behindAheadMessage.length > 0; + }, + forkDivergenceMessage() { + if (this.isUnknownDivergence) { + return this.$options.i18n.unknown; + } + if (this.hasBehindAheadMessage) { + return sprintf(this.$options.i18n.behindAndAhead, { + messages: this.behindAheadMessage, + }); + } + return this.$options.i18n.upToDate; + }, + }, +}; +</script> + +<template> + <div class="info-well gl-sm-display-flex gl-flex-direction-column"> + <div class="well-segment gl-p-5 gl-w-full gl-display-flex"> + <gl-icon name="fork" :size="16" class="gl-display-block gl-m-4 gl-text-center" /> + <div v-if="sourceName"> + {{ $options.i18n.forkedFrom }} + <gl-link data-qa-selector="forked_from_link" :href="sourcePath">{{ sourceName }}</gl-link> + <gl-skeleton-loader v-if="isLoading" :lines="1" /> + <div v-else class="gl-text-secondary"> + {{ forkDivergenceMessage }} + </div> + </div> + <div v-else data-testid="inaccessible-project" class="gl-align-items-center gl-display-flex"> + {{ $options.i18n.inaccessibleProject }} + </div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js index e9214e3acff..e5d22f50d72 100644 --- a/app/assets/javascripts/repository/index.js +++ b/app/assets/javascripts/repository/index.js @@ -11,6 +11,7 @@ import RefSelector from '~/ref/components/ref_selector.vue'; import App from './components/app.vue'; import Breadcrumbs from './components/breadcrumbs.vue'; import DirectoryDownloadLinks from './components/directory_download_links.vue'; +import ForkInfo from './components/fork_info.vue'; import LastCommit from './components/last_commit.vue'; import BlobControls from './components/blob_controls.vue'; import apolloProvider from './graphql'; @@ -63,6 +64,28 @@ export default function setupVueRepositoryList() { }, }); + const initForkInfo = () => { + const forkEl = document.getElementById('js-fork-info'); + if (!forkEl) { + return null; + } + const { sourceName, sourcePath } = forkEl.dataset; + return new Vue({ + el: forkEl, + apolloProvider, + render(h) { + return h(ForkInfo, { + props: { + projectPath, + selectedRef: ref, + sourceName, + sourcePath, + }, + }); + }, + }); + }; + const initLastCommitApp = () => new Vue({ el: document.getElementById('js-last-commit'), @@ -118,6 +141,7 @@ export default function setupVueRepositoryList() { initLastCommitApp(); initBlobControlsApp(); + initForkInfo(); initRefSwitcher(); router.afterEach(({ params: { path } }) => { diff --git a/app/assets/javascripts/repository/queries/fork_details.query.graphql b/app/assets/javascripts/repository/queries/fork_details.query.graphql new file mode 100644 index 00000000000..d1a37d00d55 --- /dev/null +++ b/app/assets/javascripts/repository/queries/fork_details.query.graphql @@ -0,0 +1,9 @@ +query getForkDetails($projectPath: ID!, $ref: String) { + project(fullPath: $projectPath) { + id + forkDetails(ref: $ref) { + ahead + behind + } + } +} |