// (C) 2019-2020 GoodData Corporation import { ExecuteAFM as AFM } from "@gooddata/typings"; import { compact } from "lodash"; export const ALL_TIME_GRANULARITY = "ALL_TIME_GRANULARITY"; function getDateFilter(filters: AFM.CompatibilityFilter[] = []): AFM.DateFilterItem { return filters.find(AFM.isDateFilter); } function getAttributeFilters(filters: AFM.CompatibilityFilter[] = []): AFM.AttributeFilterItem[] { return filters.filter(AFM.isAttributeFilter); } const getMeasureValueFilters = (filters: AFM.CompatibilityFilter[] = []): AFM.IMeasureValueFilter[] => { return filters.filter(AFM.isMeasureValueFilter); }; const getRankingFilters = (filters: AFM.CompatibilityFilter[] = []): AFM.IRankingFilter[] => { return filters.filter(AFM.isRankingFilter); }; /** * Return uri or identifier from ObjQualifier * * @method getId * @param {AFM.ObjQualifier} obj * @returns {string|null} */ export function getId(obj: AFM.ObjQualifier): string | null { if ((obj as AFM.IObjUriQualifier).uri) { return (obj as AFM.IObjUriQualifier).uri; } if ((obj as AFM.IObjIdentifierQualifier).identifier) { return (obj as AFM.IObjIdentifierQualifier).identifier; } return null; } /** * Returns date filter date dataset * * @method getDateFilterDateDataSet * @param {AFM.DateFilterItem} filter * @returns {AFM.ObjQualifier | null } */ export function getDateFilterDateDataSet(filter: AFM.DateFilterItem): AFM.ObjQualifier { if (AFM.isRelativeDateFilter(filter)) { return filter.relativeDateFilter.dataSet; } if (AFM.isAbsoluteDateFilter(filter)) { return filter.absoluteDateFilter.dataSet; } throw new Error("Unsupported type of date filter"); } /** * Returns true if dateFilters dataSets match * * @method dateFiltersDataSetsMatch * @param {AFM.DateFilterItem} f1 * @param {AFM.DateFilterItem} f2 * @returns {AFM.ObjQualifier | null | boolean} */ export function dateFiltersDataSetsMatch(f1: AFM.DateFilterItem, f2: AFM.DateFilterItem) { const d1 = getDateFilterDateDataSet(f1); const d2 = getDateFilterDateDataSet(f2); return d1 && d2 && getId(d1) === getId(d2); } function isDateFilterAllTime(dateFilter: AFM.DateFilterItem): boolean { if (AFM.isRelativeDateFilter(dateFilter)) { return dateFilter.relativeDateFilter.granularity === ALL_TIME_GRANULARITY; } return false; } /** * Append attribute filters and date filter to afm * * Date filter handling: * - Override if date filter has the same id * - Add if date filter if date filter id is different * * Attribute filter handling: * - Add all * * @method appendFilters * @param {AFM.IAfm} afm * @param {AFM.AttributeFilterItem[]} attributeFilters * @param {AFM.DateFilterItem} dateFilter * @param {AFM.IMeasureValueFilter} measureValueFilters * @param {AFM.IRankingFilter} rankingFilters * @return {AFM.IAfm} */ export function appendFilters( afm: AFM.IAfm, attributeFilters: AFM.AttributeFilterItem[], dateFilter?: AFM.DateFilterItem, measureValueFilters?: AFM.IMeasureValueFilter[], rankingFilters?: AFM.IRankingFilter[], ): AFM.IAfm { const dateFilters: AFM.DateFilterItem[] = dateFilter && !isDateFilterAllTime(dateFilter) ? [dateFilter] : []; const afmDateFilter = afm.filters ? afm.filters.filter(AFM.isDateFilter)[0] : null; // all-time selected, need to delete date filter from filters let afmFilters = afm.filters || []; if (dateFilter && isDateFilterAllTime(dateFilter)) { afmFilters = afmFilters.filter(filter => { if (AFM.isDateFilter(filter)) { return !dateFiltersDataSetsMatch(filter, dateFilter); } return true; }); } if ( (afmDateFilter && dateFilter && !dateFiltersDataSetsMatch(afmDateFilter, dateFilter)) || (afmDateFilter && !dateFilter) ) { dateFilters.push(afmDateFilter); } const afmNonDateFilters = afmFilters.filter(filter => !AFM.isDateFilter(filter)); const filters = compact([ ...afmNonDateFilters, ...attributeFilters, ...dateFilters, ...(measureValueFilters || []), ...(rankingFilters || []), ]); if (filters.length || (afm.filters && afm.filters.length)) { return { ...afm, filters, }; } return afm; } export function mergeFiltersToAfm( afm: AFM.IAfm, additionalFilters: AFM.CompatibilityFilter[] = [], ): AFM.IAfm { const attributeFilters = getAttributeFilters(additionalFilters); const dateFilter = getDateFilter(additionalFilters); const measureValueFilters = getMeasureValueFilters(additionalFilters); const rankingFilters = getRankingFilters(additionalFilters); return appendFilters(afm, attributeFilters, dateFilter, measureValueFilters, rankingFilters); }