UNPKG

@finos/legend-data-cube

Version:
451 lines (405 loc) 13.9 kB
/** * Copyright (c) 2020-present, Goldman Sachs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { TailwindCSSPalette } from '@finos/legend-art'; import { DATE_FORMAT, PRIMITIVE_TYPE, type V1_AppliedFunction, } from '@finos/legend-graph'; import { guaranteeNonNullable, IllegalStateError, UnsupportedOperationError, formatDate, } from '@finos/legend-shared'; import type { DataCubeQueryFilterOperation } from './filter/DataCubeQueryFilterOperation.js'; import type { DataCubeQueryAggregateOperation } from './aggregation/DataCubeQueryAggregateOperation.js'; export enum DataCubeFunction { // relation EXTEND = 'meta::pure::functions::relation::extend', FILTER = 'meta::pure::functions::relation::filter', GROUP_BY = 'meta::pure::functions::relation::groupBy', LIMIT = 'meta::pure::functions::relation::limit', PIVOT = 'meta::pure::functions::relation::pivot', SELECT = 'meta::pure::functions::relation::select', SLICE = 'meta::pure::functions::relation::slice', SORT = 'meta::pure::functions::relation::sort', OVER = 'meta::pure::functions::relation::over', // generic CAST = 'meta::pure::functions::lang::cast', FROM = 'meta::pure::mapping::from', // sort ASCENDING = 'meta::pure::functions::relation::ascending', DESCENDING = 'meta::pure::functions::relation::descending', ABS = 'meta::pure::functions::math::abs', // filter AND = 'meta::pure::functions::boolean::and', OR = 'meta::pure::functions::boolean::or', NOT = 'meta::pure::functions::boolean::not', TO_LOWERCASE = 'meta::pure::functions::string::toLower', CONTAINS = 'meta::pure::functions::string::contains', ENDS_WITH = 'meta::pure::functions::string::endsWith', EQUAL = 'meta::pure::functions::boolean::equal', GREATER_THAN = 'meta::pure::functions::boolean::greaterThan', GREATER_THAN_OR_EQUAL = 'meta::pure::functions::boolean::greaterThanEqual', IN = 'meta::pure::functions::collection::in', IS_EMPTY = 'meta::pure::functions::collection::isEmpty', LESS_THAN = 'meta::pure::functions::boolean::lessThan', LESS_THAN_OR_EQUAL = 'meta::pure::functions::boolean::lessThanEqual', STARTS_WITH = 'meta::pure::functions::string::startsWith', // aggregate AVERAGE = 'meta::pure::functions::math::average', COUNT = 'meta::pure::functions::collection::count', DISTINCT = 'meta::pure::functions::collection::distinct', FIRST = 'meta::pure::functions::collection::first', JOIN_STRINGS = 'meta::pure::functions::string::joinStrings', LAST = 'meta::pure::functions::collection::last', MAX = 'meta::pure::functions::collection::max', MIN = 'meta::pure::functions::collection::min', SUM = 'meta::pure::functions::math::sum', STANDARD_DEVIATION_POPULATION = 'meta::pure::functions::math::stdDevPopulation', STANDARD_DEVIATION_SAMPLE = 'meta::pure::functions::math::stdDevSample', UNIQUE_VALUE_ONLY = 'meta::pure::functions::collection::uniqueValueOnly', VARIANCE_POPULATION = 'meta::pure::functions::math::variancePopulation', VARIANCE_SAMPLE = 'meta::pure::functions::math::varianceSample', // PERCENTILE = 'meta::pure::functions::math::percentile', } export type DataCubeQueryFunctionMap = { leafExtend?: V1_AppliedFunction[] | undefined; filter?: V1_AppliedFunction | undefined; pivotSort?: V1_AppliedFunction | undefined; pivot?: V1_AppliedFunction | undefined; pivotCast?: V1_AppliedFunction | undefined; groupBy?: V1_AppliedFunction | undefined; groupBySort?: V1_AppliedFunction | undefined; groupExtend?: V1_AppliedFunction[] | undefined; select?: V1_AppliedFunction | undefined; sort?: V1_AppliedFunction | undefined; limit?: V1_AppliedFunction | undefined; }; export enum DataCubeNumberScale { BASIS_POINT = 'Basis Points (bp)', PERCENT = 'Percent (%)', THOUSANDS = 'Thousands (k)', MILLIONS = 'Millions (m)', BILLIONS = 'Billions (b)', TRILLIONS = 'Trillions (t)', AUTO = 'Auto (k/m/b/t)', } export enum DataCubeFont { // sans-serif ARIAL = 'Arial', ROBOTO = 'Roboto', ROBOTO_CONDENSED = 'Roboto Condensed', // serif TIMES_NEW_ROMAN = 'Times New Roman', GEORGIA = 'Georgia', ROBOTO_SERIF = 'Roboto Serif', // monospace JERBRAINS_MONO = 'Jetbrains Mono', ROBOTO_MONO = 'Roboto Mono', UBUNTU_MONO = 'Ubuntu Mono', } export enum DataCubeFontTextAlignment { CENTER = 'center', LEFT = 'left', RIGHT = 'right', } export enum DataCubeFontCase { LOWERCASE = 'lowercase', UPPERCASE = 'uppercase', CAPITALIZE = 'capitalize', } export enum DataCubeFontFormatUnderlineVariant { SOLID = 'solid', DASHED = 'dashed', DOTTED = 'dotted', DOUBLE = 'double', WAVY = 'wavy', } export enum DataCubeColumnKind { MEASURE = 'Measure', DIMENSION = 'Dimension', } export enum DataCubeOperationAdvancedValueType { COLUMN = 'COLUMN', VOID = 'VOID', // PARAMETER } export type DataCubeOperationValue = { value?: unknown; type: string; }; export enum DataCubeQueryAggregateOperator { SUM = 'sum', AVERAGE = 'avg', COUNT = 'count', MIN = 'min', MAX = 'max', UNIQUE = 'uniq', FIRST = 'first', LAST = 'last', // MEDIAN = 'median', VARIANCE_POPULATION = 'var', VARIANCE_SAMPLE = 'var_sample', STANDARD_DEVIATION_POPULATION = 'std', STANDARD_DEVIATION_SAMPLE = 'std_sample', // STANDARD_ERROR = 'stderr', // NULL = 'null', // ssq // countvalid // countnull // uniqunstrict // minmagnitude // maxmagnitude // commonprefix // commonprefixunstrict JOIN_STRINGS = 'strjoin', // strjoinuniq // splitjoin // daterange // wavg // wstderr // wsum // custom } export enum DataCubeQueryClientSideAggregateOperator { SUM = 'sum', AVERAGE = 'avg', MEDIAN = 'median', COUNT = 'count', MIN = 'min', MAX = 'max', VARIANCE_POPULATION = 'var', VARIANCE_SAMPLE = 'var_sample', STANDARD_DEVIATION_POPULATION = 'std', STANDARD_DEVIATION_SAMPLE = 'std_sample', } export enum DataCubeQueryFilterOperator { LESS_THAN = '<', LESS_THAN_OR_EQUAL = '<=', EQUAL = '=', NOT_EQUAL = '!=', GREATER_THAN = '>', GREATER_THAN_OR_EQUAL = '>=', IN = 'in', NOT_IN = 'not in', IS_NULL = 'is null', IS_NOT_NULL = 'is not null', // string ONLY EQUAL_CASE_INSENSITIVE = '= (case-insensitive)', NOT_EQUAL_CASE_INSENSITIVE = '!= (case-insensitive)', IN_CASE_INSENSITIVE = 'in (case-insensitive)', NOT_IN_CASE_INSENSITIVE = 'not in (case-insensitive)', CONTAIN = 'contains', CONTAIN_CASE_INSENSITIVE = 'contains (case-insensitive)', NOT_CONTAIN = 'does not contain', START_WITH = 'starts with', START_WITH_CASE_INSENSITIVE = 'starts with (case-insensitive)', NOT_START_WITH = 'does not start with', END_WITH = 'ends with', END_WITH_CASE_INSENSITIVE = 'ends with (case-insensitive)', NOT_END_WITH = 'does not end with', // column LESS_THAN_COLUMN = '< value in column', LESS_THAN_OR_EQUAL_COLUMN = '<= value in column', EQUAL_COLUMN = '= value in column', EQUAL_CASE_INSENSITIVE_COLUMN = '= (case-insensitive) value in column', NOT_EQUAL_COLUMN = '!= value in column', NOT_EQUAL_CASE_INSENSITIVE_COLUMN = '!= (case-insensitive) value in column', GREATER_THAN_COLUMN = '> value in column', GREATER_THAN_OR_EQUAL_COLUMN = '>= value in column', // TODO?: having, having in aggregate, between } export enum DataCubeQueryFilterGroupOperator { AND = 'and', OR = 'or', } export enum DataCubeQuerySortDirection { ASCENDING = 'Ascending', DESCENDING = 'Descending', } export enum DataCubeColumnPinPlacement { LEFT = 'Left', RIGHT = 'Right', } export enum DataCubeColumnDataType { NUMBER = 'Numeric', TEXT = 'Text', DATE = 'Date', TIME = 'Time', } export enum DataCubeGridMode { STANDARD = 'Standard', MULTIDIMENSIONAL = 'Multidimensional', } export enum DataCubeClientModelOption { ROW_DATA = 'rowData', COLUMN_DEFS = 'columnDefs', LOADING = 'loading', } export enum DataCubeTitleBarMenuItems { VIEW_SOURCE = 'View Source', RESET_TO_LATEST_SAVE = 'Reset to Latest Save', UPDATE_INFO = 'Update Info...', DELETE_DATACUBE = 'Delete DataCube...', SEE_DOCUMENTATION = 'See Documentation', ABOUT = 'About', UNDO = 'Undo', REDO = 'Redo', SETTINGS = 'Settings...', } export enum DataCubeOpenEditorSource { STATUS_BAR = 'Status Bar', GRID_MENU = 'Grid Menu', } export const PIVOT_COLUMN_NAME_VALUE_SEPARATOR = '__|__'; export const TREE_COLUMN_VALUE_SEPARATOR = '__/__'; export const DEFAULT_LAMBDA_VARIABLE_NAME = 'x'; export const DEFAULT_REPORT_NAME = 'New Report'; export const DEFAULT_TREE_COLUMN_SORT_DIRECTION = DataCubeQuerySortDirection.ASCENDING; export const DEFAULT_PIVOT_STATISTIC_COLUMN_NAME = 'Total'; export const DEFAULT_PIVOT_COLUMN_SORT_DIRECTION = DataCubeQuerySortDirection.ASCENDING; export const DEFAULT_ROOT_AGGREGATION_COLUMN_VALUE = '[ROOT]'; export const DEFAULT_URL_LABEL_QUERY_PARAM = 'dataCube.linkLabel'; export const DEFAULT_MISSING_VALUE_DISPLAY_TEXT = ''; export const DEFAULT_GRID_LINE_COLOR = TailwindCSSPalette.neutral[300]; export const DEFAULT_ROW_HIGHLIGHT_BACKGROUND_COLOR = '#d7e0eb'; export const DEFAULT_COLUMN_WIDTH = 300; export const DEFAULT_COLUMN_MIN_WIDTH = 50; export const DEFAULT_COLUMN_MAX_WIDTH = undefined; export const DEFAULT_GRID_MODE = DataCubeGridMode.STANDARD; export const DEFAULT_FONT_FAMILY = DataCubeFont.ROBOTO; export const DEFAULT_FONT_SIZE = 11; export const DEFAULT_FONT_BOLD = false; export const DEFAULT_FONT_ITALIC = false; export const DEFAULT_FONT_CASE = undefined; export const DEFAULT_FONT_UNDERLINED = undefined; export const DEFAULT_FONT_STRIKETHROUGH = false; export const DEFAULT_TEXT_ALIGN = DataCubeFontTextAlignment.LEFT; export const DEFAULT_FOREGROUND_COLOR = TailwindCSSPalette.black; export const DEFAULT_BACKGROUND_COLOR = TailwindCSSPalette.transparent; export const DEFAULT_ROW_BACKGROUND_COLOR = TailwindCSSPalette.white; export const DEFAULT_NEGATIVE_FOREGROUND_COLOR = TailwindCSSPalette.red[500]; export const DEFAULT_ZERO_FOREGROUND_COLOR = TailwindCSSPalette.neutral[400]; export const DEFAULT_ERROR_FOREGROUND_COLOR = TailwindCSSPalette.blue[600]; // settings export const TAB_SIZE = 2; export const DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"; export const TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH = 3; export const TYPEAHEAD_SEARCH_LIMIT = 10; export const EMPTY_VALUE_PLACEHOLDER = '(None)'; // --------------------------------- UTILITIES --------------------------------- export function _defaultPrimitiveTypeValue(type: string): unknown { switch (type) { case PRIMITIVE_TYPE.STRING: return ''; case PRIMITIVE_TYPE.BOOLEAN: return false; case PRIMITIVE_TYPE.BYTE: return btoa(''); case PRIMITIVE_TYPE.NUMBER: case PRIMITIVE_TYPE.DECIMAL: case PRIMITIVE_TYPE.FLOAT: case PRIMITIVE_TYPE.INTEGER: case PRIMITIVE_TYPE.BINARY: return 0; case PRIMITIVE_TYPE.DATE: case PRIMITIVE_TYPE.STRICTDATE: return formatDate(new Date(Date.now()), DATE_FORMAT); case PRIMITIVE_TYPE.DATETIME: return formatDate(new Date(Date.now()), DATE_TIME_FORMAT); default: throw new UnsupportedOperationError( `Can't generate value for type '${type}'`, ); } } export function getFilterOperation( operator: string, operators: DataCubeQueryFilterOperation[], ) { return guaranteeNonNullable( operators.find((op) => op.operator === operator), `Can't find filter operation '${operator}'`, ); } export function getAggregateOperation( operator: string, aggregateOperations: DataCubeQueryAggregateOperation[], ) { return guaranteeNonNullable( aggregateOperations.find((op) => op.operator === operator), `Can't find aggregate operation '${operator}'`, ); } export function getDataType(type: string): DataCubeColumnDataType { switch (type) { case PRIMITIVE_TYPE.NUMBER: case PRIMITIVE_TYPE.INTEGER: case PRIMITIVE_TYPE.DECIMAL: case PRIMITIVE_TYPE.FLOAT: return DataCubeColumnDataType.NUMBER; case PRIMITIVE_TYPE.DATE: case PRIMITIVE_TYPE.STRICTDATE: return DataCubeColumnDataType.DATE; case PRIMITIVE_TYPE.DATETIME: return DataCubeColumnDataType.TIME; case PRIMITIVE_TYPE.STRING: default: return DataCubeColumnDataType.TEXT; } } export function ofDataType( type: string, dataTypes: DataCubeColumnDataType[], ): boolean { return dataTypes.includes(getDataType(type)); } export function isDimensionalGridMode(gridMode: DataCubeGridMode) { return gridMode === DataCubeGridMode.MULTIDIMENSIONAL; } export function isPrimitiveType(type: string) { return ( [ PRIMITIVE_TYPE.NUMBER, PRIMITIVE_TYPE.INTEGER, PRIMITIVE_TYPE.DECIMAL, PRIMITIVE_TYPE.FLOAT, PRIMITIVE_TYPE.DATE, PRIMITIVE_TYPE.STRICTDATE, PRIMITIVE_TYPE.DATETIME, PRIMITIVE_TYPE.STRING, PRIMITIVE_TYPE.BOOLEAN, ] as string[] ).includes(type); } export function isPivotResultColumnName(columnName: string) { return columnName.includes(PIVOT_COLUMN_NAME_VALUE_SEPARATOR); } export function getPivotResultColumnBaseColumnName(columnName: string) { if (!isPivotResultColumnName(columnName)) { throw new IllegalStateError( `Column '${columnName}' is not a pivot result column`, ); } return columnName.substring( columnName.lastIndexOf(PIVOT_COLUMN_NAME_VALUE_SEPARATOR) + PIVOT_COLUMN_NAME_VALUE_SEPARATOR.length, ); }