diff options
Diffstat (limited to 'app/assets/javascripts/packages_and_registries/shared')
3 files changed, 171 insertions, 0 deletions
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 new file mode 100644 index 00000000000..9b2de1a1b84 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/shared/components/persisted_search.vue @@ -0,0 +1,80 @@ +<script> +import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; +import UrlSync from '~/vue_shared/components/url_sync.vue'; +import { extractFilterAndSorting, getQueryParams } from '~/packages_and_registries/shared/utils'; + +export default { + components: { RegistrySearch, UrlSync }, + props: { + sortableFields: { + type: Array, + required: true, + }, + defaultOrder: { + type: String, + required: true, + }, + defaultSort: { + type: String, + required: true, + }, + }, + data() { + return { + filters: [], + sorting: { + orderBy: this.defaultOrder, + sort: this.defaultSort, + }, + mountRegistrySearch: false, + }; + }, + computed: { + parsedSorting() { + const cleanOrderBy = this.sorting?.orderBy.replace('_at', ''); + return `${cleanOrderBy}_${this.sorting?.sort}`.toUpperCase(); + }, + }, + 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) { + this.updateSorting(newValue); + this.emitUpdate(); + }, + emitUpdate() { + this.$emit('update', { sort: this.parsedSorting, filters: this.filters }); + }, + }, +}; +</script> + +<template> + <url-sync> + <template #default="{ updateQuery }"> + <registry-search + v-if="mountRegistrySearch" + :filter="filters" + :sorting="sorting" + :tokens="$options.tokens" + :sortable-fields="sortableFields" + @sorting:changed="updateSortingAndEmitUpdate" + @filter:changed="updateFilters" + @filter:submit="emitUpdate" + @query:changed="updateQuery" + /> + </template> + </url-sync> +</template> diff --git a/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue b/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue new file mode 100644 index 00000000000..a1e3c06812c --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/shared/components/registry_breadcrumb.vue @@ -0,0 +1,56 @@ +<script> +// We are using gl-breadcrumb only at the last child of the handwritten breadcrumb +// until this gitlab-ui issue is resolved: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1079 +// +// See the CSS workaround in app/assets/stylesheets/pages/registry.scss when this file is changed. +import { GlBreadcrumb, GlIcon } from '@gitlab/ui'; + +export default { + components: { + GlBreadcrumb, + GlIcon, + }, + computed: { + rootRoute() { + return this.$router.options.routes.find((r) => r.meta.root); + }, + detailsRoute() { + return this.$router.options.routes.find((r) => r.name === 'details'); + }, + isRootRoute() { + return this.$route.name === this.rootRoute.name; + }, + detailsRouteName() { + return this.detailsRoute.meta.nameGenerator(); + }, + isLoaded() { + return this.isRootRoute || this.detailsRouteName; + }, + allCrumbs() { + const crumbs = [ + { + text: this.rootRoute.meta.nameGenerator(), + to: this.rootRoute.path, + }, + ]; + if (!this.isRootRoute) { + crumbs.push({ + text: this.detailsRouteName, + href: this.detailsRoute.meta.path, + }); + } + return crumbs; + }, + }, +}; +</script> + +<template> + <gl-breadcrumb :key="isLoaded" :items="allCrumbs"> + <template #separator> + <span class="gl-mx-n5"> + <gl-icon name="angle-right" :size="8" /> + </span> + </template> + </gl-breadcrumb> +</template> diff --git a/app/assets/javascripts/packages_and_registries/shared/utils.js b/app/assets/javascripts/packages_and_registries/shared/utils.js index cf18f655e79..7e963cd0b08 100644 --- a/app/assets/javascripts/packages_and_registries/shared/utils.js +++ b/app/assets/javascripts/packages_and_registries/shared/utils.js @@ -1,3 +1,4 @@ +import Vue from 'vue'; import { queryToObject } from '~/lib/utils/url_utility'; import { FILTERED_SEARCH_TERM } from './constants'; @@ -38,3 +39,37 @@ 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) { + // FIXME(@tnir): this is a workaround until the MR gets merged: + // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48115 + const parentEl = breadCrumbEl.parentElement.parentElement; + if (parentEl) { + parentEl.classList.remove('breadcrumbs-container'); + parentEl.classList.add('gl-display-flex'); + parentEl.classList.add('w-100'); + } + // End of FIXME(@tnir) + return createElement('registry-breadcrumb', { + class: breadCrumbEl.className, + props: { + crumbs, + }, + }); + }, + }); +}; |