Skip to content

Commit

Permalink
Add ZoneGrid component (#3512)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomTirapani authored Nov 2, 2023
1 parent 49f1c9d commit af45ab8
Show file tree
Hide file tree
Showing 30 changed files with 2,089 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
* Clicking on the right hand clear button in a `textInput` (desktop and mobile)
now maintains focus on the `textInput`, allowing a user to quickly type something else into
the field. This behaviour already existed on the `select` input.
* Added `ZoneGrid`, a specialized version of the Grid component that displays its data with
multi-line full-width rows. Each row is broken into four zones for top/bottom and left/right,
each of which can mapped to render one or more fields.

### 💥 Breaking Changes

Expand Down
2 changes: 1 addition & 1 deletion cmp/grid/Grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export const [Grid, grid] = hoistCmp.withFactory<GridProps>({
}
});

(Grid as any).MULTIFIELD_ROW_HEIGHT = 38;
(Grid as any).MULTIFIELD_ROW_HEIGHT = 42;

//------------------------
// Implementation
Expand Down
2 changes: 1 addition & 1 deletion cmp/grid/GridModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export interface GridConfig {
/** Config with which to create a GridFilterModel, or `true` to enable default. Desktop only.*/
filterModel?: GridFilterModelConfig | boolean;

/** Config with which to create aColChooserModel, or boolean `true` to enable default.*/
/** Config with which to create a ColChooserModel, or boolean `true` to enable default.*/
colChooserModel?: ColChooserConfig | boolean;

/**
Expand Down
2 changes: 1 addition & 1 deletion cmp/grid/renderers/MultiFieldRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function renderMainField(value, renderer, context) {

function renderSubField({colId, label}, context) {
const {record, gridModel} = context,
column = gridModel.findColumn(gridModel.columns, colId);
column = gridModel.getColumn(colId);

throwIf(!column, `Subfield ${colId} not found`);

Expand Down
47 changes: 47 additions & 0 deletions cmp/zoneGrid/Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2023 Extremely Heavy Industries Inc.
*/

import {Column, ColumnRenderer, ColumnSortSpec} from '@xh/hoist/cmp/grid';
import {PersistOptions} from '@xh/hoist/core';

export type Zone = 'tl' | 'tr' | 'bl' | 'br';

export interface ZoneMapping {
/** Field to display. Must match a Field found in the Store */
field: string;
/** True to prefix the field value with its name */
showLabel?: boolean;
}

export interface ZoneLimit {
/** Min number of fields that should be mapped to the zone */
min?: number;
/** Max number of fields that should be mapped to the zone */
max?: number;
/** Array of allowed fields for the zone */
only?: string[];
}

export interface ZoneField {
field: string;
displayName: string;
label: string;
renderer: ColumnRenderer;
column: Column;
chooserGroup: string;
sortable: boolean;
sortingOrder: ColumnSortSpec[];
}

export interface ZoneGridModelPersistOptions extends PersistOptions {
/** True to include mapping information (default true) */
persistMapping?: boolean;
/** True to include grouping information (default true) */
persistGrouping?: boolean;
/** True to include sorting information (default true) */
persistSort?: boolean;
}
62 changes: 62 additions & 0 deletions cmp/zoneGrid/ZoneGrid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* This file belongs to Hoist, an application development toolkit
* developed by Extremely Heavy Industries (www.xh.io | [email protected])
*
* Copyright © 2023 Extremely Heavy Industries Inc.
*/
import {hoistCmp, HoistProps, LayoutProps, TestSupportProps, uses, XH} from '@xh/hoist/core';
import {fragment} from '@xh/hoist/cmp/layout';
import {GridOptions} from '@xh/hoist/kit/ag-grid';
import {grid} from '@xh/hoist/cmp/grid';
import {splitLayoutProps} from '@xh/hoist/utils/react';
import {zoneMapper as desktopZoneMapper} from '@xh/hoist/dynamics/desktop';
import {zoneMapper as mobileZoneMapper} from '@xh/hoist/dynamics/mobile';
import {ZoneGridModel} from './ZoneGridModel';

export interface ZoneGridProps extends HoistProps<ZoneGridModel>, LayoutProps, TestSupportProps {
/**
* Options for ag-Grid's API.
*
* This constitutes an 'escape hatch' for applications that need to get to the underlying
* ag-Grid API. It should be used with care. Settings made here might be overwritten and/or
* interfere with the implementation of this component and its use of the ag-Grid API.
*
* Note that changes to these options after the component's initial render will be ignored.
*/
agOptions?: GridOptions;
}

/**
* A ZoneGrid is a specialized version of the Grid component.
*
* It displays its data with multi-line full-width rows, each broken into four zones for
* top/bottom and left/right - (tl, tr, bl, br). Zone mappings determine which of the
* available fields should be extracted from the record and rendered into each zone.
*/
export const [ZoneGrid, zoneGrid] = hoistCmp.withFactory<ZoneGridProps>({
displayName: 'ZoneGrid',
model: uses(ZoneGridModel),
className: 'xh-zone-grid',

render({model, className, testId, ...props}, ref) {
const {gridModel, mapperModel} = model,
[layoutProps] = splitLayoutProps(props),
platformZoneMapper = XH.isMobileApp ? mobileZoneMapper : desktopZoneMapper;

return fragment(
grid({
...layoutProps,
className,
testId,
ref,
model: gridModel,
agOptions: {
suppressRowGroupHidesColumns: true,
suppressMakeColumnVisibleAfterUnGroup: true,
...props.agOptions
}
}),
mapperModel ? platformZoneMapper() : null
);
}
});
Loading

0 comments on commit af45ab8

Please sign in to comment.