@gooddata/react-components
Version:
GoodData.UI - A powerful JavaScript library for building analytical applications
210 lines (182 loc) • 6.83 kB
text/typescript
// (C) 2019-2020 GoodData Corporation
import get = require("lodash/get");
import set = require("lodash/set");
import includes = require("lodash/includes");
import every = require("lodash/every");
import isEmpty = require("lodash/isEmpty");
import omitBy = require("lodash/omitBy");
import isNil = require("lodash/isNil");
import { AFM } from "@gooddata/typings";
import { DataLayer } from "@gooddata/gooddata-js";
import { SORT_DIR_ASC, SORT_DIR_DESC } from "../constants/sort";
import {
IBucket,
IBucketItem,
IExtendedReferencePoint,
IVisualizationProperties,
} from "../interfaces/Visualization";
import { getFirstAttribute, getFirstValidMeasure } from "./bucketHelper";
import { VisualizationTypes } from "../../constants/visualizationTypes";
import * as SortsHelper from "../../helpers/sorts";
export function getMeasureSortItems(identifier: string, direction: AFM.SortDirection): AFM.SortItem[] {
return [
{
measureSortItem: {
direction,
locators: [
{
measureLocatorItem: {
measureIdentifier: identifier,
},
},
],
},
},
];
}
function getDefaultTableSort(afm: AFM.IAfm): AFM.SortItem[] {
const attribute: AFM.IAttribute = get(afm, "attributes.0");
if (!attribute) {
return SortsHelper.getFirstMeasureSort(afm);
}
return [SortsHelper.getAttributeSortItem(attribute.localIdentifier, SORT_DIR_ASC)];
}
function getDefaultGeoPushpinSort(afm: AFM.IAfm): AFM.SortItem[] {
return SortsHelper.getDefaultAttributeGeoPushpinSort(afm);
}
export function getDefaultPivotTableSort(afm: AFM.IAfm): AFM.SortItem[] {
const attribute: AFM.IAttribute = get(afm, "attributes.0");
if (!attribute) {
return [];
}
return [];
}
function sanitizeSorts(afm: AFM.IAfm, sorts: AFM.SortItem[]): AFM.SortItem[] {
if (isEmpty(sorts)) {
return [];
}
return sorts.filter((sortItem: AFM.SortItem) => DataLayer.ResultSpecUtils.isSortValid(afm, sortItem));
}
// Consider disolving this function into individual components
export function createSorts(
type: string,
afm: AFM.IAfm,
resultSpec: AFM.IResultSpec,
visualizationProperties: IVisualizationProperties,
canSortStackTotalValue: boolean = false,
enableSortingByTotalGroup: boolean = false,
): AFM.SortItem[] {
const sortItems = get(visualizationProperties, "sortItems", []) as AFM.SortItem[];
const sanitizedSortItems: AFM.SortItem[] = sanitizeSorts(afm, sortItems);
// reuse sorts only for Table
// This does not apply to PivotTable, it doesn't use this function at all
if (type === VisualizationTypes.TABLE && !isEmpty(sanitizedSortItems)) {
return sanitizedSortItems;
}
switch (type) {
case VisualizationTypes.TABLE:
return getDefaultTableSort(afm);
case VisualizationTypes.COLUMN:
case VisualizationTypes.LINE:
return [];
case VisualizationTypes.BAR:
return SortsHelper.getDefaultBarChartSort(
afm,
resultSpec,
canSortStackTotalValue,
enableSortingByTotalGroup,
);
case VisualizationTypes.TREEMAP:
return SortsHelper.getDefaultTreemapSort(afm, resultSpec);
case VisualizationTypes.PUSHPIN:
return getDefaultGeoPushpinSort(afm);
case VisualizationTypes.HEATMAP:
return SortsHelper.getDefaultHeatmapSort(resultSpec);
}
return [];
}
export function getBucketItemIdentifiers(referencePoint: IExtendedReferencePoint): string[] {
const buckets: IBucket[] = get(referencePoint, "buckets", []);
return buckets.reduce((localIdentifiers: string[], bucket: IBucket): string[] => {
const items: IBucketItem[] = get(bucket, "items", []);
return localIdentifiers.concat(items.map((item: IBucketItem): string => item.localIdentifier));
}, []);
}
export function getSortIdentifiers(item: AFM.SortItem): string[] {
if (AFM.isMeasureSortItem(item)) {
return get(item, "measureSortItem.locators", []).map((locator: AFM.LocatorItem) => {
if (get(locator, "measureLocatorItem")) {
return get(locator, "measureLocatorItem.measureIdentifier");
} else {
return get(locator, "attributeLocatorItem.attributeIdentifier");
}
});
}
if (AFM.isAttributeSortItem(item)) {
const attribute = get(item, "attributeSortItem.attributeIdentifier");
if (attribute) {
return [attribute];
}
}
return [];
}
function isSortItemValid(item: AFM.SortItem, identifiers: string[]) {
const sortIdentifiers = getSortIdentifiers(item);
return every(sortIdentifiers, id => includes(identifiers, id));
}
export function removeSort(referencePoint: Readonly<IExtendedReferencePoint>) {
if (referencePoint.properties) {
const properties = omitBy(
{
...referencePoint.properties,
sortItems: null,
},
isNil,
);
return {
...referencePoint,
properties,
};
}
return referencePoint;
}
export function removeInvalidSort(referencePoint: Readonly<IExtendedReferencePoint>) {
if (referencePoint.properties) {
const identifiers = getBucketItemIdentifiers(referencePoint);
let sortItems = referencePoint.properties.sortItems || [];
sortItems = sortItems.filter((item: AFM.SortItem) => {
return isSortItemValid(item, identifiers);
});
return {
...referencePoint,
properties: {
...referencePoint.properties,
sortItems,
},
};
}
return referencePoint;
}
export function setSortItems(referencePoint: IExtendedReferencePoint) {
const buckets = referencePoint.buckets;
const sortItems = get(referencePoint, ["properties", "sortItems"], []);
if (sortItems.length > 0) {
return referencePoint;
}
const firstMeasure = getFirstValidMeasure(buckets);
const firstAttribute = getFirstAttribute(buckets);
if (firstMeasure !== null && firstAttribute == null) {
set(
referencePoint,
["properties", "sortItems"],
getMeasureSortItems(firstMeasure.localIdentifier, SORT_DIR_DESC),
);
} else if (firstAttribute !== null) {
set(
referencePoint,
["properties", "sortItems"],
[SortsHelper.getAttributeSortItem(firstAttribute.localIdentifier, SORT_DIR_ASC)],
);
}
return referencePoint;
}