Geo Primary Verification List: Hookup filtered search filters to UI
Why are we doing this work
This work will be behind feature flag geo_primary_verification_view
This work is focused on taking the UI added as as part of Geo Primary Verification List: Hookup `geo_shar... (#538023 - closed) and hooking up the filters that will be supported in the API Geo Primary Verification API: GET `api/v4/admin... (#537710 - closed). The API itself will be hooked up to the UI in Geo Primary Verification List: Hookup API to UI (#538025 - closed) and this functionality can be added whether or not that is implemented yet.
These filters will function very similar to how we utilize them in the Geo Replicables views: https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/geo_replicable/filters.js
Relevant links
- UI issue: Geo Primary Verification List: Hookup `geo_shar... (#538023 - closed)
- API Endpoint Issue: Geo Primary Verification API: GET `api/v4/admin... (#537710 - closed)
- Geo Replicables filters: https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/geo_replicable/filters.js
Implementation plan
- Define tokens and items needed in the
constants.js
export const CHECKSUM_STATUS_STATES_ARRAY = [
{
title: s__('Geo|Pending'),
value: 'pending',
},
{
title: s__('Geo|Started'),
value: 'started',
},
{
title: s__('Geo|Succeeded'),
value: 'succeeded',
},
{
title: s__('Geo|Failed'),
value: 'failed',
},
{
title: s__('Geo|Disabled'),
value: 'disabled',
},
{
title: s__('Geo|Unknown'),
value: null,
},
]
export const TOKEN_TYPES = {
CHECKSUM_STATUS: 'checksum_status'
};
export const FILTERED_SEARCH_TOKEN_DEFINITIONS = [
{
title: s__('Geo|Checksum status'),
type: TOKEN_TYPES.CHECKSUM_STATUS,
icon: 'check-circle',
token: GlFilteredSearchToken,
operators: OPERATORS_IS,
unique: true,
},
];
export const FILTERED_SEARCH_TOKEN_OPTIONS = FILTERED_SEARCH_TOKEN_DEFINITIONS.map((def) => {
let options = [];
if (def.type === TOKEN_TYPES.CHECKSUM_STATUS) {
options = CHECKSUM_STATUS_STATES_ARRAY;
}
return { ...def, options };
});
- Expose newly added
FILTERED_SEARCH_TOKEN_OPTIONS
to theindex.js
and provide it to the Vue app.
import { FILTERED_SEARCH_TOKEN_OPTIONS } from './constants'
export const initDataManagement = () => {
// most of file omitted
return new Vue({
// omitted
provide: {
filteredSearchTokens: FILTERED_SEARCH_TOKEN_OPTIONS,
},
});
};
- Added needed methods and new filter support to the
filters.js
export const isValidFilter = (data, array) => {
return data && array?.some(({ value }) => value === data);
};
export const getChecksumStatusFilter = (data) => {
return {
type: TOKEN_TYPES.CHECKSUM_STATUS,
value: {
data,
},
};
};
export const processFilters = (filters) => {
// URL Structure: /admin/data_management/${MODEL}?${FILTERS}
const url = new URL(window.location.href);
const query = {};
filters.forEach((filter) => {
// other filters omitted
if (filter.type === TOKEN_TYPES.CHECKSUM_STATUS) {
query[TOKEN_TYPES.CHECKSUM_STATUS] = filter.value.data;
}
});
return { query, url };
};
- Add updated logic to get filter from URL onCreate in the `app.vue
getFiltersFromQuery() {
const filters = [];
const url = new URL(window.location.href);
const segments = pathSegments(url);
const { checksum_status: checksumStatus } = queryToObject(window.location.search || '');
if (isValidFilter(checksumStatus, CHECKSUM_STATUS_STATES_ARRAY)) {
filters.push(getChecksumStatusFilter(checksumStatus));
}
this.activeFilters = [getModelFilter(segments.pop()), ...filters];
},
- Add
activeFilteredSearchFilters
computed property and pass it to the proper component inapp.vue
<script>
export default {
computed: {
activeFilteredSearchFilters() {
return this.activeFilters.filter(({ type }) => type !== TOKEN_TYPES.MODEL);
},
},
}
</script>
<template>
<geo-list-top-bar
:active-filtered-search-filters="activeFilteredSearchFilters"
/>
</template
- Update events to process filter changes and hook up event in template in
app.vue
<script>
export default {
methods: {
// This event needs to handle the activeFilteredSearchFilters now
onListboxChange(val) {
this.onSearch([getModelFilter(val), ...this.activeFilteredSearchFilters]);
},
}
}
</script>
<template>
<geo-list-top-bar
@search="onSearch"
/>
</template>
- Update
emptyState
computed property to handle filters inapp.vue
emptyState() {
const title = this.activeFilteredSearchFilters.length
? sprintf(this.$options.i18n.noResultsFilteredTitle, { model: this.activeModel })
: this.$options.i18n.noResultsFoundTitle
const description = this.activeFilteredSearchFilters.length
? this.$options.i18n.noResultsFilteredDescription
: this.$options.i18n.noResultsFoundDescription
return {
title,
description,
item: this.activeModel,
svgPath: this.emptyStateSvgPath,
helpLink: GEO_TROUBLESHOOTING_LINK,
};
},
Edited by 🤖 GitLab Bot 🤖