UNPKG

@gooddata/react-components

Version:

GoodData.UI - A powerful JavaScript library for building analytical applications

234 lines (213 loc) • 9.31 kB
// (C) 2020 GoodData Corporation import includes = require("lodash/includes"); import { VisualizationObject } from "@gooddata/typings"; import { ColumnWidthItem, IMeasureColumnWidthItem, isAttributeColumnWidthItem, isMeasureLocatorItem, isMeasureColumnWidthItem, isAllMeasureColumnWidthItem, isWeakMeasureColumnWidthItem, IWeakMeasureColumnWidthItem, isAbsoluteColumnWidth, } from "../../../../interfaces/PivotTable"; import { IAttributeFilter, IBucketFilter, isAttributeFilter, IBucketItem, } from "../../../interfaces/Visualization"; import { getMeasures, getRows, getColumns } from "./sortItemsHelpers"; const isMeasureWidthItemMatchedByFilter = ( widthItem: IMeasureColumnWidthItem, filter: IAttributeFilter, ): boolean => filter.selectedElements.some(selectedElement => widthItem.measureColumnWidthItem.locators.some( locator => !isMeasureLocatorItem(locator) && locator.attributeLocatorItem.element === selectedElement.uri, ), ); const matchesMeasureColumnWidthItemFilters = ( widthItem: IMeasureColumnWidthItem, filters: IBucketFilter[], ): boolean => filters.reduce((isMatching, filter) => { if (isAttributeFilter(filter)) { const shouldBeMatched = !filter.isInverted; return isMatching && shouldBeMatched === isMeasureWidthItemMatchedByFilter(widthItem, filter); } return isMatching; }, true); const matchesWidthItemFilters = (widthItem: ColumnWidthItem, filters: IBucketFilter[]): boolean => { if (isMeasureColumnWidthItem(widthItem)) { return matchesMeasureColumnWidthItemFilters(widthItem, filters); } return true; }; const containsMeasureLocator = (widthItem: IMeasureColumnWidthItem): boolean => widthItem.measureColumnWidthItem.locators.some(locator => isMeasureLocatorItem(locator)); const widthItemLocatorsHaveProperLength = ( widthItem: IMeasureColumnWidthItem, measuresCount: number, columnAttributesCount: number, ): boolean => { const widthItemLocatorsLength = widthItem.measureColumnWidthItem.locators.length; const hasWidthItemLocators = widthItemLocatorsLength > 0; const hasMeasureLocators = measuresCount > 0 && containsMeasureLocator(widthItem); const hasNotMeasureLocators = measuresCount === 0 && !containsMeasureLocator(widthItem); const widthItemLocatorsMatchesColumnAttributesLength = widthItemLocatorsLength === columnAttributesCount + 1; const widthItemLocatorsHasLengthAsColumnAttributesLength = widthItemLocatorsLength === columnAttributesCount; const locatorsMatchesLength = hasMeasureLocators && widthItemLocatorsMatchesColumnAttributesLength; const locatorsAreEmpty = hasNotMeasureLocators && widthItemLocatorsHasLengthAsColumnAttributesLength; return hasWidthItemLocators && (locatorsMatchesLength || locatorsAreEmpty); }; function removeInvalidLocators( columnWidth: IMeasureColumnWidthItem, measureLocalIdentifiers: string[], columnAttributeLocalIdentifiers: string[], ) { return columnWidth.measureColumnWidthItem.locators.filter(locator => { // filter out invalid measure locators if (isMeasureLocatorItem(locator)) { return includes(measureLocalIdentifiers, locator.measureLocatorItem.measureIdentifier); } // filter out invalid column attribute locators return includes(columnAttributeLocalIdentifiers, locator.attributeLocatorItem.attributeIdentifier); }); } function transformToWeakMeasureColumnWidthItem( columnWidth: IMeasureColumnWidthItem, ): IWeakMeasureColumnWidthItem { if ( isAbsoluteColumnWidth(columnWidth.measureColumnWidthItem.width) && columnWidth.measureColumnWidthItem.locators.length === 1 && isMeasureLocatorItem(columnWidth.measureColumnWidthItem.locators[0]) ) { return { measureColumnWidthItem: { width: columnWidth.measureColumnWidthItem.width, locator: columnWidth.measureColumnWidthItem.locators.filter(isMeasureLocatorItem)[0], }, }; } } // removes attribute widthItems with invalid identifiers // removes measure widthItems with invalid identifiers and invalid number of locators function adaptWidthItemsToPivotTable( originalColumnWidths: ColumnWidthItem[], measureLocalIdentifiers: string[], rowAttributeLocalIdentifiers: string[], columnAttributeLocalIdentifiers: string[], filters: IBucketFilter[], firstColumnAttributeAdded: boolean, ): ColumnWidthItem[] { if (!originalColumnWidths) { return originalColumnWidths; } const attributeLocalIdentifiers = [...rowAttributeLocalIdentifiers, ...columnAttributeLocalIdentifiers]; return originalColumnWidths.reduce((columnWidths: ColumnWidthItem[], columnWidth: ColumnWidthItem) => { if (isMeasureColumnWidthItem(columnWidth)) { const filteredMeasureColumnWidthItem: IMeasureColumnWidthItem = { measureColumnWidthItem: { ...columnWidth.measureColumnWidthItem, locators: removeInvalidLocators( columnWidth, measureLocalIdentifiers, columnAttributeLocalIdentifiers, ), }, }; if (firstColumnAttributeAdded) { const transformedWeakMeasureWidthItem = transformToWeakMeasureColumnWidthItem(columnWidth); if (transformedWeakMeasureWidthItem) { return [...columnWidths, transformedWeakMeasureWidthItem]; } } if ( matchesWidthItemFilters(filteredMeasureColumnWidthItem, filters) && widthItemLocatorsHaveProperLength( filteredMeasureColumnWidthItem, measureLocalIdentifiers.length, columnAttributeLocalIdentifiers.length, ) ) { return [...columnWidths, filteredMeasureColumnWidthItem]; } } else if (isAttributeColumnWidthItem(columnWidth)) { if ( includes(attributeLocalIdentifiers, columnWidth.attributeColumnWidthItem.attributeIdentifier) ) { return [...columnWidths, columnWidth]; } } else if ( (isAllMeasureColumnWidthItem(columnWidth) || isWeakMeasureColumnWidthItem(columnWidth)) && measureLocalIdentifiers.length > 0 ) { return [...columnWidths, columnWidth]; } return columnWidths; }, []); } export function adaptReferencePointWidthItemsToPivotTable( originalColumnWidths: ColumnWidthItem[], measures: IBucketItem[], rowAttributes: IBucketItem[], columnAttributes: IBucketItem[], previousRowAttributes: IBucketItem[], previousColumnAttributes: IBucketItem[], filters: IBucketFilter[], ): ColumnWidthItem[] { const measureLocalIdentifiers = measures.map(measure => measure.localIdentifier); const rowAttributeLocalIdentifiers = rowAttributes.map(rowAttribute => rowAttribute.localIdentifier); const columnAttributeLocalIdentifiers = columnAttributes.map( columnAttribute => columnAttribute.localIdentifier, ); const previousRowAttributeLocalIdentifiers = previousRowAttributes.map( rowAttribute => rowAttribute.localIdentifier, ); const previousColumnAttributeLocalIdentifiers = previousColumnAttributes.map( columnAttribute => columnAttribute.localIdentifier, ); const filteredRowAttributeLocalIdentifiers = rowAttributeLocalIdentifiers.filter( rowAttributeLocalIdentifier => !previousColumnAttributeLocalIdentifiers.includes(rowAttributeLocalIdentifier), ); const filteredColumnAttributeLocalIdentifiers = columnAttributeLocalIdentifiers.filter( columnAttributeLocalIdentifier => !previousRowAttributeLocalIdentifiers.includes(columnAttributeLocalIdentifier), ); const firstColumnAttributeAdded = previousColumnAttributes.length === 0 && columnAttributes.length === 1; return adaptWidthItemsToPivotTable( originalColumnWidths, measureLocalIdentifiers, filteredRowAttributeLocalIdentifiers, filteredColumnAttributeLocalIdentifiers, filters, firstColumnAttributeAdded, ); } export function adaptMdObjectWidthItemsToPivotTable( originalColumnWidths: ColumnWidthItem[], buckets: VisualizationObject.IBucket[], ): ColumnWidthItem[] { const measureLocalIdentifiers = getMeasures(buckets).map(measure => measure.measure.localIdentifier); const rowAttributeLocalIdentifiers = getRows(buckets).map( rowAttribute => rowAttribute.visualizationAttribute.localIdentifier, ); const columnAttributeLocalIdentifiers = getColumns(buckets).map( columnAttribute => columnAttribute.visualizationAttribute.localIdentifier, ); return adaptWidthItemsToPivotTable( originalColumnWidths, measureLocalIdentifiers, rowAttributeLocalIdentifiers, columnAttributeLocalIdentifiers, [], false, ); }