From 398905e50dac43bafba5cc2ffe423beecbce8708 Mon Sep 17 00:00:00 2001 From: Xun Li Date: Thu, 1 Feb 2024 14:12:07 -0700 Subject: [PATCH] addColumn action; ordinal scale on numeric field --- src/actions/src/action-types.ts | 1 + src/actions/src/vis-state-actions.ts | 29 +++++++++++++++++- src/constants/src/default-settings.ts | 2 +- src/layers/src/index.ts | 2 +- src/reducers/src/vis-state-updaters.ts | 36 +++++++++++++++++++++++ src/reducers/src/vis-state.ts | 2 ++ src/utils/src/arrow-data-container.ts | 11 +++++++ src/utils/src/data-container-interface.ts | 10 +++++++ 8 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/actions/src/action-types.ts b/src/actions/src/action-types.ts index 22d45a8bed..90104242dd 100644 --- a/src/actions/src/action-types.ts +++ b/src/actions/src/action-types.ts @@ -97,6 +97,7 @@ export const ActionTypes = { SORT_TABLE_COLUMN: `${ACTION_PREFIX}SORT_TABLE_COLUMN`, PIN_TABLE_COLUMN: `${ACTION_PREFIX}PIN_TABLE_COLUMN`, COPY_TABLE_COLUMN: `${ACTION_PREFIX}COPY_TABLE_COLUMN`, + ADD_TABLE_COLUMN: `${ACTION_PREFIX}ADD_TABLE_COLUMN`, SET_COLUMN_DISPLAY_FORMAT: `${ACTION_PREFIX}SET_COLUMN_DISPLAY_FORMAT`, NEXT_FILE_BATCH: `${ACTION_PREFIX}NEXT_FILE_BATCH`, PROCESS_FILE_CONTENT: `${ACTION_PREFIX}PROCESS_FILE_CONTENT`, diff --git a/src/actions/src/vis-state-actions.ts b/src/actions/src/vis-state-actions.ts index 14d175a8a2..69f7d67d00 100644 --- a/src/actions/src/vis-state-actions.ts +++ b/src/actions/src/vis-state-actions.ts @@ -20,7 +20,8 @@ import { Filter, ParsedConfig, ParsedLayer, - EffectPropsPartial + EffectPropsPartial, + Field } from '@kepler.gl/types'; // TODO - import LoaderObject type from @loaders.gl/core when supported // TODO - import LoadOptions type from @loaders.gl/core when supported @@ -720,6 +721,32 @@ export function copyTableColumn( }; } +export type AddTableColumnUpdaterAction = { + dataId: string; + field: Field; + values: unknown[]; +}; +/** + * Add new column to dataset, for table display + * @param dataId + * @param field + * @param values + * @returns action + * @public + */ +export function addTableColumn( + dataId: string, + field: Field, + values: unknown[] +): Merge { + return { + type: ActionTypes.ADD_TABLE_COLUMN, + dataId, + field, + values + }; +} + export type SetColumnDisplayFormatUpdaterAction = { dataId: string; formats: { diff --git a/src/constants/src/default-settings.ts b/src/constants/src/default-settings.ts index 3d1c206dd9..a34275db5e 100644 --- a/src/constants/src/default-settings.ts +++ b/src/constants/src/default-settings.ts @@ -591,7 +591,7 @@ export const AGGREGATION_TYPE_OPTIONS: {id: string; label: string}[] = Object.en })); export const linearFieldScaleFunctions = { - [CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom], + [CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.custom, SCALE_TYPES.ordinal], [CHANNEL_SCALES.radius]: [SCALE_TYPES.sqrt], [CHANNEL_SCALES.size]: [SCALE_TYPES.linear, SCALE_TYPES.sqrt, SCALE_TYPES.log] }; diff --git a/src/layers/src/index.ts b/src/layers/src/index.ts index 9cabb9f49f..aab45ea5c0 100644 --- a/src/layers/src/index.ts +++ b/src/layers/src/index.ts @@ -15,7 +15,7 @@ import {default as GridLayer} from './grid-layer/grid-layer'; export {pointToPolygonGeo} from './grid-layer/grid-utils'; import {default as HexagonLayer} from './hexagon-layer/hexagon-layer'; import {default as GeojsonLayer} from './geojson-layer/geojson-layer'; -export {defaultElevation, defaultLineWidth, defaultRadius} from './geojson-layer/geojson-layer'; +export {default as GeojsonLayer, defaultElevation, defaultLineWidth, defaultRadius} from './geojson-layer/geojson-layer'; import {default as ClusterLayer} from './cluster-layer/cluster-layer'; import {default as IconLayer} from './icon-layer/icon-layer'; import {default as HeatmapLayer} from './heatmap-layer/heatmap-layer'; diff --git a/src/reducers/src/vis-state-updaters.ts b/src/reducers/src/vis-state-updaters.ts index 5ce3d6ba7f..adba66a1b7 100644 --- a/src/reducers/src/vis-state-updaters.ts +++ b/src/reducers/src/vis-state-updaters.ts @@ -2774,6 +2774,42 @@ export function copyTableColumnUpdater( return state; } +/** + * Add new field to table with values, if field already exists, update the column values + * @memberof visStateUpdaters + * @public + */ +export function addTableColumnUpdater( + state: VisState, + {dataId, field, values}: VisStateActions.AddTableColumnUpdaterAction +): VisState { + const dataset = state.datasets[dataId]; + if (!dataset) { + return state; + } + const dataContainer = dataset.dataContainer; + let newDataset = dataset; + + // check if field already exists + const fieldIdx = dataset.fields.findIndex(f => f.name === field.name); + if (fieldIdx >= 0) { + // update the column values + if (dataContainer && dataContainer.updateColumn) { + dataContainer.updateColumn(fieldIdx, values); + } + newDataset = copyTableAndUpdate(dataset); + } else { + // add new column with values + const newFields = [...dataset.fields, field]; + if (dataContainer && dataContainer.addColumn) { + dataContainer.addColumn(values, field); + } + newDataset = copyTableAndUpdate(dataset, { fields: newFields }); + } + + return pick_('datasets')(merge_({[dataId]: newDataset}))(state); +} + /** * Set display format from columns from user selection * @memberof visStateUpdaters diff --git a/src/reducers/src/vis-state.ts b/src/reducers/src/vis-state.ts index bb46c8cd5a..b8885cad04 100644 --- a/src/reducers/src/vis-state.ts +++ b/src/reducers/src/vis-state.ts @@ -129,6 +129,8 @@ const actionHandler = { [ActionTypes.COPY_TABLE_COLUMN]: visStateUpdaters.copyTableColumnUpdater, + [ActionTypes.ADD_TABLE_COLUMN]: visStateUpdaters.addTableColumnUpdater, + [ActionTypes.SET_COLUMN_DISPLAY_FORMAT]: visStateUpdaters.setColumnDisplayFormatUpdater, [ActionTypes.NEXT_FILE_BATCH]: visStateUpdaters.nextFileBatchUpdater, diff --git a/src/utils/src/arrow-data-container.ts b/src/utils/src/arrow-data-container.ts index c7a5d73a9e..3f0b1f547e 100644 --- a/src/utils/src/arrow-data-container.ts +++ b/src/utils/src/arrow-data-container.ts @@ -75,6 +75,17 @@ export class ArrowDataContainer implements DataContainerInterface { // this._colData = this._cols.map(c => c.toArray()); } + addColumn(values: unknown[], field: Field) { + const newColumn = arrow.vectorFromArray(values); + this._cols.push(newColumn); + this._numColumns++; + this._fields.push(field); + } + + updateColumn(columnIndex: number, values: unknown[]) { + this._cols[columnIndex] = arrow.vectorFromArray(values); + } + numChunks(): number { return this._numChunks; } diff --git a/src/utils/src/data-container-interface.ts b/src/utils/src/data-container-interface.ts index 5e544df2a5..2e09caba8e 100644 --- a/src/utils/src/data-container-interface.ts +++ b/src/utils/src/data-container-interface.ts @@ -18,6 +18,16 @@ export interface DataContainerInterface { */ update?(updateData: any[]): void; + /** + * Adds a new column to the data container. + */ + addColumn?(columnValues: unknown[], field: Field): void; + + /** + * Update the values of a column + */ + updateColumn?(columnIndex: number, columnValues: unknown[]): void; + /** * Returns the number of rows in the data container. * @returns Number of rows in the data container.