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:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 11:17:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-18 11:17:02 +0300
commitb39512ed755239198a9c294b6a45e65c05900235 (patch)
treed234a3efade1de67c46b9e5a38ce813627726aa7 /app/assets/javascripts/packages_and_registries/package_registry/components
parentd31474cf3b17ece37939d20082b07f6657cc79a9 (diff)
Add latest changes from gitlab-org/gitlab@15-3-stable-eev15.3.0-rc42
Diffstat (limited to 'app/assets/javascripts/packages_and_registries/package_registry/components')
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue109
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue35
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue52
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue47
4 files changed, 188 insertions, 55 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 a049b0eff8d..b872294d2cf 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
@@ -1,14 +1,16 @@
<script>
-import { GlLink, GlTableLite, GlDropdownItem, GlDropdown, GlIcon, GlButton } from '@gitlab/ui';
+import { GlLink, GlTable, GlDropdownItem, GlDropdown, GlButton, GlFormCheckbox } from '@gitlab/ui';
import { last } from 'lodash';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import FileSha from '~/packages_and_registries/package_registry/components/details/file_sha.vue';
import Tracking from '~/tracking';
import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
+ REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION,
+ SELECT_PACKAGE_FILE_TRACKING_ACTION,
TRACKING_LABEL_PACKAGE_ASSET,
TRACKING_ACTION_EXPAND_PACKAGE_ASSET,
} from '~/packages_and_registries/package_registry/constants';
@@ -17,10 +19,10 @@ export default {
name: 'PackageFiles',
components: {
GlLink,
- GlTableLite,
- GlIcon,
+ GlTable,
GlDropdown,
GlDropdownItem,
+ GlFormCheckbox,
GlButton,
FileIcon,
TimeAgoTooltip,
@@ -33,13 +35,29 @@ export default {
required: false,
default: false,
},
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
packageFiles: {
type: Array,
required: false,
default: () => [],
},
},
+ data() {
+ return {
+ selectedReferences: [],
+ };
+ },
computed: {
+ areFilesSelected() {
+ return this.selectedReferences.length > 0;
+ },
+ areAllFilesSelected() {
+ return this.packageFiles.every(this.isSelected);
+ },
filesTableRows() {
return this.packageFiles.map((pf) => ({
...pf,
@@ -47,6 +65,9 @@ export default {
pipeline: last(pf.pipelines),
}));
},
+ hasSelectedSomeFiles() {
+ return this.areFilesSelected && !this.areAllFilesSelected;
+ },
showCommitColumn() {
// note that this is always false for now since we do not return
// pipelines associated to files for performance concerns
@@ -55,6 +76,12 @@ export default {
filesTableHeaderFields() {
return [
{
+ key: 'checkbox',
+ label: __('Select all'),
+ class: 'gl-w-4',
+ hide: !this.canDelete,
+ },
+ {
key: 'name',
label: __('Name'),
},
@@ -77,7 +104,7 @@ export default {
label: '',
hide: !this.canDelete,
class: 'gl-text-right',
- tdClass: 'gl-w-4',
+ tdClass: 'gl-w-4 gl-pt-3!',
},
].filter((c) => !c.hide);
},
@@ -99,21 +126,71 @@ export default {
this.track(TRACKING_ACTION_EXPAND_PACKAGE_ASSET, { label: TRACKING_LABEL_PACKAGE_ASSET });
}
},
+ updateSelectedReferences(selection) {
+ this.track(SELECT_PACKAGE_FILE_TRACKING_ACTION);
+ this.selectedReferences = selection;
+ },
+ isSelected(packageFile) {
+ return this.selectedReferences.find((reference) => reference.id === packageFile.id);
+ },
+ handleFileDeleteSelected() {
+ this.track(REQUEST_DELETE_SELECTED_PACKAGE_FILE_TRACKING_ACTION);
+ this.$emit('delete-files', this.selectedReferences);
+ },
},
i18n: {
deleteFile: __('Delete file'),
+ deleteSelected: s__('PackageRegistry|Delete selected'),
+ moreActionsText: __('More actions'),
},
};
</script>
<template>
- <div>
- <h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3>
- <gl-table-lite
+ <div class="gl-pt-6">
+ <div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
+ <h3 class="gl-font-lg gl-mt-5">{{ __('Files') }}</h3>
+ <gl-button
+ v-if="canDelete"
+ :disabled="isLoading || !areFilesSelected"
+ category="secondary"
+ variant="danger"
+ data-testid="delete-selected"
+ @click="handleFileDeleteSelected"
+ >
+ {{ $options.i18n.deleteSelected }}
+ </gl-button>
+ </div>
+ <gl-table
:fields="filesTableHeaderFields"
:items="filesTableRows"
+ show-empty
+ selectable
+ select-mode="multi"
+ selected-variant="primary"
:tbody-tr-attr="{ 'data-testid': 'file-row' }"
+ @row-selected="updateSelectedReferences"
>
+ <template #head(checkbox)="{ selectAllRows, clearSelected }">
+ <gl-form-checkbox
+ v-if="canDelete"
+ data-testid="package-files-checkbox-all"
+ :checked="areAllFilesSelected"
+ :indeterminate="hasSelectedSomeFiles"
+ @change="areAllFilesSelected ? clearSelected() : selectAllRows()"
+ />
+ </template>
+
+ <template #cell(checkbox)="{ rowSelected, selectRow, unselectRow }">
+ <gl-form-checkbox
+ v-if="canDelete"
+ class="gl-mt-1"
+ :checked="rowSelected"
+ data-testid="package-files-checkbox"
+ @change="rowSelected ? unselectRow() : selectRow()"
+ />
+ </template>
+
<template #cell(name)="{ item, toggleDetails, detailsShowing }">
<gl-button
v-if="hasDetails(item)"
@@ -156,11 +233,15 @@ export default {
</template>
<template #cell(actions)="{ item }">
- <gl-dropdown category="tertiary" right>
- <template #button-content>
- <gl-icon name="ellipsis_v" />
- </template>
- <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-file', item)">
+ <gl-dropdown
+ category="tertiary"
+ icon="ellipsis_v"
+ :text-sr-only="true"
+ :text="$options.i18n.moreActionsText"
+ no-caret
+ right
+ >
+ <gl-dropdown-item data-testid="delete-file" @click="$emit('delete-files', [item])">
{{ $options.i18n.deleteFile }}
</gl-dropdown-item>
</gl-dropdown>
@@ -180,6 +261,6 @@ export default {
<file-sha v-if="item.fileSha1" data-testid="sha-1" title="SHA-1" :sha="item.fileSha1" />
</div>
</template>
- </gl-table-lite>
+ </gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue
index 96b82a20364..a1fc7563de1 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_history.vue
@@ -5,12 +5,17 @@ import { first } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__, n__ } from '~/locale';
+import Tracking from '~/tracking';
+import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import { HISTORY_PIPELINES_LIMIT } from '~/packages_and_registries/shared/constants';
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import {
GRAPHQL_PACKAGE_PIPELINES_PAGE_SIZE,
FETCH_PACKAGE_PIPELINES_ERROR_MESSAGE,
+ TRACKING_ACTION_CLICK_PIPELINE_LINK,
+ TRACKING_ACTION_CLICK_COMMIT_LINK,
+ TRACKING_LABEL_PACKAGE_HISTORY,
} from '../../constants';
import getPackagePipelinesQuery from '../../graphql/queries/get_package_pipelines.query.graphql';
import PackageHistoryLoader from './package_history_loader.vue';
@@ -37,6 +42,9 @@ export default {
PackageHistoryLoader,
TimeAgoTooltip,
},
+ mixins: [Tracking.mixin()],
+ TRACKING_ACTION_CLICK_PIPELINE_LINK,
+ TRACKING_ACTION_CLICK_COMMIT_LINK,
props: {
packageEntity: {
type: Object,
@@ -97,6 +105,11 @@ export default {
first: GRAPHQL_PACKAGE_PIPELINES_PAGE_SIZE,
};
},
+ tracking() {
+ return {
+ category: packageTypeToTrackCategory(this.packageType),
+ };
+ },
},
methods: {
truncate(value) {
@@ -105,6 +118,12 @@ export default {
convertToBaseId(value) {
return getIdFromGraphQLId(value);
},
+ trackPipelineClick() {
+ this.track(TRACKING_ACTION_CLICK_PIPELINE_LINK, { label: TRACKING_LABEL_PACKAGE_HISTORY });
+ },
+ trackCommitClick() {
+ this.track(TRACKING_ACTION_CLICK_COMMIT_LINK, { label: TRACKING_LABEL_PACKAGE_HISTORY });
+ },
},
};
</script>
@@ -140,7 +159,9 @@ export default {
<history-item icon="commit" data-testid="first-pipeline-commit">
<gl-sprintf :message="$options.i18n.createdByCommitText">
<template #link>
- <gl-link :href="firstPipeline.commitPath">#{{ truncate(firstPipeline.sha) }}</gl-link>
+ <gl-link :href="firstPipeline.commitPath" @click="trackCommitClick"
+ >#{{ truncate(firstPipeline.sha) }}</gl-link
+ >
</template>
<template #branch>
<strong>{{ firstPipeline.ref }}</strong>
@@ -150,7 +171,9 @@ export default {
<history-item icon="pipeline" data-testid="first-pipeline-pipeline">
<gl-sprintf :message="$options.i18n.createdByPipelineText">
<template #link>
- <gl-link :href="firstPipeline.path">#{{ convertToBaseId(firstPipeline.id) }}</gl-link>
+ <gl-link :href="firstPipeline.path" @click="trackPipelineClick"
+ >#{{ convertToBaseId(firstPipeline.id) }}</gl-link
+ >
</template>
<template #datetime>
<time-ago-tooltip :time="firstPipeline.createdAt" />
@@ -189,13 +212,17 @@ export default {
>
<gl-sprintf :message="$options.i18n.combinedUpdateText">
<template #link>
- <gl-link :href="pipeline.commitPath">#{{ truncate(pipeline.sha) }}</gl-link>
+ <gl-link :href="pipeline.commitPath" @click="trackCommitClick"
+ >#{{ truncate(pipeline.sha) }}</gl-link
+ >
</template>
<template #branch>
<strong>{{ pipeline.ref }}</strong>
</template>
<template #pipeline>
- <gl-link :href="pipeline.path">#{{ convertToBaseId(pipeline.id) }}</gl-link>
+ <gl-link :href="pipeline.path" @click="trackPipelineClick"
+ >#{{ convertToBaseId(pipeline.id) }}</gl-link
+ >
</template>
<template #datetime>
<time-ago-tooltip :time="pipeline.createdAt" />
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue
index f5946797626..11fd0db3106 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue
@@ -23,6 +23,7 @@ export default {
directives: {
GlResizeObserver: GlResizeObserverDirective,
},
+ inject: ['isGroupPage'],
i18n: {
packageInfo: __('v%{version} published %{timeAgo}'),
},
@@ -65,9 +66,6 @@ export default {
this.checkBreakpoints();
},
methods: {
- dynamicSlotName(index) {
- return `metadata-tag${index}`;
- },
checkBreakpoints() {
this.isDesktop = GlBreakpointInstance.isDesktop();
},
@@ -83,21 +81,38 @@ export default {
data-qa-selector="package_title"
>
<template #sub-header>
- <span data-testid="sub-header">
+ <div data-testid="sub-header" class="gl-display-flex gl-gap-3">
<gl-sprintf :message="$options.i18n.packageInfo">
<template #version>
{{ packageEntity.version }}
</template>
<template #timeAgo>
- <time-ago-tooltip
- v-if="packageEntity.createdAt"
- class="gl-ml-2"
- :time="packageEntity.createdAt"
- />
+ <time-ago-tooltip v-if="packageEntity.createdAt" :time="packageEntity.createdAt" />
</template>
</gl-sprintf>
- </span>
+
+ <package-tags
+ v-if="isDesktop && hasTagsToDisplay"
+ :tag-display-limit="2"
+ :tags="packageEntity.tags.nodes"
+ hide-label
+ />
+
+ <!-- we need to duplicate the package tags on mobile to ensure proper styling inside the flex wrap -->
+ <template v-else-if="hasTagsToDisplay">
+ <gl-badge
+ v-for="(tag, index) in packageEntity.tags.nodes"
+ :key="index"
+ class="gl-my-1"
+ data-testid="tag-badge"
+ variant="info"
+ size="sm"
+ >
+ {{ tag.name }}
+ </gl-badge>
+ </template>
+ </div>
</template>
<template v-if="packageTypeDisplay" #metadata-type>
@@ -108,7 +123,7 @@ export default {
<metadata-item data-testid="package-size" icon="disk" :text="totalSize" />
</template>
- <template v-if="packagePipeline" #metadata-pipeline>
+ <template v-if="isGroupPage && packagePipeline" #metadata-pipeline>
<metadata-item
data-testid="pipeline-project"
icon="review-list"
@@ -121,21 +136,6 @@ export default {
<metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
</template>
- <template v-if="isDesktop && hasTagsToDisplay" #metadata-tags>
- <package-tags :tag-display-limit="2" :tags="packageEntity.tags.nodes" hide-label />
- </template>
-
- <!-- we need to duplicate the package tags on mobile to ensure proper styling inside the flex wrap -->
- <template
- v-for="(tag, index) in packageEntity.tags.nodes"
- v-else-if="hasTagsToDisplay"
- #[dynamicSlotName(index)]
- >
- <gl-badge :key="index" class="gl-my-1" data-testid="tag-badge" variant="info" size="sm">
- {{ tag.name }}
- </gl-badge>
- </template>
-
<template #right-actions>
<slot name="delete-button"></slot>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
index a126d30f1ec..dd58f28a262 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
@@ -1,9 +1,10 @@
<script>
-import { GlLink, GlSprintf } from '@gitlab/ui';
+import { GlFormGroup, GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
import {
+ PERSONAL_ACCESS_TOKEN_HELP_URL,
TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND,
TRACKING_ACTION_COPY_PYPI_SETUP_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
@@ -16,6 +17,7 @@ export default {
components: {
InstallationTitle,
CodeInstruction,
+ GlFormGroup,
GlLink,
GlSprintf,
},
@@ -43,6 +45,7 @@ password = <your personal access token>`;
TRACKING_LABEL_CODE_INSTRUCTION,
},
i18n: {
+ tokenText: s__(`PackageRegistry|You will need a %{linkStart}personal access token%{linkEnd}.`),
setupText: s__(
`PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file.`,
),
@@ -50,7 +53,10 @@ password = <your personal access token>`;
'PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}.',
),
},
- links: { PYPI_HELP_PATH },
+ links: {
+ PERSONAL_ACCESS_TOKEN_HELP_URL,
+ PYPI_HELP_PATH,
+ },
installOptions: [{ value: 'pypi', label: s__('PackageRegistry|Show PyPi commands') }],
};
</script>
@@ -59,14 +65,28 @@ password = <your personal access token>`;
<div>
<installation-title package-type="pypi" :options="$options.installOptions" />
- <code-instruction
- :label="s__('PackageRegistry|Pip Command')"
- :instruction="pypiPipCommand"
- :copy-text="s__('PackageRegistry|Copy Pip command')"
- data-testid="pip-command"
- :tracking-action="$options.tracking.TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND"
- :tracking-label="$options.tracking.TRACKING_LABEL_CODE_INSTRUCTION"
- />
+ <gl-form-group id="installation-pip-command-group">
+ <code-instruction
+ id="installation-pip-command"
+ :label="s__('PackageRegistry|Pip Command')"
+ :instruction="pypiPipCommand"
+ :copy-text="s__('PackageRegistry|Copy Pip command')"
+ data-testid="pip-command"
+ :tracking-action="$options.tracking.TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND"
+ :tracking-label="$options.tracking.TRACKING_LABEL_CODE_INSTRUCTION"
+ />
+ <template #description>
+ <gl-sprintf :message="$options.i18n.tokenText">
+ <template #link="{ content }">
+ <gl-link
+ :href="$options.links.PERSONAL_ACCESS_TOKEN_HELP_URL"
+ data-testid="access-token-link"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-form-group>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
<p>
@@ -87,7 +107,12 @@ password = <your personal access token>`;
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="$options.links.PYPI_HELP_PATH" target="_blank">{{ content }}</gl-link>
+ <gl-link
+ :href="$options.links.PYPI_HELP_PATH"
+ target="_blank"
+ data-testid="pypi-docs-link"
+ >{{ content }}</gl-link
+ >
</template>
</gl-sprintf>
</div>