diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-18 11:17:02 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-18 11:17:02 +0300 |
commit | b39512ed755239198a9c294b6a45e65c05900235 (patch) | |
tree | d234a3efade1de67c46b9e5a38ce813627726aa7 /app/assets/javascripts/packages_and_registries/package_registry/components | |
parent | d31474cf3b17ece37939d20082b07f6657cc79a9 (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')
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> |