Skip to content

Commit

Permalink
[chore] Split out column mode config into separate component
Browse files Browse the repository at this point in the history
Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com>
  • Loading branch information
igorDykhta committed Sep 23, 2024
1 parent add6192 commit b4cec94
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 73 deletions.
6 changes: 5 additions & 1 deletion src/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {
LayerColorRangeSelectorFactory,
ArcLayerColorSelectorFactory
} from './side-panel/layer-panel/layer-color-selector';
import LayerColumnModeConfigFactory from './side-panel/layer-panel/layer-column-mode-config';
import {
default as LayerColumnModeConfigFactory,
ColumnModeConfigFactory
} from './side-panel/layer-panel/layer-column-mode-config';
import {appInjector} from './container';

// Components
Expand Down Expand Up @@ -427,6 +430,7 @@ export {
ColorSelectorFactory,
LayerColorSelectorFactory,
LayerColumnModeConfigFactory,
ColumnModeConfigFactory,
LayerColorRangeSelectorFactory,
ArcLayerColorSelectorFactory
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import React, {useCallback, useMemo} from 'react';
import {LayerBaseConfig} from '@kepler.gl/layers';
import {
FieldPair,
Field,
ColumnPairs,
LayerColumns,
ColumnLabels,
Expand All @@ -21,7 +20,7 @@ import {SidePanelSection} from '../../common/styled-components';
export type LayerColumnConfigProps<FieldOption extends MinimalField> = {
columns: LayerColumns;
fields: FieldOption[];
assignColumnPairs: (key: string, pair: string) => LayerColumns;
assignColumnPairs: (key: string, pair: FieldPair) => LayerColumns;
assignColumn: (key: string, field: FieldOption) => LayerColumns;
updateLayerConfig: (newConfig: Partial<LayerBaseConfig>) => void;
updateLayerType?: (newType: string) => void;
Expand Down Expand Up @@ -54,7 +53,7 @@ function getValidFieldPairsSuggestionsForColumn(
LayerColumnConfigFactory.deps = [ColumnSelectorFactory];

function LayerColumnConfigFactory(ColumnSelector: ReturnType<typeof ColumnSelectorFactory>) {
const LayerColumnConfig: React.FC<LayerColumnConfigProps<Field>> = ({
const LayerColumnConfig: React.FC<LayerColumnConfigProps<MinimalField>> = ({
columnPairs,
fieldPairs,
columns,
Expand Down
172 changes: 118 additions & 54 deletions src/components/src/side-panel/layer-panel/layer-column-mode-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ import PanelHeaderActionFactory from '../panel-header-action';
import LayerColumnConfigFactory from './layer-column-config';
import {FormattedMessage} from '@kepler.gl/localization';
import {assignColumnsByColumnMode, Layer, LayerInfoModal, LayerBaseConfig} from '@kepler.gl/layers';
import {SupportedColumnModes, FieldPair} from '@kepler.gl/types';
import {SupportedColumnMode, FieldPair, LayerColumns} from '@kepler.gl/types';

import {Help} from '../../common/icons';

LayerColumnModeConfigFactory.deps = [LayerColumnConfigFactory, PanelHeaderActionFactory];

const TopRow = styled.div`
display: flex;
justify-content: space-between;
Expand Down Expand Up @@ -78,32 +76,32 @@ const ConfigPanesContainer = styled.div`
}
`;

export type LayerColumnModeConfigProps<FieldOption extends MinimalField> = {
layer: Layer;
supportedColumnModes: SupportedColumnModes[] | null;
interface FieldOption extends MinimalField {}

export type ColumnModeConfigProps = {
supportedColumnModes: SupportedColumnMode[] | null;
selectedColumnMode?: string;
id: string;
layerConfig: LayerBaseConfig;
fields: FieldOption[];
fieldPairs?: FieldPair[];
openModal: (l: LayerInfoModal) => void;
updateLayerConfig: (config: Partial<LayerBaseConfig>) => void;
columns: LayerColumns;
renderColumnConfig: (mode: {key: string; label: string; columns: any}) => JSX.Element;
selectColumnMode: (mode: SupportedColumnMode) => void;
getHelpHandler?: (mode: SupportedColumnMode) => (() => void) | null;
};

function LayerColumnModeConfigFactory(
LayerColumnConfig: ReturnType<typeof LayerColumnConfigFactory>,
ColumnModeConfigFactory.deps = [PanelHeaderActionFactory];

export function ColumnModeConfigFactory(
PanelHeaderAction: ReturnType<typeof PanelHeaderActionFactory>
) {
const LayerColumnModeConfig: React.FC<LayerColumnModeConfigProps<any>> = ({
layer,
supportedColumnModes,
const ColumnModeConfig: React.FC<ColumnModeConfigProps> = ({
id,
layerConfig,
fields,
fieldPairs,
openModal,
updateLayerConfig
}: LayerColumnModeConfigProps<any>) => {
const {columns} = layerConfig;
supportedColumnModes,
selectedColumnMode,
columns,
renderColumnConfig,
selectColumnMode,
getHelpHandler = () => null
}: ColumnModeConfigProps) => {
const columnModes = useMemo(
() =>
supportedColumnModes
Expand All @@ -117,23 +115,11 @@ function LayerColumnModeConfigFactory(
return {key, label, columns: allColumns};
})
: Object.keys(columns).length > 0
? [{key: 'default', label: undefined, columns}]
? [{key: 'default', label: '', columns}]
: [],
[supportedColumnModes, columns]
);

const handleSelectColumnMode = useCallback(
columnMode => {
const updatedColumns = assignColumnsByColumnMode({
columns,
supportedColumnModes,
columnMode
});

updateLayerConfig({columnMode, columns: updatedColumns});
},
[updateLayerConfig, columns, supportedColumnModes]
);
return (
<>
{columnModes.length > 0 ? (
Expand All @@ -147,19 +133,11 @@ function LayerColumnModeConfigFactory(
</TopRow>
) : null}
<ConfigPanesContainer>
{columnModes.map(({key: columnMode, label, columns: cols}, i) => {
const columnPanel = (
<LayerColumnConfig
columnPairs={layer.columnPairs}
columns={cols}
assignColumnPairs={layer.assignColumnPairs.bind(layer)}
assignColumn={layer.assignColumn.bind(layer)}
columnLabels={layer.columnLabels}
fields={fields}
fieldPairs={fieldPairs}
updateLayerConfig={updateLayerConfig}
/>
);
{columnModes.map((modeConfig, i) => {
const columnPanel = renderColumnConfig(modeConfig);
const helpHandler = getHelpHandler(modeConfig);
const selectColumnModeHandler = () => selectColumnMode(modeConfig);
const {key: columnMode, label} = modeConfig;

return (
<Fragment key={columnMode}>
Expand All @@ -175,20 +153,19 @@ function LayerColumnModeConfigFactory(
<Checkbox
type="radio"
name={`layer-${id}-input-modes`}
checked={layerConfig.columnMode === columnMode}
checked={selectedColumnMode === columnMode}
id={`${id}-input-column-${columnMode}`}
label={label}
secondary
onChange={() => handleSelectColumnMode(columnMode)}
onChange={selectColumnModeHandler}
/>
</PanelHeaderContent>
{layer.layerInfoModal?.[columnMode] ? (
{helpHandler ? (
<div className="interaction-panel__header__actions">
<PanelHeaderAction
id={`${id}-help-button`}
className="layer__help-button"
tooltip={'layerConfiguration.howTo'}
onClick={() => openModal(layer.layerInfoModal?.[columnMode])}
onClick={helpHandler}
IconComponent={Help}
/>
</div>
Expand All @@ -209,6 +186,93 @@ function LayerColumnModeConfigFactory(
);
};

return ColumnModeConfig;
}

export type LayerColumnModeConfigProps = {
layer: Layer;
layerConfig: LayerBaseConfig;
supportedColumnModes: SupportedColumnMode[] | null;
id: string;
fields: FieldOption[];
fieldPairs?: FieldPair[];
openModal: (l: LayerInfoModal) => void;
updateLayerConfig: (config: Partial<LayerBaseConfig>) => void;
};

LayerColumnModeConfigFactory.deps = [LayerColumnConfigFactory, ColumnModeConfigFactory];

function LayerColumnModeConfigFactory(
LayerColumnConfig: ReturnType<typeof LayerColumnConfigFactory>,
ColumnModeConfig: ReturnType<typeof ColumnModeConfigFactory>
) {
const LayerColumnModeConfig = ({
id,
layer,
supportedColumnModes,
layerConfig,
fields,
fieldPairs,
openModal,
updateLayerConfig
}: LayerColumnModeConfigProps) => {
const {columns} = layerConfig;

const selectColumnMode = useCallback(
({key: columnMode}) => {
const updatedColumns = assignColumnsByColumnMode({
columns,
supportedColumnModes,
columnMode
});

updateLayerConfig({columnMode, columns: updatedColumns});
},
[updateLayerConfig, columns, supportedColumnModes]
);

const renderColumnConfig = useCallback(
({key: columnMode, label, columns: cols}) => (

Check warning on line 235 in src/components/src/side-panel/layer-panel/layer-column-mode-config.tsx

View workflow job for this annotation

GitHub Actions / build (18.x)

'columnMode' is defined but never used

Check warning on line 235 in src/components/src/side-panel/layer-panel/layer-column-mode-config.tsx

View workflow job for this annotation

GitHub Actions / build (18.x)

'label' is defined but never used
<LayerColumnConfig
columnPairs={layer.columnPairs}
columns={cols}
assignColumnPairs={layer.assignColumnPairs.bind(layer)}
assignColumn={
layer.assignColumn.bind(layer) as (key: string, field: FieldOption) => LayerColumns
}
columnLabels={layer.columnLabels}
fields={fields}
fieldPairs={fieldPairs}
updateLayerConfig={updateLayerConfig}
/>
),
[layer, updateLayerConfig, fieldPairs, fields]
);

const getHelpHandler = useCallback(
({key: columnMode}) => {
const modal = layer.layerInfoModal?.[columnMode];
if (modal) {
return () => openModal(modal);
}
return null;
},
[layer, openModal]
);

return (
<ColumnModeConfig
id={id}
supportedColumnModes={supportedColumnModes}
selectedColumnMode={layerConfig.columnMode}
columns={columns}
selectColumnMode={selectColumnMode}
renderColumnConfig={renderColumnConfig}
getHelpHandler={getHelpHandler}
/>
);
};

return LayerColumnModeConfig;
}

Expand Down
15 changes: 8 additions & 7 deletions src/layers/src/base-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ import {
LayerColumn,
ColumnPairs,
ColumnLabels,
SupportedColumnModes
SupportedColumnMode,
FieldPair
} from '@kepler.gl/types';
import {KeplerTable, Datasets, GpuFilter} from '@kepler.gl/table';

Expand Down Expand Up @@ -390,7 +391,7 @@ class Layer {
/**
* Returns which column modes this layer supports
*/
get supportedColumnModes(): SupportedColumnModes[] | null {
get supportedColumnModes(): SupportedColumnMode[] | null {
return null;
}

Expand Down Expand Up @@ -438,10 +439,10 @@ class Layer {
return null;
}

return this.getAllPossibleColumnParis(requiredColumns);
return this.getAllPossibleColumnPairs(requiredColumns);
}

static getAllPossibleColumnParis(requiredColumns) {
static getAllPossibleColumnPairs(requiredColumns) {
// for multiple matched field for one required column, return multiple
// combinations, e. g. if column a has 2 matched, column b has 3 matched
// 6 possible column pairs will be returned
Expand Down Expand Up @@ -571,9 +572,9 @@ class Layer {
* Assign a field pair to column config, return column config
* @param key - Column Key
* @param pair - field Pair
* @returns {object} - Column config
* @returns Column config
*/
assignColumnPairs(key: string, pair: string): LayerColumns {
assignColumnPairs(key: string, pair: FieldPair): LayerColumns {
if (!this.columnPairs || !this.columnPairs?.[key]) {
// should not end in this state
return this.config.columns;
Expand Down Expand Up @@ -931,7 +932,7 @@ class Layer {
const {columns} = this.config;
return (
columns &&
Object.values(columns).every(column => {
Object.values(columns).every((column?: LayerColumn) => {
return Boolean(column && (column.optional || (column.value && column.fieldIdx > -1)));
})
);
Expand Down
6 changes: 3 additions & 3 deletions src/layers/src/layer-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import * as arrow from 'apache-arrow';
import {Feature, BBox} from 'geojson';
import {Field, FieldPair, SupportedColumnModes, LayerColumns} from '@kepler.gl/types';
import {Field, FieldPair, SupportedColumnMode, LayerColumns} from '@kepler.gl/types';
import {DataContainerInterface} from '@kepler.gl/utils';
import {
getBinaryGeometriesFromArrow,
Expand Down Expand Up @@ -135,7 +135,7 @@ export function getHoveredObjectFromArrow(
* find requiredColumns of supported column mode based on column mode
*/
export function getColumnModeRequiredColumns(
supportedColumnModes: SupportedColumnModes[] | null,
supportedColumnModes: SupportedColumnMode[] | null,
columnMode?: string
): string[] | undefined {
return supportedColumnModes?.find(({key}) => key === columnMode)?.requiredColumns;
Expand All @@ -150,7 +150,7 @@ export function assignColumnsByColumnMode({
columnMode
}: {
columns: LayerColumns;
supportedColumnModes: SupportedColumnModes[] | null;
supportedColumnModes: SupportedColumnMode[] | null;
columnMode: string | undefined;
}): LayerColumns {
const requiredColumns = getColumnModeRequiredColumns(supportedColumnModes, columnMode);
Expand Down
3 changes: 2 additions & 1 deletion src/types/layers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ export type EnhancedFieldPair = {
pair: FieldPair['pair'];
};

export type SupportedColumnModes = {
export type SupportedColumnMode = {
key: string;
label: string;
requiredColumns?: string[];
optionalColumns?: string[];
hasHelp?: boolean;
};

export type LayerColorConfig = {
Expand Down
8 changes: 4 additions & 4 deletions test/browser/layer-tests/base-layer-sepcs.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ test('#AggregationLayer -> updateLayerDomain', t => {
t.end();
});

test('#BaseLayer -> getAllPossibleColumnParis', t => {
test('#BaseLayer -> getAllPossibleColumnPairs', t => {
const columnes1 = {
a: [1, 2],
b: [3, 4]
Expand All @@ -124,8 +124,8 @@ test('#BaseLayer -> getAllPossibleColumnParis', t => {
const columnes3 = {
a: [1]
};
t.equal(Layer.getAllPossibleColumnParis(columnes1).length, 4, 'should find 4 pairs');
t.equal(Layer.getAllPossibleColumnParis(columnes2).length, 2, 'should find 4 pairs');
t.equal(Layer.getAllPossibleColumnParis(columnes3).length, 1, 'should find 4 pairs');
t.equal(Layer.getAllPossibleColumnPairs(columnes1).length, 4, 'should find 4 pairs');
t.equal(Layer.getAllPossibleColumnPairs(columnes2).length, 2, 'should find 4 pairs');
t.equal(Layer.getAllPossibleColumnPairs(columnes3).length, 1, 'should find 4 pairs');
t.end();
});

0 comments on commit b4cec94

Please sign in to comment.