import filterMapping from "@/data/FiltersLabelMapping.json";
import Client from "@/lib/GraphClient/GraphClient.js";
import recordsQuery from "@/lib/GraphClient/queries/getRecords.json";
let client = new Client();
export const mutations = {
setCollectionIdsParam(state, collectionIDs) {
state.collectionIDs = collectionIDs;
state.params["ids"] = collectionIDs;
},
setRecords(state, data) {
state.records = data["records"];
state.facets = buildFacets(data["aggregations"]);
state.totalPages = data["totalPages"];
state.perPage = data["perPage"];
state.currentPage = data["currentPage"];
state.hits = data["totalCount"];
},
resetRecords(state) {
recordsQuery.queryParam = null;
state.records = [];
},
resetPages(state) {
state.hits = null;
state.perPage = null;
state.currentPage = 1;
state.totalPages = null;
},
setLoadingStatus(state, status) {
state.loading = status;
},
cleanRecordsStore(state) {
state.params = { ids: [] };
state.collectionIDs = [];
state.records = [];
state.facets = [];
state.hits = null;
state.loading = false;
state.totalPages = null;
state.perPage = null;
state.currentPage = 1;
},
};
export const actions = {
async initializeCollectionRecords(state, collectionIDs) {
this.commit("records/setCollectionIdsParam", collectionIDs);
this.commit("records/setLoadingStatus", true);
this.commit("records/resetRecords");
this.commit("records/resetPages");
recordsQuery.queryParam = state.state.params;
let data;
try {
data = await client.executeQuery(recordsQuery);
this.commit("records/setRecords", data["searchFairsharingRecords"]);
this.commit("records/setLoadingStatus", false);
} catch {
// Loading complete, but no data returned...
this.commit("records/setRecords", { records: [] });
}
},
async fetchCollectionRecords(state, options) {
let params = options.params;
let token = options.token;
this.commit("records/setLoadingStatus", true);
this.commit("records/resetRecords");
this.commit("records/resetPages");
//initialize params state
state.state.params = { ids: [...state.state.params.ids] };
Object.keys(params).forEach((key) => {
state.state.params[key] = params[key];
});
recordsQuery.queryParam = state.state.params;
let data;
try {
if (token) {
client.setHeader(token);
}
data = await client.executeQuery(recordsQuery);
this.commit("records/setRecords", data["searchFairsharingRecords"]);
this.commit("records/setLoadingStatus", false);
} catch {
// Loading complete, but no data returned...
this.commit("records/setRecords", { records: [] });
}
},
async fetchRecords(state, options) {
let params = options.params;
let token = options.token;
this.commit("records/setLoadingStatus", true);
this.commit("records/resetRecords");
this.commit("records/resetPages");
if (Object.keys(params).length > 0) {
// attempt to fix single fields with brackets, as per:
// https://github.com/FAIRsharing/fairsharing.github.io/issues/2648
Object.keys(params).forEach((key) => {
if (String(params[key]).includes('(') || String(params[key]).includes(')')) {
params[key] = [params[key]];
}
})
// params['q'] needs to be sanitised here.
if ("q" in params) {
// TODO: Is it worth preserving foreign characters as discussed here?
// https://stackoverflow.com/questions/22192458/how-to-remove-non-alphanumeric-characters-and-space-but-keep-foreign-language-i
const cleaned = params["q"].replace(/[^0-9a-z\s]/gi, "");
const newParams = { ...params, q: cleaned };
recordsQuery.queryParam = newParams;
} else {
recordsQuery.queryParam = params;
}
}
let data;
try {
if (token) {
client.setHeader(token);
}
data = await client.executeQuery(recordsQuery);
// See: https://github.com/FAIRsharing/FAIRsharing-API/issues/532
if (data["error"] === "invalid query") {
this.commit("records/setRecords", {
aggregations: {
is_invalid: {
meta: {},
doc_count: 1,
doc_count_error_upper_bound: 1,
sum_other_doc_count: 1,
buckets: [{ key: 1, key_as_string: "true", doc_count: 1 }],
},
},
records: [],
});
} else {
this.commit("records/setRecords", data["searchFairsharingRecords"]);
}
this.commit("records/setLoadingStatus", false);
} catch {
// Loading complete, but no data returned...
/* istanbul ignore next */
this.commit("records/setRecords", { records: [] });
}
},
resetRecords() {
this.commit("records/resetRecords");
},
};
export const getters = {
getFilter: (state) => (facetName) => {
if (state.facets.length > 0) {
let currentFacet = JSON.parse(
JSON.stringify(
state.facets.find((facet) => facet.filterName === facetName)
)
);
currentFacet["values"] = currentFacet["buckets"];
return currentFacet;
}
return [];
},
getRecordsLength: (state) => {
return state.records.length;
},
getCollectionIdsParams: (state) => {
return state.collectionIDs;
},
};
/**
* The records store handles the requests related to records (searchFairsharingRecords and fairsharingRecord).
* @type {Object}
*/
let recordsStore = {
namespaced: true,
state: {
params: { ids: [] },
collectionIDs: [],
records: [],
facets: [],
hits: null,
loading: false,
totalPages: null,
perPage: null,
currentPage: 1,
},
mutations: mutations,
actions: actions,
getters: getters,
};
export default recordsStore;
/**
* Given an object containing the raw facets coming from the client and a mapping object , build the ready to use facets
* for usage by the Vue components.
* @param {Object} rawFacets - the aggregation object coming from the API response as data['aggregations']
* @returns {Array} output - the array of ready to use facets containing a name, a label and values
*/
export const buildFacets = function (rawFacets) {
let output = [];
const mapper = filterMapping["autocomplete"];
Object.keys(rawFacets).forEach(function (facetName) {
if (Object.prototype.hasOwnProperty.call(mapper, facetName)) {
let localFacet = mapper[facetName];
rawFacets[facetName]["buckets"].forEach(function (bucket) {
if (Object.prototype.hasOwnProperty.call(bucket, "key_as_string")) {
bucket["key"] = bucket["key_as_string"];
}
});
localFacet["buckets"] = rawFacets[facetName]["buckets"];
output.push(localFacet);
}
});
return output;
};