Source: store/searchFilters.js

import { isEqual } from "lodash";

import buttonOptions from "@/data/ButtonOptions.json";
import filterMapping from "@/data/FiltersLabelMapping.json";
import homePageData from "@/data/homePageData.json";
import GraphQLClient from "@/lib/GraphClient/GraphClient.js";
import query from "@/lib/GraphClient/queries/getFilters.json";

const graphClient = new GraphQLClient();

export const mutations = {
  setFilters(state, data) {
    state.filtersStatistic = data["searchFairsharingRecords"]["aggregations"];
    state.rawFilters = buildFilters(state.filtersStatistic);
    state.filters = state.rawFilters.filter(
      (item) => item.type !== "Boolean" && item.filterName !== "status",
    );
  },
  setFilterButtons(state) {
    state.filterButtons.push({
      data: [
        {
          title: "Match all terms",
          active: true,
          filterName: "searchAnd",
          value: true,
        },
        {
          title: "Match any term",
          active: false,
          filterName: "searchAnd",
          value: false,
        },
      ],
      curator_only: false,
    });
    state.rawFilters.forEach((item) => {
      // TODO: Return here if the button is marked as curator-only and the user isn't logged in as a curator.
      if (item.type === "Boolean") {
        let ObjectModel = buttonOptions[item.filterName];
        state.filterButtons.push(ObjectModel);
      } else if (item.filterName === "status") {
        let ObjectModel = buttonOptions.status.data;
        ObjectModel.forEach(function (button) {
          if (Object.prototype.hasOwnProperty.call(button, "apiIndex")) {
            button.value = item.values[button["apiIndex"]];
          }
        });
        state.filterButtons.push({ data: ObjectModel, curator_only: false });
      }
    });
  },
  setLoadingStatus(state, status) {
    state.isLoadingFilters = status;
  },
  resetFilterButtons(state, itemParentIndex) {
    state.filterButtons[itemParentIndex].data.map((item) => {
      item.active = false;
    });
  },
  activateButton(state, item) {
    state.filterButtons[item.itemParentIndex].data.map((filterItem) => {
      if (isEqual(filterItem, item.activeItem)) {
        filterItem.active = true;
      }
    });
  },
};
export const actions = {
  resetFilterButtons(state, itemParentIndex) {
    this.commit("searchFilters/resetFilterButtons", itemParentIndex);
  },
  activateButton(state, item) {
    this.commit("searchFilters/activateButton", item);
  },
  async assembleFilters() {
    this.commit("searchFilters/setLoadingStatus", true);

    // Please refer to ticket:
    // https://github.com/FAIRsharing/fairsharing.github.io/issues/1288
    let keys = [];
    homePageData.blockInfo["database"]["items"].forEach((item) => {
      keys.push(item.option.key);
    });

    let data = await graphClient.executeQuery(query);
    this.commit("searchFilters/setFilters", data);
    this.commit("searchFilters/setFilterButtons");
    this.commit("searchFilters/setLoadingStatus", false);
  },
};
export const getters = {
  getFilters: (state) => {
    let output = [];
    state.filters.forEach(function (filter) {
      output.push({
        filterName: filter.filterName,
        filterLabel: filter.filterLabel,
      });
    });
    return output;
  },

  getFiltersStatisticCount: (state) => (option) => {
    if (state.filtersStatistic && state.filtersStatistic[option.filterName]) {
      const targetBucket = state.filtersStatistic[
        option.filterName
      ].buckets.find((item) => item.key === option.key);

      return targetBucket ? targetBucket.doc_count : 0;
    }
    return 0;
  },
};

/**
 * The searchFilters store trigger a single field query to searchFairsharingRecords, gets the aggregation array and
 * builds the filtering system to be used by advanced search functions.
 * @type {Object}
 */
let filtersStore = {
  namespaced: true,
  state: {
    rawFilters: [],
    filters: [],
    filtersStatistic: [],
    filterButtons: [],
    isLoadingFilters: false,
    databaseCount: {},
  },
  mutations: mutations,
  actions: actions,
  getters: getters,
};
export default filtersStore;

/**
 * Given a searchFairsharingRecords aggregations array, build the values used by the advanced search widgets
 * @param {Array} val - an array of raw filters coming from the api as data['searchFairsharingRecords']['aggregations']
 * @returns {Array} filters - ready to use filters for the advanced search components
 */

export const buildFilters = function (val) {
  let filters = [];
  let filtersLabels = filterMapping["autocomplete"];
  Object.keys(val).forEach(function (key) {
    if (Object.prototype.hasOwnProperty.call(filtersLabels, key)) {
      let filter = filtersLabels[key];
      filter.values = null;
      let filterValues = [];

      let buckets = val[key]["buckets"];
      buckets.forEach(function (bucket) {
        if (Object.prototype.hasOwnProperty.call(bucket, "key_as_string")) {
          filterValues.push(bucket["key_as_string"]);
        } else {
          filterValues.push(bucket["key"]);
        }
      });
      filter.values = filterValues;
      filters.push(filter);
    }
  });
  return filters;
};