296 lines
8.5 KiB
Vue
296 lines
8.5 KiB
Vue
<script>
|
|
import {
|
|
GlBadge,
|
|
GlButton,
|
|
GlModal,
|
|
GlModalDirective,
|
|
GlTooltipDirective,
|
|
GlLink,
|
|
GlEmptyState,
|
|
GlTab,
|
|
GlTabs,
|
|
GlTable,
|
|
GlSprintf,
|
|
} from '@gitlab/ui';
|
|
import { mapActions, mapState } from 'vuex';
|
|
import Tracking from '~/tracking';
|
|
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 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';
|
|
|
|
export default {
|
|
name: 'PackagesApp',
|
|
components: {
|
|
GlBadge,
|
|
GlButton,
|
|
GlEmptyState,
|
|
GlLink,
|
|
GlModal,
|
|
GlTab,
|
|
GlTabs,
|
|
GlTable,
|
|
FileIcon,
|
|
GlSprintf,
|
|
PackageTitle,
|
|
PackagesListLoader,
|
|
PackageListRow,
|
|
DependencyRow,
|
|
PackageHistory,
|
|
AdditionalMetadata,
|
|
InstallationCommands,
|
|
},
|
|
directives: {
|
|
GlTooltip: GlTooltipDirective,
|
|
GlModal: GlModalDirective,
|
|
},
|
|
mixins: [timeagoMixin, Tracking.mixin()],
|
|
trackingActions: { ...TrackingActions },
|
|
computed: {
|
|
...mapState([
|
|
'projectName',
|
|
'packageEntity',
|
|
'packageFiles',
|
|
'isLoading',
|
|
'canDelete',
|
|
'svgPath',
|
|
'npmPath',
|
|
'npmHelpPath',
|
|
'projectListUrl',
|
|
'groupListUrl',
|
|
]),
|
|
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),
|
|
};
|
|
},
|
|
hasVersions() {
|
|
return this.packageEntity.versions?.length > 0;
|
|
},
|
|
packageDependencies() {
|
|
return this.packageEntity.dependency_links || [];
|
|
},
|
|
showDependencies() {
|
|
return this.packageEntity.package_type === PackageType.NUGET;
|
|
},
|
|
showFiles() {
|
|
return this.packageEntity?.package_type !== PackageType.COMPOSER;
|
|
},
|
|
},
|
|
methods: {
|
|
...mapActions(['deletePackage', 'fetchPackageVersions']),
|
|
formatSize(size) {
|
|
return numberToHumanSize(size);
|
|
},
|
|
cancelDelete() {
|
|
this.$refs.deleteModal.hide();
|
|
},
|
|
getPackageVersions() {
|
|
if (!this.packageEntity.versions) {
|
|
this.fetchPackageVersions();
|
|
}
|
|
},
|
|
async confirmPackageDeletion() {
|
|
this.track(TrackingActions.DELETE_PACKAGE);
|
|
await this.deletePackage();
|
|
const returnTo =
|
|
!this.groupListUrl || document.referrer.includes(this.projectName)
|
|
? this.projectListUrl
|
|
: this.groupListUrl; // to avoid security issue url are supplied from backend
|
|
const modalQuery = objectToQueryString({ [SHOW_DELETE_SUCCESS_ALERT]: true });
|
|
window.location.replace(`${returnTo}?${modalQuery}`);
|
|
},
|
|
},
|
|
i18n: {
|
|
deleteModalTitle: s__(`PackageRegistry|Delete Package Version`),
|
|
deleteModalContent: s__(
|
|
`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>
|
|
|
|
<template>
|
|
<gl-empty-state
|
|
v-if="!isValidPackage"
|
|
:title="s__('PackageRegistry|Unable to load package')"
|
|
:description="s__('PackageRegistry|There was a problem fetching the details for this package.')"
|
|
:svg-path="svgPath"
|
|
/>
|
|
|
|
<div v-else class="packages-app">
|
|
<package-title>
|
|
<template #delete-button>
|
|
<gl-button
|
|
v-if="canDelete"
|
|
v-gl-modal="'delete-modal'"
|
|
class="js-delete-button"
|
|
variant="danger"
|
|
category="primary"
|
|
data-qa-selector="delete_button"
|
|
>
|
|
{{ __('Delete') }}
|
|
</gl-button>
|
|
</template>
|
|
</package-title>
|
|
|
|
<gl-tabs>
|
|
<gl-tab :title="__('Detail')">
|
|
<div data-qa-selector="package_information_content">
|
|
<package-history :package-entity="packageEntity" :project-name="projectName" />
|
|
|
|
<installation-commands
|
|
:package-entity="packageEntity"
|
|
:npm-path="npmPath"
|
|
:npm-help-path="npmHelpPath"
|
|
/>
|
|
|
|
<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>
|
|
</gl-tab>
|
|
|
|
<gl-tab v-if="showDependencies" title-item-class="js-dependencies-tab">
|
|
<template #title>
|
|
<span>{{ __('Dependencies') }}</span>
|
|
<gl-badge size="sm" data-testid="dependencies-badge">{{
|
|
packageDependencies.length
|
|
}}</gl-badge>
|
|
</template>
|
|
|
|
<template v-if="packageDependencies.length > 0">
|
|
<dependency-row
|
|
v-for="(dep, index) in packageDependencies"
|
|
:key="index"
|
|
:dependency="dep"
|
|
/>
|
|
</template>
|
|
|
|
<p v-else class="gl-mt-3" data-testid="no-dependencies-message">
|
|
{{ s__('PackageRegistry|This NuGet package has no dependencies.') }}
|
|
</p>
|
|
</gl-tab>
|
|
|
|
<gl-tab
|
|
:title="__('Other versions')"
|
|
title-item-class="js-versions-tab"
|
|
@click="getPackageVersions"
|
|
>
|
|
<template v-if="isLoading && !hasVersions">
|
|
<packages-list-loader />
|
|
</template>
|
|
|
|
<template v-else-if="hasVersions">
|
|
<package-list-row
|
|
v-for="v in packageEntity.versions"
|
|
:key="v.id"
|
|
:package-entity="{ name: packageEntity.name, ...v }"
|
|
:package-link="v.id.toString()"
|
|
:disable-delete="true"
|
|
:show-package-type="false"
|
|
/>
|
|
</template>
|
|
|
|
<p v-else class="gl-mt-3" data-testid="no-versions-message">
|
|
{{ s__('PackageRegistry|There are no other versions of this package.') }}
|
|
</p>
|
|
</gl-tab>
|
|
</gl-tabs>
|
|
|
|
<gl-modal ref="deleteModal" class="js-delete-modal" modal-id="delete-modal">
|
|
<template #modal-title>{{ $options.i18n.deleteModalTitle }}</template>
|
|
<gl-sprintf :message="$options.i18n.deleteModalContent">
|
|
<template #version>
|
|
<strong>{{ packageEntity.version }}</strong>
|
|
</template>
|
|
|
|
<template #name>
|
|
<strong>{{ packageEntity.name }}</strong>
|
|
</template>
|
|
</gl-sprintf>
|
|
|
|
<template #modal-footer>
|
|
<div class="gl-w-full">
|
|
<div class="float-right">
|
|
<gl-button @click="cancelDelete">{{ __('Cancel') }}</gl-button>
|
|
<gl-button
|
|
ref="modal-delete-button"
|
|
variant="danger"
|
|
category="primary"
|
|
data-qa-selector="delete_modal_button"
|
|
@click="confirmPackageDeletion"
|
|
>
|
|
{{ __('Delete') }}
|
|
</gl-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</gl-modal>
|
|
</div>
|
|
</template>
|