diff options
Diffstat (limited to 'app/assets/javascripts/packages')
7 files changed, 216 insertions, 101 deletions
diff --git a/app/assets/javascripts/packages/details/components/app.vue b/app/assets/javascripts/packages/details/components/app.vue index af3220840a6..c9f1c8b903c 100644 --- a/app/assets/javascripts/packages/details/components/app.vue +++ b/app/assets/javascripts/packages/details/components/app.vue @@ -5,29 +5,26 @@ import { GlModal, GlModalDirective, GlTooltipDirective, - GlLink, GlEmptyState, GlTab, GlTabs, - GlTable, GlSprintf, } from '@gitlab/ui'; import { mapActions, mapState } from 'vuex'; import Tracking from '~/tracking'; +import { s__ } from '~/locale'; +import { objectToQueryString } from '~/lib/utils/common_utils'; +import { numberToHumanSize } from '~/lib/utils/number_utils'; import PackageHistory from './package_history.vue'; import PackageTitle from './package_title.vue'; import PackagesListLoader from '../../shared/components/packages_list_loader.vue'; import PackageListRow from '../../shared/components/package_list_row.vue'; +import { packageTypeToTrackCategory } from '../../shared/utils'; +import { PackageType, TrackingActions, SHOW_DELETE_SUCCESS_ALERT } from '../../shared/constants'; import DependencyRow from './dependency_row.vue'; import AdditionalMetadata from './additional_metadata.vue'; import InstallationCommands from './installation_commands.vue'; -import { numberToHumanSize } from '~/lib/utils/number_utils'; -import timeagoMixin from '~/vue_shared/mixins/timeago'; -import FileIcon from '~/vue_shared/components/file_icon.vue'; -import { __, s__ } from '~/locale'; -import { PackageType, TrackingActions, SHOW_DELETE_SUCCESS_ALERT } from '../../shared/constants'; -import { packageTypeToTrackCategory } from '../../shared/utils'; -import { objectToQueryString } from '~/lib/utils/common_utils'; +import PackageFiles from './package_files.vue'; export default { name: 'PackagesApp', @@ -35,12 +32,9 @@ export default { GlBadge, GlButton, GlEmptyState, - GlLink, GlModal, GlTab, GlTabs, - GlTable, - FileIcon, GlSprintf, PackageTitle, PackagesListLoader, @@ -49,12 +43,13 @@ export default { PackageHistory, AdditionalMetadata, InstallationCommands, + PackageFiles, }, directives: { GlTooltip: GlTooltipDirective, GlModal: GlModalDirective, }, - mixins: [timeagoMixin, Tracking.mixin()], + mixins: [Tracking.mixin()], trackingActions: { ...TrackingActions }, computed: { ...mapState([ @@ -72,14 +67,6 @@ export default { isValidPackage() { return Boolean(this.packageEntity.name); }, - filesTableRows() { - return this.packageFiles.map(x => ({ - name: x.file_name, - downloadPath: x.download_path, - size: this.formatSize(x.size), - created: x.created_at, - })); - }, tracking() { return { category: packageTypeToTrackCategory(this.packageEntity.package_type), @@ -128,22 +115,6 @@ export default { `PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?`, ), }, - filesTableHeaderFields: [ - { - key: 'name', - label: __('Name'), - tdClass: 'd-flex align-items-center', - }, - { - key: 'size', - label: __('Size'), - }, - { - key: 'created', - label: __('Created'), - class: 'text-right', - }, - ], }; </script> @@ -185,35 +156,11 @@ export default { <additional-metadata :package-entity="packageEntity" /> </div> - <template v-if="showFiles"> - <h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3> - <gl-table - :fields="$options.filesTableHeaderFields" - :items="filesTableRows" - tbody-tr-class="js-file-row" - > - <template #cell(name)="{ item }"> - <gl-link - :href="item.downloadPath" - class="js-file-download gl-relative" - @click="track($options.trackingActions.PULL_PACKAGE)" - > - <file-icon - :file-name="item.name" - css-classes="gl-relative file-icon" - class="gl-mr-1 gl-relative" - /> - <span class="gl-relative">{{ item.name }}</span> - </gl-link> - </template> - - <template #cell(created)="{ item }"> - <span v-gl-tooltip :title="tooltipTitle(item.created)">{{ - timeFormatted(item.created) - }}</span> - </template> - </gl-table> - </template> + <package-files + v-if="showFiles" + :package-files="packageFiles" + @download-file="track($options.trackingActions.PULL_PACKAGE)" + /> </gl-tab> <gl-tab v-if="showDependencies" title-item-class="js-dependencies-tab"> diff --git a/app/assets/javascripts/packages/details/components/package_files.vue b/app/assets/javascripts/packages/details/components/package_files.vue new file mode 100644 index 00000000000..ab46dd0114d --- /dev/null +++ b/app/assets/javascripts/packages/details/components/package_files.vue @@ -0,0 +1,107 @@ +<script> +import { GlLink, GlTable } from '@gitlab/ui'; +import { last } from 'lodash'; +import { __ } from '~/locale'; +import Tracking from '~/tracking'; +import { numberToHumanSize } from '~/lib/utils/number_utils'; +import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import FileIcon from '~/vue_shared/components/file_icon.vue'; + +export default { + name: 'PackageFiles', + components: { + GlLink, + GlTable, + FileIcon, + TimeAgoTooltip, + }, + mixins: [Tracking.mixin()], + props: { + packageFiles: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + filesTableRows() { + return this.packageFiles.map(pf => ({ + ...pf, + size: this.formatSize(pf.size), + pipeline: last(pf.pipelines), + })); + }, + showCommitColumn() { + return this.filesTableRows.some(row => Boolean(row.pipeline?.id)); + }, + filesTableHeaderFields() { + return [ + { + key: 'name', + label: __('Name'), + tdClass: 'gl-display-flex gl-align-items-center', + }, + { + key: 'commit', + label: __('Commit'), + hide: !this.showCommitColumn, + }, + { + key: 'size', + label: __('Size'), + }, + { + key: 'created', + label: __('Created'), + class: 'gl-text-right', + }, + ].filter(c => !c.hide); + }, + }, + methods: { + formatSize(size) { + return numberToHumanSize(size); + }, + }, +}; +</script> + +<template> + <div> + <h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3> + <gl-table + :fields="filesTableHeaderFields" + :items="filesTableRows" + :tbody-tr-attr="{ 'data-testid': 'file-row' }" + > + <template #cell(name)="{ item }"> + <gl-link + :href="item.download_path" + class="gl-relative gl-text-gray-500" + data-testid="download-link" + @click="$emit('download-file')" + > + <file-icon + :file-name="item.file_name" + css-classes="gl-relative file-icon" + class="gl-mr-1 gl-relative" + /> + <span class="gl-relative">{{ item.file_name }}</span> + </gl-link> + </template> + + <template #cell(commit)="{item}"> + <gl-link + :href="item.pipeline.project.commit_url" + class="gl-text-gray-500" + data-testid="commit-link" + >{{ item.pipeline.git_commit_message }}</gl-link + > + </template> + + <template #cell(created)="{ item }"> + <time-ago-tooltip :time="item.created_at" /> + </template> + </gl-table> + </div> +</template> diff --git a/app/assets/javascripts/packages/details/components/package_history.vue b/app/assets/javascripts/packages/details/components/package_history.vue index 413ab1d15cb..62550602428 100644 --- a/app/assets/javascripts/packages/details/components/package_history.vue +++ b/app/assets/javascripts/packages/details/components/package_history.vue @@ -1,17 +1,26 @@ <script> import { GlLink, GlSprintf } from '@gitlab/ui'; -import { s__ } from '~/locale'; +import { first } from 'lodash'; +import { s__, n__ } from '~/locale'; +import { truncateSha } from '~/lib/utils/text_utility'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import HistoryItem from '~/vue_shared/components/registry/history_item.vue'; +import { HISTORY_PIPELINES_LIMIT } from '~/packages/details/constants'; export default { name: 'PackageHistory', i18n: { - createdOn: s__('PackageRegistry|%{name} version %{version} was created %{datetime}'), - updatedAtText: s__('PackageRegistry|%{name} version %{version} was updated %{datetime}'), - commitText: s__('PackageRegistry|Commit %{link} on branch %{branch}'), - pipelineText: s__('PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}'), + createdOn: s__('PackageRegistry|%{name} version %{version} was first created %{datetime}'), + createdByCommitText: s__('PackageRegistry|Created by commit %{link} on branch %{branch}'), + createdByPipelineText: s__( + 'PackageRegistry|Built by pipeline %{link} triggered %{datetime} by %{author}', + ), publishText: s__('PackageRegistry|Published to the %{project} Package Registry %{datetime}'), + combinedUpdateText: s__( + 'PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}', + ), + archivedPipelineMessageSingular: s__('PackageRegistry|Package has %{number} archived update'), + archivedPipelineMessagePlural: s__('PackageRegistry|Package has %{number} archived updates'), }, components: { GlLink, @@ -35,8 +44,32 @@ export default { }; }, computed: { - packagePipeline() { - return this.packageEntity.pipeline?.id ? this.packageEntity.pipeline : null; + pipelines() { + return this.packageEntity.pipelines || []; + }, + firstPipeline() { + return first(this.pipelines); + }, + lastPipelines() { + return this.pipelines.slice(1).slice(-HISTORY_PIPELINES_LIMIT); + }, + showPipelinesInfo() { + return Boolean(this.firstPipeline?.id); + }, + archiviedLines() { + return Math.max(this.pipelines.length - HISTORY_PIPELINES_LIMIT - 1, 0); + }, + archivedPipelineMessage() { + return n__( + this.$options.i18n.archivedPipelineMessageSingular, + this.$options.i18n.archivedPipelineMessagePlural, + this.archiviedLines, + ); + }, + }, + methods: { + truncate(value) { + return truncateSha(value); }, }, }; @@ -59,46 +92,35 @@ export default { </template> </gl-sprintf> </history-item> - <history-item icon="pencil" data-testid="updated-at"> - <gl-sprintf :message="$options.i18n.updatedAtText"> - <template #name> - <strong>{{ packageEntity.name }}</strong> - </template> - <template #version> - <strong>{{ packageEntity.version }}</strong> - </template> - <template #datetime> - <time-ago-tooltip :time="packageEntity.updated_at" /> - </template> - </gl-sprintf> - </history-item> - <template v-if="packagePipeline"> - <history-item icon="commit" data-testid="commit"> - <gl-sprintf :message="$options.i18n.commitText"> + + <template v-if="showPipelinesInfo"> + <!-- FIRST PIPELINE BLOCK --> + <history-item icon="commit" data-testid="first-pipeline-commit"> + <gl-sprintf :message="$options.i18n.createdByCommitText"> <template #link> - <gl-link :href="packagePipeline.project.commit_url">{{ - packagePipeline.sha - }}</gl-link> + <gl-link :href="firstPipeline.project.commit_url" + >#{{ truncate(firstPipeline.sha) }}</gl-link + > </template> <template #branch> - <strong>{{ packagePipeline.ref }}</strong> + <strong>{{ firstPipeline.ref }}</strong> </template> </gl-sprintf> </history-item> - <history-item icon="pipeline" data-testid="pipeline"> - <gl-sprintf :message="$options.i18n.pipelineText"> + <history-item icon="pipeline" data-testid="first-pipeline-pipeline"> + <gl-sprintf :message="$options.i18n.createdByPipelineText"> <template #link> - <gl-link :href="packagePipeline.project.pipeline_url" - >#{{ packagePipeline.id }}</gl-link - > + <gl-link :href="firstPipeline.project.pipeline_url">#{{ firstPipeline.id }}</gl-link> </template> <template #datetime> - <time-ago-tooltip :time="packagePipeline.created_at" /> + <time-ago-tooltip :time="firstPipeline.created_at" /> </template> - <template #author>{{ packagePipeline.user.name }}</template> + <template #author>{{ firstPipeline.user.name }}</template> </gl-sprintf> </history-item> </template> + + <!-- PUBLISHED LINE --> <history-item icon="package" data-testid="published"> <gl-sprintf :message="$options.i18n.publishText"> <template #project> @@ -109,6 +131,37 @@ export default { </template> </gl-sprintf> </history-item> + + <history-item v-if="archiviedLines" icon="history" data-testid="archived"> + <gl-sprintf :message="archivedPipelineMessage"> + <template #number> + <strong>{{ archiviedLines }}</strong> + </template> + </gl-sprintf> + </history-item> + + <!-- PIPELINES LIST ENTRIES --> + <history-item + v-for="pipeline in lastPipelines" + :key="pipeline.id" + icon="pencil" + data-testid="pipeline-entry" + > + <gl-sprintf :message="$options.i18n.combinedUpdateText"> + <template #link> + <gl-link :href="pipeline.project.commit_url">#{{ truncate(pipeline.sha) }}</gl-link> + </template> + <template #branch> + <strong>{{ pipeline.ref }}</strong> + </template> + <template #pipeline> + <gl-link :href="pipeline.project.pipeline_url">#{{ pipeline.id }}</gl-link> + </template> + <template #datetime> + <time-ago-tooltip :time="pipeline.created_at" /> + </template> + </gl-sprintf> + </history-item> </ul> </div> </template> diff --git a/app/assets/javascripts/packages/details/constants.js b/app/assets/javascripts/packages/details/constants.js index c6e1b388132..986b0667356 100644 --- a/app/assets/javascripts/packages/details/constants.js +++ b/app/assets/javascripts/packages/details/constants.js @@ -45,3 +45,5 @@ export const NpmManager = { export const FETCH_PACKAGE_VERSIONS_ERROR = s__( 'PackageRegistry|Unable to fetch package version information.', ); + +export const HISTORY_PIPELINES_LIMIT = 5; diff --git a/app/assets/javascripts/packages/list/constants.js b/app/assets/javascripts/packages/list/constants.js index 6a0e92bff2d..e14696e0d1c 100644 --- a/app/assets/javascripts/packages/list/constants.js +++ b/app/assets/javascripts/packages/list/constants.js @@ -68,6 +68,10 @@ export const PACKAGE_REGISTRY_TABS = [ title: s__('PackageRegistry|Conan'), type: PackageType.CONAN, }, + { + title: s__('PackageRegistry|Generic'), + type: PackageType.GENERIC, + }, { title: s__('PackageRegistry|Maven'), diff --git a/app/assets/javascripts/packages/shared/constants.js b/app/assets/javascripts/packages/shared/constants.js index c481abd8658..c0f7f150337 100644 --- a/app/assets/javascripts/packages/shared/constants.js +++ b/app/assets/javascripts/packages/shared/constants.js @@ -7,6 +7,7 @@ export const PackageType = { NUGET: 'nuget', PYPI: 'pypi', COMPOSER: 'composer', + GENERIC: 'generic', }; export const TrackingActions = { diff --git a/app/assets/javascripts/packages/shared/utils.js b/app/assets/javascripts/packages/shared/utils.js index b0807558266..d7a883e4397 100644 --- a/app/assets/javascripts/packages/shared/utils.js +++ b/app/assets/javascripts/packages/shared/utils.js @@ -21,7 +21,8 @@ export const getPackageTypeLabel = packageType => { return s__('PackageType|PyPI'); case PackageType.COMPOSER: return s__('PackageType|Composer'); - + case PackageType.GENERIC: + return s__('PackageType|Generic'); default: return null; } |