Geo Replicables List: Add ability to find a record by ID in UI
Why are we doing this work
note: This may need to be implemented via multiple MRs.
The list view is currently going through a migration and may look different depending on if you have the feature flag geo_replicables_filtered_list_view and/or geo_replicables_show_view enabled.
We are working to enhance the functionality available in the Geo Replicables List View &16585 (closed)
Currently, there is no way for a customer to do the following:
Find an exact replication record on demand in the UI
Typically, we solve this issue in list views by adding search-ability. Searching is a very complicated subject inside of Geo due to how Geo Registries are stored. This change proposing a middle ground of providing a way to search by ID to return a single record if it exists.
Why this is NOT a search
Searching comes with expectations of more robust functionality. We have learned in the past that overpromising on search functionality can really be harmful to the trust customers have in a feature.
More can be read about this over on Geo: Support Filtering Replicables by Keyword (#411770 - closed)
Rather I am proposing we find a middle ground where we clearly communicate through the UI to customers that this a find by ID function rather than a search. Allow customers who know exactly what they are looking for to directly find it without having to sift through pages of records.
Considerations
With the upcoming UI changes we are going to be using FilteredSearch. The intent is the user will be able to freeform search for a Registry via Registry ID. We can build a semi-intelligent mechanism that can attempt to interpret the search and then Generate the GID to form a proper API query.
Proposal Demo
Screen_Recording_2025-04-10_at_1.58.04_PM
Relevant links
- Screenshot of upcoming UI changes
- Epic related to creating a Keyword search in Geo: Geo: Add keyword search for components in repli... (&11593)
- Replicable filter UI
geo_replicable_filter_bar.vue
Implementation plan
- Add the ability to manage the
idsin the vuex store (geo_replicable/store)
// state.js
idsFilter: '',
// mutation_types.js
export const SET_IDS_FILTER = 'SET_IDS_FILTER';
// mutations.js
[types.SET_IDS_FILTER](state, filter) {
state.idsFilter = filter;
},
- Add ability when setting the
idsfilter in the vuex store to accept either thegidorregistryId
// actions.js
export const setIdsFilter = ({ commit }, { ids, graphqlRegistryClass }) => {
const filter = ids.split(' ').map(id => {
if (isGid(id)) {
return id
}
try {
const num = id.replace(`${graphqlRegistryClass}/`, '')
return convertToGraphQLId(graphqlRegistryClass, num)
} catch {
return null
}
})
commit(types.SET_IDS_FILTER, filter);
};
- Add ability to add the
idsto the GraphQL filterreplicable_type_query_builder.js
// replicable_type_query_builder.js
// some of file omitted for clairty
export default (graphQlFieldName, verificationEnabled) => {
return gql`
query($first: Int, $last: Int, $before: String!, $after: String!, $replicationState: ReplicationStateEnum, $ids: [ID!]) {
geoNode {
${graphQlFieldName}(first: $first, last: $last, before: $before, after: $after, replicationState: $replicationState, ids: $ids) {
}
}
`
}
// actions.js
// some of file omitted for clarity
export const fetchReplicableItems = ({ state, dispatch }, direction) => {
// ...
const ids = state.idsFilter || null;
client
.query({
query: buildReplicableTypeQuery(state.graphqlFieldName, state.verificationEnabled),
variables: { first, last, before, after, replicationState, ids },
})
}
- Add support for the
idsas a token ingeo_replicable/constants.js
// some of file omitted for clarity
// constants.js
export const TOKEN_TYPES = {
// ...
IDS: 'ids'
};
- Add support for the
idsas a filter ingeo_replicable/filters.js
// some of file omitted for clarity
// filters.js
export const processFilters = (filters) => {
// ...
// ids is stored as plaintext in the filtered search
if (typeof filter === 'string') {
query[TOKEN_TYPES.IDS] = filter
}
return { query, url };
};
- Add support to get the
idsfrom the query viagetFiltersFromQuery()inapp.vue
// some of file omitted for clarity
// app.vue
getFiltersFromQuery() {
// ...
const { ids } = queryToObject(window.location.search || '');
// IDs filter is treated as plaintext and should be last filter in array
if (ids) {
filters.push(ids)
this.setIdsFilter({ ids, graphqlRegistryClass: this.graphqlRegistryClass })
}
},
- Update
search-text-option-labelto communicate it is a freeform search by id ingeo_replicable_filtered_search.vue
// some of file omitted for clarity
// geo_replicable_filtered_search.vue
<script>
export default {
i18n: {
searchById: __('Search by ID')
}
}
</script>
<template>
<gl-filtered-search
:search-text-option-label="$options.i18n.searchById"
/>
</template>