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:
Diffstat (limited to 'app/assets/javascripts/packages_and_registries')
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue197
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql3
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql3
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue152
4 files changed, 187 insertions, 168 deletions
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
index 10ac4c5383b..3157653648b 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
@@ -8,8 +8,10 @@ import {
GlButton,
GlFormCheckbox,
GlLoadingIcon,
+ GlModal,
+ GlSprintf,
} from '@gitlab/ui';
-import { last } from 'lodash';
+import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/alert';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __, s__ } from '~/locale';
import FileSha from '~/packages_and_registries/package_registry/components/details/file_sha.vue';
@@ -22,10 +24,22 @@ import {
GRAPHQL_PACKAGE_FILES_PAGE_SIZE,
REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION,
SELECT_PACKAGE_FILE_TRACKING_ACTION,
+ DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
TRACKING_LABEL_PACKAGE_ASSET,
TRACKING_ACTION_EXPAND_PACKAGE_ASSET,
+ DELETE_PACKAGE_FILE_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
+ DELETE_PACKAGE_FILES_ERROR_MESSAGE,
+ DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
+ DELETE_PACKAGE_FILES_TRACKING_ACTION,
+ DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT,
+ DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT,
} from '~/packages_and_registries/package_registry/constants';
import getPackageFilesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql';
+import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql';
export default {
name: 'PackageFiles',
@@ -38,22 +52,25 @@ export default {
GlFormCheckbox,
GlButton,
GlLoadingIcon,
+ GlModal,
+ GlSprintf,
FileIcon,
TimeAgoTooltip,
FileSha,
},
mixins: [Tracking.mixin()],
+ trackingActions: {
+ DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
+ },
props: {
canDelete: {
type: Boolean,
required: false,
default: false,
},
- isLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
packageId: {
type: String,
required: true,
@@ -62,6 +79,10 @@ export default {
type: String,
required: true,
},
+ projectPath: {
+ type: String,
+ required: true,
+ },
},
apollo: {
packageFiles: {
@@ -73,7 +94,7 @@ export default {
return this.queryVariables;
},
update(data) {
- return data.package?.packageFiles?.nodes || [];
+ return data.package?.packageFiles ?? {};
},
error() {
this.fetchPackageFilesError = true;
@@ -83,29 +104,33 @@ export default {
data() {
return {
fetchPackageFilesError: false,
- packageFiles: [],
+ filesToDelete: [],
+ packageFiles: {},
+ mutationLoading: false,
selectedReferences: [],
};
},
computed: {
+ files() {
+ return this.packageFiles?.nodes ?? [];
+ },
areFilesSelected() {
return this.selectedReferences.length > 0;
},
areAllFilesSelected() {
- return this.packageFiles.length > 0 && this.packageFiles.every(this.isSelected);
+ return this.files.length > 0 && this.files.every(this.isSelected);
},
filesTableRows() {
- return this.packageFiles.map((pf) => ({
+ return this.files.map((pf) => ({
...pf,
size: this.formatSize(pf.size),
- pipeline: last(pf.pipelines),
}));
},
hasSelectedSomeFiles() {
return this.areFilesSelected && !this.areAllFilesSelected;
},
- loading() {
- return this.$apollo.queries.packageFiles.loading || this.isLoading;
+ isLoading() {
+ return this.$apollo.queries.packageFiles.loading || this.mutationLoading;
},
filesTableHeaderFields() {
return [
@@ -148,6 +173,29 @@ export default {
category: packageTypeToTrackCategory(this.packageType),
};
},
+ refetchQueriesData() {
+ return [
+ {
+ query: getPackageFilesQuery,
+ variables: this.queryVariables,
+ },
+ ];
+ },
+ modalAction() {
+ return this.hasOneItem(this.filesToDelete)
+ ? this.$options.modal.fileDeletePrimaryAction
+ : this.$options.modal.filesDeletePrimaryAction;
+ },
+ modalTitle() {
+ return this.hasOneItem(this.filesToDelete)
+ ? this.$options.i18n.deleteFileModalTitle
+ : this.$options.i18n.deleteFilesModalTitle;
+ },
+ modalDescription() {
+ return this.hasOneItem(this.filesToDelete)
+ ? this.$options.i18n.deleteFileModalContent
+ : this.$options.i18n.deleteFilesModalContent;
+ },
},
methods: {
formatSize(size) {
@@ -170,15 +218,97 @@ export default {
},
handleFileDeleteSelected() {
this.track(REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION);
- this.$emit('delete-files', this.selectedReferences);
+ this.handleFileDelete(this.selectedReferences);
+ },
+ async deletePackageFiles(ids) {
+ this.mutationLoading = true;
+ try {
+ const { data } = await this.$apollo.mutate({
+ mutation: destroyPackageFilesMutation,
+ variables: {
+ projectPath: this.projectPath,
+ ids,
+ },
+ awaitRefetchQueries: true,
+ refetchQueries: this.refetchQueriesData,
+ });
+ if (data?.destroyPackageFiles?.errors[0]) {
+ throw data.destroyPackageFiles.errors[0];
+ }
+ createAlert({
+ message: this.hasOneItem(ids)
+ ? DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
+ : DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
+ variant: VARIANT_SUCCESS,
+ });
+ } catch (error) {
+ createAlert({
+ message: this.hasOneItem(ids)
+ ? DELETE_PACKAGE_FILE_ERROR_MESSAGE
+ : DELETE_PACKAGE_FILES_ERROR_MESSAGE,
+ variant: VARIANT_WARNING,
+ captureError: true,
+ error,
+ });
+ } finally {
+ this.mutationLoading = false;
+ this.filesToDelete = [];
+ this.selectedReferences = [];
+ }
+ },
+ handleFileDelete(files) {
+ this.track(REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION);
+ if (files.length === this.files.length && !this.packageFiles?.pageInfo?.hasNextPage) {
+ this.$emit(
+ 'delete-all-files',
+ this.hasOneItem(files)
+ ? DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT
+ : DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT,
+ );
+ } else {
+ this.filesToDelete = files;
+ this.$refs.deleteFilesModal.show();
+ }
+ },
+ hasOneItem(items) {
+ return items.length === 1;
+ },
+ confirmFilesDelete() {
+ if (this.hasOneItem(this.filesToDelete)) {
+ this.track(DELETE_PACKAGE_FILE_TRACKING_ACTION);
+ } else {
+ this.track(DELETE_PACKAGE_FILES_TRACKING_ACTION);
+ }
+ this.deletePackageFiles(this.filesToDelete.map((file) => file.id));
},
},
i18n: {
- deleteFile: __('Delete asset'),
+ deleteFile: s__('PackageRegistry|Delete asset'),
+ deleteFileModalTitle: s__('PackageRegistry|Delete package asset'),
+ deleteFileModalContent: s__(
+ 'PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?',
+ ),
+ deleteFilesModalTitle: s__('PackageRegistry|Delete %{count} assets'),
+ deleteFilesModalContent: s__(
+ 'PackageRegistry|You are about to delete %{count} assets. This operation is irreversible.',
+ ),
deleteSelected: s__('PackageRegistry|Delete selected'),
moreActionsText: __('More actions'),
fetchPackageFilesErrorMessage: FETCH_PACKAGE_FILES_ERROR_MESSAGE,
},
+ modal: {
+ fileDeletePrimaryAction: {
+ text: __('Delete'),
+ attributes: { variant: 'danger', category: 'primary' },
+ },
+ filesDeletePrimaryAction: {
+ text: s__('PackageRegistry|Permanently delete assets'),
+ attributes: { variant: 'danger', category: 'primary' },
+ },
+ cancelAction: {
+ text: __('Cancel'),
+ },
+ },
};
</script>
@@ -188,7 +318,7 @@ export default {
<h3 class="gl-font-lg gl-mt-5">{{ __('Assets') }}</h3>
<gl-button
v-if="!fetchPackageFilesError && canDelete"
- :disabled="loading || !areFilesSelected"
+ :disabled="isLoading || !areFilesSelected"
category="secondary"
variant="danger"
data-testid="delete-selected"
@@ -206,7 +336,7 @@ export default {
</gl-alert>
<gl-table
v-else
- :busy="loading"
+ :busy="isLoading"
:fields="filesTableHeaderFields"
:items="filesTableRows"
show-empty
@@ -255,7 +385,7 @@ export default {
:href="item.downloadPath"
class="gl-text-gray-500"
data-testid="download-link"
- @click="$emit('download-file')"
+ @click="track($options.trackingActions.DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION)"
>
<file-icon
:file-name="item.fileName"
@@ -279,7 +409,7 @@ export default {
no-caret
right
>
- <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-files', [item])">
+ <gl-dropdown-item data-testid="delete-file" @click="handleFileDelete([item])">
{{ $options.i18n.deleteFile }}
</gl-dropdown-item>
</gl-dropdown>
@@ -300,5 +430,34 @@ export default {
</div>
</template>
</gl-table>
+
+ <gl-modal
+ ref="deleteFilesModal"
+ size="sm"
+ modal-id="delete-files-modal"
+ :action-primary="modalAction"
+ :action-cancel="$options.modal.cancelAction"
+ data-testid="delete-files-modal"
+ @primary="confirmFilesDelete"
+ @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
+ >
+ <template #modal-title>
+ <gl-sprintf :message="modalTitle">
+ <template #count>
+ {{ filesToDelete.length }}
+ </template>
+ </gl-sprintf>
+ </template>
+
+ <gl-sprintf :message="modalDescription">
+ <template #filename>
+ <strong>{{ filesToDelete[0].fileName }}</strong>
+ </template>
+
+ <template #count>
+ {{ filesToDelete.length }}
+ </template>
+ </gl-sprintf>
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql
index e5ef9265f3e..2a9cfb955a7 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql
@@ -47,9 +47,6 @@ query getPackageDetails($id: PackagesPackageID!) {
}
}
packageFiles(first: 100) {
- pageInfo {
- hasNextPage
- }
nodes {
id
size
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql
index 7851cd39200..e6f292ec1d3 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_files.query.graphql
@@ -2,6 +2,9 @@ query getPackageFiles($id: PackagesPackageID!, $first: Int) {
package(id: $id) {
id
packageFiles(first: $first) {
+ pageInfo {
+ hasNextPage
+ }
nodes {
id
fileMd5
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
index 48a45956ef1..922886fa9cd 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/details.vue
@@ -11,7 +11,7 @@ import {
GlTabs,
GlSprintf,
} from '@gitlab/ui';
-import { createAlert, VARIANT_SUCCESS, VARIANT_WARNING } from '~/alert';
+import { createAlert } from '~/alert';
import { TYPENAME_PACKAGES_PACKAGE } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
@@ -33,27 +33,15 @@ import {
DELETE_PACKAGE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
- DELETE_PACKAGE_FILE_TRACKING_ACTION,
- DELETE_PACKAGE_FILES_TRACKING_ACTION,
- REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
REQUEST_FORWARDING_HELP_PAGE_PATH,
- CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
SHOW_DELETE_SUCCESS_ALERT,
FETCH_PACKAGE_DETAILS_ERROR_MESSAGE,
- DELETE_PACKAGE_FILE_ERROR_MESSAGE,
- DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
- DELETE_PACKAGE_FILES_ERROR_MESSAGE,
- DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
DELETE_PACKAGE_REQUEST_FORWARDING_MODAL_CONTENT,
- DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
DELETE_MODAL_TITLE,
DELETE_MODAL_CONTENT,
- DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT,
- DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT,
GRAPHQL_PAGE_SIZE,
} from '~/packages_and_registries/package_registry/constants';
-import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql';
import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql';
import getPackageVersionsQuery from '~/packages_and_registries/package_registry/graphql/queries/get_package_versions.query.graphql';
import Tracking from '~/tracking';
@@ -92,10 +80,6 @@ export default {
DELETE_PACKAGE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
- DELETE_PACKAGE_FILE_TRACKING_ACTION,
- REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
- CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
- DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION,
},
data() {
return {
@@ -158,9 +142,6 @@ export default {
isLoading() {
return this.$apollo.queries.packageEntity.loading;
},
- packageFilesMutationLoading() {
- return this.mutationLoading;
- },
isValidPackage() {
return this.isLoading || Boolean(this.packageEntity.name);
},
@@ -196,14 +177,6 @@ export default {
PACKAGE_TYPE_PYPI,
].includes(this.packageType);
},
- refetchQueriesData() {
- return [
- {
- query: getPackageDetails,
- variables: this.queryVariables,
- },
- ];
- },
refetchVersionsQueryData() {
return [
{
@@ -230,71 +203,9 @@ export default {
window.location.replace(`${returnTo}?${modalQuery}`);
},
- async deletePackageFiles(ids) {
- this.mutationLoading = true;
- try {
- const { data } = await this.$apollo.mutate({
- mutation: destroyPackageFilesMutation,
- variables: {
- projectPath: this.projectPath,
- ids,
- },
- awaitRefetchQueries: true,
- refetchQueries: this.refetchQueriesData,
- });
- if (data?.destroyPackageFiles?.errors[0]) {
- throw data.destroyPackageFiles.errors[0];
- }
- createAlert({
- message: this.isLastItem(ids)
- ? DELETE_PACKAGE_FILE_SUCCESS_MESSAGE
- : DELETE_PACKAGE_FILES_SUCCESS_MESSAGE,
- variant: VARIANT_SUCCESS,
- });
- } catch (error) {
- createAlert({
- message: this.isLastItem(ids)
- ? DELETE_PACKAGE_FILE_ERROR_MESSAGE
- : DELETE_PACKAGE_FILES_ERROR_MESSAGE,
- variant: VARIANT_WARNING,
- captureError: true,
- error,
- });
- }
- this.mutationLoading = false;
- },
- handleFileDelete(files) {
- this.track(REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION);
- if (
- files.length === this.packageFiles.length &&
- !this.packageEntity.packageFiles?.pageInfo?.hasNextPage
- ) {
- if (this.isLastItem(files)) {
- this.deletePackageModalContent = DELETE_LAST_PACKAGE_FILE_MODAL_CONTENT;
- } else {
- this.deletePackageModalContent = DELETE_ALL_PACKAGE_FILES_MODAL_CONTENT;
- }
- this.$refs.deleteModal.show();
- } else {
- this.filesToDelete = files;
- if (this.isLastItem(files)) {
- this.$refs.deleteFileModal.show();
- } else if (files.length > 1) {
- this.$refs.deleteFilesModal.show();
- }
- }
- },
- isLastItem(items) {
- return items.length === 1;
- },
- confirmFilesDelete() {
- if (this.isLastItem(this.filesToDelete)) {
- this.track(DELETE_PACKAGE_FILE_TRACKING_ACTION);
- } else {
- this.track(DELETE_PACKAGE_FILES_TRACKING_ACTION);
- }
- this.deletePackageFiles(this.filesToDelete.map((file) => file.id));
- this.filesToDelete = [];
+ handleAllFilesDelete(content) {
+ this.deletePackageModalContent = content;
+ this.$refs.deleteModal.show();
},
resetDeleteModalContent() {
this.deletePackageModalContent = DELETE_MODAL_CONTENT;
@@ -302,10 +213,6 @@ export default {
},
i18n: {
DELETE_MODAL_TITLE,
- deleteFileModalTitle: s__(`PackageRegistry|Delete package asset`),
- deleteFileModalContent: s__(
- `PackageRegistry|You are about to delete %{filename}. This is a destructive action that may render your package unusable. Are you sure?`,
- ),
otherVersionsTabTitle: s__('PackageRegistry|Other versions'),
},
links: {
@@ -374,11 +281,10 @@ export default {
<package-files
v-if="showFiles"
:can-delete="packageEntity.canDestroy"
- :is-loading="packageFilesMutationLoading"
:package-id="packageEntity.id"
:package-type="packageType"
- @download-file="track($options.trackingActions.DOWNLOAD_PACKAGE_ASSET_TRACKING_ACTION)"
- @delete-files="handleFileDelete"
+ :project-path="projectPath"
+ @delete-all-files="handleAllFilesDelete"
/>
</div>
</gl-tab>
@@ -471,51 +377,5 @@ export default {
</gl-modal>
</template>
</delete-packages>
-
- <gl-modal
- ref="deleteFileModal"
- size="sm"
- modal-id="delete-file-modal"
- :action-primary="$options.modal.fileDeletePrimaryAction"
- :action-cancel="$options.modal.cancelAction"
- data-testid="delete-file-modal"
- @primary="confirmFilesDelete"
- @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
- >
- <template #modal-title>{{ $options.i18n.deleteFileModalTitle }}</template>
- <gl-sprintf v-if="isLastItem(filesToDelete)" :message="$options.i18n.deleteFileModalContent">
- <template #filename>
- <strong>{{ filesToDelete[0].fileName }}</strong>
- </template>
- </gl-sprintf>
- </gl-modal>
-
- <gl-modal
- ref="deleteFilesModal"
- size="sm"
- modal-id="delete-files-modal"
- :action-primary="$options.modal.filesDeletePrimaryAction"
- :action-cancel="$options.modal.cancelAction"
- data-testid="delete-files-modal"
- @primary="confirmFilesDelete"
- @canceled="track($options.trackingActions.CANCEL_DELETE_PACKAGE_FILE)"
- >
- <template #modal-title>{{
- n__(
- `PackageRegistry|Delete 1 asset`,
- `PackageRegistry|Delete %d assets`,
- filesToDelete.length,
- )
- }}</template>
- <span v-if="filesToDelete.length > 0">
- {{
- n__(
- `PackageRegistry|You are about to delete 1 asset. This operation is irreversible.`,
- `PackageRegistry|You are about to delete %d assets. This operation is irreversible.`,
- filesToDelete.length,
- )
- }}
- </span>
- </gl-modal>
</div>
</template>