[go: up one dir, main page]

Skip to content

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

Implementation plan

  1. 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 };
});
  1. Expose newly added FILTERED_SEARCH_TOKEN_OPTIONS to the index.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,
    },
  });
};
  1. 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 };
};
  1. 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];
},
  1. Add activeFilteredSearchFilters computed property and pass it to the proper component in app.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
  1. 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>
  1. Update emptyState computed property to handle filters in app.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 🤖