diff options
Diffstat (limited to 'app/assets/javascripts/packages/list/components')
7 files changed, 111 insertions, 145 deletions
diff --git a/app/assets/javascripts/packages/list/components/package_search.vue b/app/assets/javascripts/packages/list/components/package_search.vue new file mode 100644 index 00000000000..cd61d323d83 --- /dev/null +++ b/app/assets/javascripts/packages/list/components/package_search.vue @@ -0,0 +1,50 @@ +<script> +import { mapState, mapActions } from 'vuex'; +import { __, s__ } from '~/locale'; +import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; +import getTableHeaders from '../utils'; +import PackageTypeToken from './tokens/package_type_token.vue'; + +export default { + tokens: [ + { + type: 'type', + icon: 'package', + title: s__('PackageRegistry|Type'), + unique: true, + token: PackageTypeToken, + operators: [{ value: '=', description: __('is'), default: 'true' }], + }, + ], + components: { RegistrySearch }, + computed: { + ...mapState({ + isGroupPage: (state) => state.config.isGroupPage, + sorting: (state) => state.sorting, + filter: (state) => state.filter, + }), + sortableFields() { + return getTableHeaders(this.isGroupPage); + }, + }, + methods: { + ...mapActions(['setSorting', 'setFilter']), + updateSorting(newValue) { + this.setSorting(newValue); + this.$emit('update'); + }, + }, +}; +</script> + +<template> + <registry-search + :filter="filter" + :sorting="sorting" + :tokens="$options.tokens" + :sortable-fields="sortableFields" + @sorting:changed="updateSorting" + @filter:changed="setFilter" + @filter:submit="$emit('update')" + /> +</template> diff --git a/app/assets/javascripts/packages/list/components/package_title.vue b/app/assets/javascripts/packages/list/components/package_title.vue index f94a98e4ca7..6176e15ffd4 100644 --- a/app/assets/javascripts/packages/list/components/package_title.vue +++ b/app/assets/javascripts/packages/list/components/package_title.vue @@ -1,7 +1,7 @@ <script> import { n__ } from '~/locale'; -import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue'; +import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import { LIST_INTRO_TEXT, LIST_TITLE_TEXT } from '../constants'; export default { diff --git a/app/assets/javascripts/packages/list/components/packages_filter.vue b/app/assets/javascripts/packages/list/components/packages_filter.vue deleted file mode 100644 index 17398071217..00000000000 --- a/app/assets/javascripts/packages/list/components/packages_filter.vue +++ /dev/null @@ -1,21 +0,0 @@ -<script> -import { GlSearchBoxByClick } from '@gitlab/ui'; -import { mapActions } from 'vuex'; - -export default { - components: { - GlSearchBoxByClick, - }, - methods: { - ...mapActions(['setFilter']), - }, -}; -</script> - -<template> - <gl-search-box-by-click - :placeholder="s__('PackageRegistry|Filter by name')" - @submit="$emit('filter')" - @input="setFilter" - /> -</template> diff --git a/app/assets/javascripts/packages/list/components/packages_list.vue b/app/assets/javascripts/packages/list/components/packages_list.vue index 1e38ee525b8..23ba070aa26 100644 --- a/app/assets/javascripts/packages/list/components/packages_list.vue +++ b/app/assets/javascripts/packages/list/components/packages_list.vue @@ -1,12 +1,12 @@ <script> -import { mapState, mapGetters } from 'vuex'; import { GlPagination, GlModal, GlSprintf } from '@gitlab/ui'; -import Tracking from '~/tracking'; +import { mapState, mapGetters } from 'vuex'; import { s__ } from '~/locale'; +import Tracking from '~/tracking'; +import PackagesListRow from '../../shared/components/package_list_row.vue'; +import PackagesListLoader from '../../shared/components/packages_list_loader.vue'; import { TrackingActions } from '../../shared/constants'; import { packageTypeToTrackCategory } from '../../shared/utils'; -import PackagesListLoader from '../../shared/components/packages_list_loader.vue'; -import PackagesListRow from '../../shared/components/package_list_row.vue'; export default { components: { diff --git a/app/assets/javascripts/packages/list/components/packages_list_app.vue b/app/assets/javascripts/packages/list/components/packages_list_app.vue index 2a786b92515..a609dfebedf 100644 --- a/app/assets/javascripts/packages/list/components/packages_list_app.vue +++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue @@ -1,39 +1,43 @@ <script> +import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui'; import { mapActions, mapState } from 'vuex'; -import { GlEmptyState, GlTab, GlTabs, GlLink, GlSprintf } from '@gitlab/ui'; -import { s__, sprintf } from '~/locale'; import createFlash from '~/flash'; import { historyReplaceState } from '~/lib/utils/common_utils'; +import { s__ } from '~/locale'; import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants'; -import PackageFilter from './packages_filter.vue'; -import PackageList from './packages_list.vue'; -import PackageSort from './packages_sort.vue'; -import { PACKAGE_REGISTRY_TABS, DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants'; +import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants'; +import PackageSearch from './package_search.vue'; import PackageTitle from './package_title.vue'; +import PackageList from './packages_list.vue'; export default { components: { GlEmptyState, - GlTab, - GlTabs, GlLink, GlSprintf, - PackageFilter, PackageList, - PackageSort, PackageTitle, + PackageSearch, }, computed: { ...mapState({ emptyListIllustration: (state) => state.config.emptyListIllustration, emptyListHelpUrl: (state) => state.config.emptyListHelpUrl, - filterQuery: (state) => state.filterQuery, + filter: (state) => state.filter, selectedType: (state) => state.selectedType, packageHelpUrl: (state) => state.config.packageHelpUrl, packagesCount: (state) => state.pagination?.total, }), - tabsToRender() { - return PACKAGE_REGISTRY_TABS; + emptySearch() { + return ( + this.filter.filter((f) => f.type !== 'filtered-search-term' || f.value?.data).length === 0 + ); + }, + + emptyStateTitle() { + return this.emptySearch + ? s__('PackageRegistry|There are no packages yet') + : s__('PackageRegistry|Sorry, your filter produced no results'); }, }, mounted() { @@ -48,27 +52,6 @@ export default { onPackageDeleteRequest(item) { return this.requestDeletePackage(item); }, - tabChanged(index) { - const selected = PACKAGE_REGISTRY_TABS[index]; - - if (selected !== this.selectedType) { - this.setSelectedType(selected); - this.requestPackagesList(); - } - }, - emptyStateTitle({ title, type }) { - if (this.filterQuery) { - return s__('PackageRegistry|Sorry, your filter produced no results'); - } - - if (type) { - return sprintf(s__('PackageRegistry|There are no %{packageType} packages yet'), { - packageType: title, - }); - } - - return s__('PackageRegistry|There are no packages yet'); - }, checkDeleteAlert() { const urlParams = new URLSearchParams(window.location.search); const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT); @@ -92,33 +75,21 @@ export default { <template> <div> <package-title :package-help-url="packageHelpUrl" :packages-count="packagesCount" /> + <package-search @update="requestPackagesList" /> - <gl-tabs @input="tabChanged"> - <template #tabs-end> - <div - class="gl-display-flex gl-align-self-center gl-py-2 gl-flex-grow-1 gl-justify-content-end" - > - <package-filter class="gl-mr-2" @filter="requestPackagesList" /> - <package-sort @sort:changed="requestPackagesList" /> - </div> - </template> - - <gl-tab v-for="(tab, index) in tabsToRender" :key="index" :title="tab.title"> - <package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest"> - <template #empty-state> - <gl-empty-state :title="emptyStateTitle(tab)" :svg-path="emptyListIllustration"> - <template #description> - <gl-sprintf v-if="filterQuery" :message="$options.i18n.widenFilters" /> - <gl-sprintf v-else :message="$options.i18n.noResults"> - <template #noPackagesLink="{ content }"> - <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link> - </template> - </gl-sprintf> + <package-list @page:changed="onPageChanged" @package:delete="onPackageDeleteRequest"> + <template #empty-state> + <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration"> + <template #description> + <gl-sprintf v-if="!emptySearch" :message="$options.i18n.widenFilters" /> + <gl-sprintf v-else :message="$options.i18n.noResults"> + <template #noPackagesLink="{ content }"> + <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link> </template> - </gl-empty-state> + </gl-sprintf> </template> - </package-list> - </gl-tab> - </gl-tabs> + </gl-empty-state> + </template> + </package-list> </div> </template> diff --git a/app/assets/javascripts/packages/list/components/packages_sort.vue b/app/assets/javascripts/packages/list/components/packages_sort.vue deleted file mode 100644 index 4b2d9091f8f..00000000000 --- a/app/assets/javascripts/packages/list/components/packages_sort.vue +++ /dev/null @@ -1,60 +0,0 @@ -<script> -import { GlSorting, GlSortingItem } from '@gitlab/ui'; -import { mapState, mapActions } from 'vuex'; -import { ASCENDING_ODER, DESCENDING_ORDER } from '../constants'; -import getTableHeaders from '../utils'; - -export default { - name: 'PackageSort', - components: { - GlSorting, - GlSortingItem, - }, - computed: { - ...mapState({ - isGroupPage: (state) => state.config.isGroupPage, - orderBy: (state) => state.sorting.orderBy, - sort: (state) => state.sorting.sort, - }), - sortText() { - const field = this.sortableFields.find((s) => s.orderBy === this.orderBy); - return field ? field.label : ''; - }, - sortableFields() { - return getTableHeaders(this.isGroupPage); - }, - isSortAscending() { - return this.sort === ASCENDING_ODER; - }, - }, - methods: { - ...mapActions(['setSorting']), - onDirectionChange() { - const sort = this.isSortAscending ? DESCENDING_ORDER : ASCENDING_ODER; - this.setSorting({ sort }); - this.$emit('sort:changed'); - }, - onSortItemClick(item) { - this.setSorting({ orderBy: item }); - this.$emit('sort:changed'); - }, - }, -}; -</script> - -<template> - <gl-sorting - :text="sortText" - :is-ascending="isSortAscending" - @sortDirectionChange="onDirectionChange" - > - <gl-sorting-item - v-for="item in sortableFields" - ref="packageListSortItem" - :key="item.orderBy" - @click="onSortItemClick(item.orderBy)" - > - {{ item.label }} - </gl-sorting-item> - </gl-sorting> -</template> diff --git a/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue b/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue new file mode 100644 index 00000000000..74b6774712e --- /dev/null +++ b/app/assets/javascripts/packages/list/components/tokens/package_type_token.vue @@ -0,0 +1,26 @@ +<script> +import { GlFilteredSearchToken, GlFilteredSearchSuggestion } from '@gitlab/ui'; +import { PACKAGE_TYPES } from '../../constants'; + +export default { + components: { + GlFilteredSearchToken, + GlFilteredSearchSuggestion, + }, + PACKAGE_TYPES, +}; +</script> + +<template> + <gl-filtered-search-token v-bind="{ ...$attrs }" v-on="$listeners"> + <template #suggestions> + <gl-filtered-search-suggestion + v-for="(type, index) in $options.PACKAGE_TYPES" + :key="index" + :value="type.type" + > + {{ type.title }} + </gl-filtered-search-suggestion> + </template> + </gl-filtered-search-token> +</template> |