diff options
Diffstat (limited to 'app/assets/javascripts/packages_and_registries')
14 files changed, 171 insertions, 144 deletions
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js index afddf78203d..7040f42398e 100644 --- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js +++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/index.js @@ -4,7 +4,7 @@ import { parseBoolean } from '~/lib/utils/common_utils'; import PerformancePlugin from '~/performance/vue_performance_plugin'; import Translate from '~/vue_shared/translate'; import RegistryBreadcrumb from '~/packages_and_registries/shared/components/registry_breadcrumb.vue'; -import { renderBreadcrumb } from '~/packages_and_registries/shared/utils'; +import { injectVueAppBreadcrumbs } from '~/lib/utils/breadcrumbs'; import { apolloProvider } from './graphql/index'; import RegistryExplorer from './pages/index.vue'; import createRouter from './router'; @@ -88,7 +88,7 @@ export default () => { }); return { - attachBreadcrumb: renderBreadcrumb(router, apolloProvider, RegistryBreadcrumb), + attachBreadcrumb: () => injectVueAppBreadcrumbs(router, RegistryBreadcrumb, apolloProvider), attachMainComponent, }; }; diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue index e18e6f7ed1a..6bb4a8797df 100644 --- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue @@ -2,8 +2,8 @@ import { GlAlert, GlButton, - GlDropdown, - GlDropdownItem, + GlDisclosureDropdown, + GlDisclosureDropdownItem, GlFormGroup, GlFormInputGroup, GlSkeletonLoader, @@ -18,6 +18,8 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import ManifestsList from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue'; import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/dependency_proxy/constants'; +import { getPageParams } from '~/packages_and_registries/dependency_proxy/utils'; +import { extractPageInfo } from '~/packages_and_registries/shared/utils'; import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql'; @@ -25,8 +27,8 @@ export default { components: { GlAlert, GlButton, - GlDropdown, - GlDropdownItem, + GlDisclosureDropdown, + GlDisclosureDropdownItem, GlSkeletonLoader, GlFormGroup, GlFormInputGroup, @@ -79,11 +81,15 @@ export default { }, computed: { queryVariables() { - return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE }; + return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE, ...this.pageParams }; }, pageInfo() { return this.group.dependencyProxyManifests?.pageInfo; }, + pageParams() { + const pageInfo = extractPageInfo(this.$route.query); + return getPageParams(pageInfo); + }, manifests() { return this.group.dependencyProxyManifests?.nodes ?? []; }, @@ -123,25 +129,10 @@ export default { }, methods: { fetchNextPage() { - this.fetchMore({ - first: GRAPHQL_PAGE_SIZE, - after: this.pageInfo?.endCursor, - }); + this.$router.push({ query: { after: this.pageInfo?.endCursor } }); }, fetchPreviousPage() { - this.fetchMore({ - first: null, - last: GRAPHQL_PAGE_SIZE, - before: this.pageInfo?.startCursor, - }); - }, - fetchMore(variables) { - this.$apollo.queries.group.fetchMore({ - variables: { ...this.queryVariables, ...variables }, - updateQuery(_, { fetchMoreResult }) { - return fetchMoreResult; - }, - }); + this.$router.push({ query: { before: this.pageInfo?.startCursor } }); }, async submit() { try { @@ -165,20 +156,23 @@ export default { </gl-alert> <title-area :title="$options.i18n.pageTitle"> <template #right-actions> - <gl-dropdown + <gl-disclosure-dropdown v-if="showDeleteDropdown" icon="ellipsis_v" - text="More actions" + :toggle-text="__('More actions')" :text-sr-only="true" category="tertiary" + placement="right" no-caret > - <gl-dropdown-item - v-gl-modal-directive="$options.confirmClearCacheModal" - variant="danger" - >{{ $options.i18n.clearCache }}</gl-dropdown-item - > - </gl-dropdown> + <gl-disclosure-dropdown-item v-gl-modal-directive="$options.confirmClearCacheModal"> + <template #list-item> + <span class="gl-text-red-500"> + {{ $options.i18n.clearCache }} + </span> + </template> + </gl-disclosure-dropdown-item> + </gl-disclosure-dropdown> <gl-button v-if="canClearCache" v-gl-tooltip="$options.i18n.settingsText" @@ -198,14 +192,14 @@ export default { <gl-form-input-group id="proxy-url" readonly - :value="group.dependencyProxyImagePrefix" + :value="dependencyProxyImagePrefix" select-on-click class="gl-layout-w-limited" data-testid="proxy-url" > <template #append> <clipboard-button - :text="group.dependencyProxyImagePrefix" + :text="dependencyProxyImagePrefix" :title="$options.i18n.copyImagePrefixText" /> </template> diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js index 74444d2c7ec..c115898c75b 100644 --- a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js @@ -1,8 +1,8 @@ import Vue from 'vue'; import { parseBoolean } from '~/lib/utils/common_utils'; -import app from '~/packages_and_registries/dependency_proxy/app.vue'; import { apolloProvider } from '~/packages_and_registries/dependency_proxy/graphql'; import Translate from '~/vue_shared/translate'; +import createRouter from './router'; Vue.use(Translate); @@ -11,10 +11,18 @@ export const initDependencyProxyApp = () => { if (!el) { return null; } - const { groupPath, groupId, noManifestsIllustration, canClearCache, settingsPath } = el.dataset; + const { + endpoint, + groupPath, + groupId, + noManifestsIllustration, + canClearCache, + settingsPath, + } = el.dataset; return new Vue({ el, apolloProvider, + router: createRouter(endpoint), provide: { groupPath, groupId, @@ -23,7 +31,7 @@ export const initDependencyProxyApp = () => { settingsPath, }, render(createElement) { - return createElement(app); + return createElement('router-view'); }, }); }; diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/router.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/router.js new file mode 100644 index 00000000000..087d8c189c4 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/router.js @@ -0,0 +1,14 @@ +import Vue from 'vue'; +import VueRouter from 'vue-router'; +import App from '~/packages_and_registries/dependency_proxy/app.vue'; + +Vue.use(VueRouter); + +export default function createRouter(base) { + const routes = [{ path: '/', name: 'dependencyProxyApp', component: App }]; + return new VueRouter({ + mode: 'history', + base, + routes, + }); +} diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/utils.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/utils.js new file mode 100644 index 00000000000..e6b97fac896 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/utils.js @@ -0,0 +1,24 @@ +import { GRAPHQL_PAGE_SIZE } from './constants'; + +const getNextPageParams = (cursor) => ({ + after: cursor, + first: GRAPHQL_PAGE_SIZE, +}); + +const getPreviousPageParams = (cursor) => ({ + first: null, + before: cursor, + last: GRAPHQL_PAGE_SIZE, +}); + +export const getPageParams = (pageInfo = {}) => { + if (pageInfo.before) { + return getPreviousPageParams(pageInfo.before); + } + + if (pageInfo.after) { + return getNextPageParams(pageInfo.after); + } + + return {}; +}; diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/index.js b/app/assets/javascripts/packages_and_registries/harbor_registry/index.js index 6185e4c7bc6..41a5a0e3797 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/index.js +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/index.js @@ -4,7 +4,7 @@ import { parseBoolean } from '~/lib/utils/common_utils'; import PerformancePlugin from '~/performance/vue_performance_plugin'; import Translate from '~/vue_shared/translate'; import RegistryBreadcrumb from '~/packages_and_registries/harbor_registry/components/harbor_registry_breadcrumb.vue'; -import { renderBreadcrumb } from '~/packages_and_registries/shared/utils'; +import { injectVueAppBreadcrumbs } from '~/lib/utils/breadcrumbs'; import createRouter from './router'; import HarborRegistryExplorer from './pages/index.vue'; @@ -79,7 +79,7 @@ export default (id) => { }; return { - attachBreadcrumb: renderBreadcrumb(router, null, RegistryBreadcrumb), + attachBreadcrumb: () => injectVueAppBreadcrumbs(router, RegistryBreadcrumb), attachMainComponent, }; }; diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue index 0cf49b25bf2..1020cd0c533 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue +++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_search.vue @@ -6,9 +6,7 @@ import { TOKEN_TITLE_TYPE, TOKEN_TYPE_TYPE, } from '~/vue_shared/components/filtered_search_bar/constants'; -import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; -import UrlSync from '~/vue_shared/components/url_sync.vue'; -import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils'; +import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue'; import { LIST_KEY_CREATED_AT } from '~/packages_and_registries/package_registry/constants'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import PackageTypeToken from './tokens/package_type_token.vue'; @@ -24,7 +22,10 @@ export default { operators: OPERATORS_IS, }, ], - components: { RegistrySearch, UrlSync, LocalStorageSync }, + components: { + LocalStorageSync, + PersistedSearch, + }, inject: ['isGroupPage'], data() { return { @@ -40,17 +41,25 @@ export default { sortableFields() { return sortableFields(this.isGroupPage); }, - parsedSorting() { - const cleanOrderBy = this.sorting?.orderBy.replace('_at', ''); - return `${cleanOrderBy}_${this.sorting?.sort}`.toUpperCase(); - }, - parsedFilters() { + }, + mounted() { + // local-storage-sync does not emit `input` + // event when key is not found, so set the + // flag if it hasn't been updated + this.$nextTick(() => { + if (!this.mountRegistrySearch) { + this.mountRegistrySearch = true; + } + }); + }, + methods: { + formatFilters(filters) { const parsed = { packageName: '', packageType: undefined, }; - return this.filters.reduce((acc, filter) => { + return filters.reduce((acc, filter) => { if (filter.type === TOKEN_TYPE_TYPE && filter.value?.data) { return { ...acc, @@ -68,28 +77,17 @@ export default { return acc; }, parsed); }, - }, - mounted() { - const queryParams = getQueryParams(window.document.location.search); - const { sorting, filters } = extractFilterAndSorting(queryParams); - this.updateSorting(sorting); - this.updateFilters(filters); - this.mountRegistrySearch = true; - this.emitUpdate(); - }, - methods: { - updateFilters(newValue) { - this.filters = newValue; - }, updateSorting(newValue) { this.sorting = { ...this.sorting, ...newValue }; }, - updateSortingAndEmitUpdate(newValue) { + updateSortingFromLocalStorage(newValue) { this.updateSorting(newValue); - this.emitUpdate(); + this.mountRegistrySearch = true; }, - emitUpdate() { - this.$emit('update', { sort: this.parsedSorting, filters: this.parsedFilters }); + emitUpdate(values) { + const { filters, sorting } = values; + this.updateSorting(sorting); + this.$emit('update', { ...values, filters: this.formatFilters(filters) }); }, }, }; @@ -99,22 +97,15 @@ export default { <local-storage-sync storage-key="package_registry_list_sorting" :value="sorting" - @input="updateSorting" + @input="updateSortingFromLocalStorage" > - <url-sync> - <template #default="{ updateQuery }"> - <registry-search - v-if="mountRegistrySearch" - :filters="filters" - :sorting="sorting" - :tokens="$options.tokens" - :sortable-fields="sortableFields" - @sorting:changed="updateSortingAndEmitUpdate" - @filter:changed="updateFilters" - @filter:submit="emitUpdate" - @query:changed="updateQuery" - /> - </template> - </url-sync> + <persisted-search + v-if="mountRegistrySearch" + :sortable-fields="sortableFields" + :default-order="sorting.orderBy" + :default-sort="sorting.sort" + :tokens="$options.tokens" + @update="emitUpdate" + /> </local-storage-sync> </template> diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue index a7831ef2588..b892305055c 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue +++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue @@ -48,10 +48,6 @@ export default { required: false, default: false, }, - pageInfo: { - type: Object, - required: true, - }, groupSettings: { type: Object, required: false, @@ -179,11 +175,8 @@ export default { :hidden-delete="!canDeletePackages" :is-loading="isLoading" :items="list" - :pagination="pageInfo" :title="listTitle" @delete="setItemsToBeDeleted" - @prev-page="$emit('prev-page')" - @next-page="$emit('next-page')" > <template #default="{ selectItem, isSelected, item, first }"> <packages-list-row diff --git a/app/assets/javascripts/packages_and_registries/package_registry/index.js b/app/assets/javascripts/packages_and_registries/package_registry/index.js index ae0f6d18d99..1a9b192e2c8 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/index.js +++ b/app/assets/javascripts/packages_and_registries/package_registry/index.js @@ -4,7 +4,7 @@ import { parseBoolean } from '~/lib/utils/common_utils'; import { apolloProvider } from '~/packages_and_registries/package_registry/graphql/index'; import PackageRegistry from '~/packages_and_registries/package_registry/pages/index.vue'; import RegistryBreadcrumb from '~/packages_and_registries/shared/components/registry_breadcrumb.vue'; -import { renderBreadcrumb } from '~/packages_and_registries/shared/utils'; +import { injectVueAppBreadcrumbs } from '~/lib/utils/breadcrumbs'; import createRouter from './router'; Vue.use(Translate); @@ -60,7 +60,7 @@ export default () => { }); return { - attachBreadcrumb: renderBreadcrumb(router, apolloProvider, RegistryBreadcrumb), + attachBreadcrumb: () => injectVueAppBreadcrumbs(router, RegistryBreadcrumb, apolloProvider), attachMainComponent, }; }; diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue index 6de89748708..a187c7a70d2 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue +++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue @@ -18,6 +18,12 @@ import DeletePackages from '~/packages_and_registries/package_registry/component import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue'; import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue'; import PackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue'; +import PersistedPagination from '~/packages_and_registries/shared/components/persisted_pagination.vue'; +import { + getPageParams, + getNextPageParams, + getPreviousPageParams, +} from '~/packages_and_registries/package_registry/utils'; export default { components: { @@ -28,6 +34,7 @@ export default { PackageList, PackageTitle, PackageSearch, + PersistedPagination, DeletePackages, }, directives: { @@ -39,7 +46,7 @@ export default { packagesResource: {}, sort: '', filters: {}, - mutationLoading: false, + isDeleteInProgress: false, pageParams: {}, }; }, @@ -100,7 +107,7 @@ export default { : this.$options.i18n.noResultsTitle; }, isLoading() { - return this.$apollo.queries.packagesResource.loading || this.mutationLoading; + return this.$apollo.queries.packagesResource.loading || this.isDeleteInProgress; }, refetchQueriesData() { return [ @@ -124,23 +131,16 @@ export default { historyReplaceState(cleanUrl); } }, - handleSearchUpdate({ sort, filters }) { - this.pageParams = {}; + handleSearchUpdate({ sort, filters, pageInfo }) { + this.pageParams = getPageParams(pageInfo); this.sort = sort; this.filters = { ...filters }; }, fetchNextPage() { - this.pageParams = { - first: GRAPHQL_PAGE_SIZE, - after: this.pageInfo?.endCursor, - }; + this.pageParams = getNextPageParams(this.pageInfo.endCursor); }, fetchPreviousPage() { - this.pageParams = { - first: null, - last: GRAPHQL_PAGE_SIZE, - before: this.pageInfo?.startCursor, - }; + this.pageParams = getPreviousPageParams(this.pageInfo.startCursor); }, }, i18n: { @@ -176,17 +176,14 @@ export default { <delete-packages :refetch-queries="refetchQueriesData" show-success-alert - @start="mutationLoading = true" - @end="mutationLoading = false" + @start="isDeleteInProgress = true" + @end="isDeleteInProgress = false" > <template #default="{ deletePackages }"> <package-list :group-settings="groupSettings" :list="packages.nodes" :is-loading="isLoading" - :page-info="pageInfo" - @prev-page="fetchPreviousPage" - @next-page="fetchNextPage" @delete="deletePackages" > <template #empty-state> @@ -210,5 +207,13 @@ export default { </package-list> </template> </delete-packages> + <div v-if="!isDeleteInProgress" class="gl-display-flex gl-justify-content-center"> + <persisted-pagination + class="gl-mt-3" + :pagination="pageInfo" + @prev="fetchPreviousPage" + @next="fetchNextPage" + /> + </div> </div> </template> diff --git a/app/assets/javascripts/packages_and_registries/package_registry/utils.js b/app/assets/javascripts/packages_and_registries/package_registry/utils.js index 4ff8edb8f66..35ff3d5ea63 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/utils.js +++ b/app/assets/javascripts/packages_and_registries/package_registry/utils.js @@ -1,6 +1,7 @@ import { capitalize } from 'lodash'; import { s__ } from '~/locale'; import { + GRAPHQL_PAGE_SIZE, PACKAGE_TYPE_CONAN, PACKAGE_TYPE_MAVEN, PACKAGE_TYPE_NPM, @@ -46,3 +47,26 @@ export const packageTypeToTrackCategory = (type) => `UI::${capitalize(type)}Pack export const sortableFields = (isGroupPage) => SORT_FIELDS.filter((f) => f.orderBy !== LIST_KEY_PROJECT || isGroupPage); + +export const getNextPageParams = (cursor) => ({ + after: cursor, + first: GRAPHQL_PAGE_SIZE, +}); + +export const getPreviousPageParams = (cursor) => ({ + first: null, + before: cursor, + last: GRAPHQL_PAGE_SIZE, +}); + +export const getPageParams = (pageInfo = {}) => { + if (pageInfo.before) { + return getPreviousPageParams(pageInfo.before); + } + + if (pageInfo.after) { + return getNextPageParams(pageInfo.after); + } + + return {}; +}; diff --git a/app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue b/app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue index dc61f3c788c..e00681f4183 100644 --- a/app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue +++ b/app/assets/javascripts/packages_and_registries/shared/components/cli_commands.vue @@ -1,5 +1,5 @@ <script> -import { GlDropdown } from '@gitlab/ui'; +import { GlDisclosureDropdown } from '@gitlab/ui'; import Tracking from '~/tracking'; import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue'; import { @@ -16,8 +16,8 @@ const trackingLabel = 'quickstart_dropdown'; export default { components: { - GlDropdown, CodeInstruction, + GlDisclosureDropdown, }, mixins: [Tracking.mixin({ label: trackingLabel })], props: { @@ -47,14 +47,13 @@ export default { }; </script> <template> - <gl-dropdown - :text="$options.i18n.QUICK_START" + <gl-disclosure-dropdown + :toggle-text="$options.i18n.QUICK_START" variant="confirm" - right + placement="right" @shown="track('click_dropdown')" > - <!-- This li is used as a container since gl-dropdown produces a root ul, this mimics the functionality exposed by b-dropdown-form --> - <li role="presentation" class="px-2 py-1"> + <div class="gl-px-3 gl-py-2"> <code-instruction :label="$options.i18n.LOGIN_COMMAND_LABEL" :instruction="dockerLoginCommand" @@ -79,6 +78,6 @@ export default { tracking-action="click_copy_push" :tracking-label="$options.trackingLabel" /> - </li> - </gl-dropdown> + </div> + </gl-disclosure-dropdown> </template> diff --git a/app/assets/javascripts/packages_and_registries/shared/components/persisted_search.vue b/app/assets/javascripts/packages_and_registries/shared/components/persisted_search.vue index 95343a3a09b..529086e7f8c 100644 --- a/app/assets/javascripts/packages_and_registries/shared/components/persisted_search.vue +++ b/app/assets/javascripts/packages_and_registries/shared/components/persisted_search.vue @@ -87,6 +87,7 @@ export default { sort: this.parsedSorting, filters: this.filters, pageInfo: this.pageInfo, + sorting: this.sorting, }); }, }, diff --git a/app/assets/javascripts/packages_and_registries/shared/utils.js b/app/assets/javascripts/packages_and_registries/shared/utils.js index bda0839092e..a19c8ed5866 100644 --- a/app/assets/javascripts/packages_and_registries/shared/utils.js +++ b/app/assets/javascripts/packages_and_registries/shared/utils.js @@ -1,4 +1,3 @@ -import Vue from 'vue'; import { queryToObject } from '~/lib/utils/url_utility'; import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants'; @@ -47,28 +46,3 @@ export const getCommitLink = ({ project_path: projectPath, pipeline = {} }, isGr return `../commit/${pipeline.sha}`; }; - -export const renderBreadcrumb = (router, apolloProvider, RegistryBreadcrumb) => () => { - const breadCrumbEls = document.querySelectorAll('nav .js-breadcrumbs-list li'); - const breadCrumbEl = breadCrumbEls[breadCrumbEls.length - 1]; - const lastCrumb = breadCrumbEl.children[0]; - const crumbs = [lastCrumb]; - const nestedBreadcrumbEl = document.createElement('div'); - breadCrumbEl.replaceChild(nestedBreadcrumbEl, lastCrumb); - return new Vue({ - el: nestedBreadcrumbEl, - router, - apolloProvider, - components: { - RegistryBreadcrumb, - }, - render(createElement) { - return createElement('registry-breadcrumb', { - class: breadCrumbEl.className, - props: { - crumbs, - }, - }); - }, - }); -}; |