Skip to content

Commit

Permalink
✨ Integrate col mgmt modal feature with table hooks
Browse files Browse the repository at this point in the history
Signed-off-by: Ian Bolton <[email protected]>
  • Loading branch information
ibolton336 committed Mar 25, 2024
1 parent 4f54b05 commit e2a0503
Show file tree
Hide file tree
Showing 33 changed files with 388 additions and 78 deletions.
1 change: 1 addition & 0 deletions client/src/app/components/answer-table/answer-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const AnswerTable: React.FC<IAnswerTableProps> = ({
const { t } = useTranslation();

const tableControls = useLocalTableControls({
tableName: "answer-table",
idProperty: "text",
items: hideAnswerKey
? answers.filter((answer) => answer.selected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const QuestionsTable: React.FC<{
hideAnswerKey,
}) => {
const tableControls = useLocalTableControls({
tableName: "questions-table",
idProperty: "text",
items: questions || [],
columnNames: {
Expand Down
1 change: 1 addition & 0 deletions client/src/app/hooks/table-controls/DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const things: Thing[] = [
];

const tableControls = useLocalTableControls({
tableName: 'page-table-name' // A unique name of the table
idProperty: "id", // The name of a unique string or number property on the data items.
items: things, // The generic type `TItem` is inferred from the items passed here.
columnNames: {
Expand Down
28 changes: 28 additions & 0 deletions client/src/app/hooks/table-controls/column/useColumnState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useLocalStorage } from "@migtools/lib-ui";

export interface ColumnState<TColumnKey extends string> {
id: TColumnKey;
label: string;
isVisible: boolean;
}

export interface IColumnState<TColumnKey extends string> {
columns: ColumnState<TColumnKey>[];
setColumns: (newColumns: ColumnState<TColumnKey>[]) => void;
}

interface IColumnStateArgs<TColumnKey extends string> {
initialColumns: ColumnState<TColumnKey>[];
columnsKey: string;
}

export const useColumnState = <TColumnKey extends string>(
args: IColumnStateArgs<TColumnKey>
): IColumnState<TColumnKey> => {
const [columns, setColumns] = useLocalStorage<ColumnState<TColumnKey>[]>({
key: args.columnsKey,
defaultValue: args.initialColumns,
});

return { columns, setColumns };
};
34 changes: 33 additions & 1 deletion client/src/app/hooks/table-controls/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
import { IFilterToolbarProps } from "@app/components/FilterToolbar";
import { IToolbarBulkSelectorProps } from "@app/components/ToolbarBulkSelector";
import { IExpansionPropHelpersExternalArgs } from "./expansion/useExpansionPropHelpers";
import { IColumnState } from "./column/useColumnState";

// Generic type params used here:
// TItem - The actual API objects represented by rows in the table. Can be any object.
Expand All @@ -56,7 +57,8 @@ export type TableFeature =
| "pagination"
| "selection"
| "expansion"
| "activeItem";
| "activeItem"
| "columns";

/**
* Identifier for where to persist state for a single table feature or for all table features.
Expand Down Expand Up @@ -136,12 +138,19 @@ export type IUseTableControlStateArgs<
TFilterCategoryKey extends string = string,
TPersistenceKeyPrefix extends string = string,
> = {
/**
* Unique table identifier. Used for state persistence and to distinguish between stored state between multiple tables.
*/
tableName: string;
/**
* An ordered mapping of unique keys to human-readable column name strings.
* - Keys of this object are used as unique identifiers for columns (`columnKey`).
* - Values of this object are rendered in the column headers by default (can be overridden by passing children to <Th>) and used as `dataLabel` for cells in the column.
*/
columnNames: Record<TColumnKey, string>;
/**
* Initial state for the columns feature. If omitted, all columns are enabled by default.
*/
} & IFilterStateArgs<TItem, TFilterCategoryKey> &
ISortStateArgs<TSortableColumnKey> &
IPaginationStateArgs & {
Expand Down Expand Up @@ -193,6 +202,10 @@ export type ITableControlState<
* State for the active item feature. Returned by useActiveItemState.
*/
activeItemState: IActiveItemState;
/**
* State for the columns feature. Returned by useColumnState.
*/
columnState: IColumnState<TColumnKey>;
};

/**
Expand Down Expand Up @@ -288,6 +301,10 @@ export type IUseTableControlPropsArgs<
* @todo this won't be included here when useSelectionState gets moved from lib-ui. It is separated from the other state temporarily and used only at render time.
*/
selectionState: ReturnType<typeof useSelectionState<TItem>>;
/**
* The state for the columns feature. Returned by useColumnState.
*/
columnState: IColumnState<TColumnKey>;
};

/**
Expand Down Expand Up @@ -325,9 +342,18 @@ export type ITableControls<
* Values derived at render time from the expansion feature state. Includes helper functions for convenience.
*/
expansionDerivedState: IExpansionDerivedState<TItem, TColumnKey>;
/**
* Values derived at render time from the column feature state. Includes helper functions for convenience.
*
*
*
*
*/
columnState: IColumnState<TColumnKey>;
/**
* Values derived at render time from the active-item feature state. Includes helper functions for convenience.
*/

activeItemDerivedState: IActiveItemDerivedState<TItem>;
/**
* Prop helpers: where it all comes together.
Expand Down Expand Up @@ -406,6 +432,12 @@ export type ITableControls<
* The two Trs for the expandable row and expanded content row should be contained in a Tbody with no other Tr components.
*/
getExpandedContentTdProps: (args: { item: TItem }) => Omit<TdProps, "ref">;

/**
* Returns the visibility of a column
*/

getColumnVisibility: (columnKey: TColumnKey) => boolean;
};
};

Expand Down
3 changes: 3 additions & 0 deletions client/src/app/hooks/table-controls/useLocalTableControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const useLocalTableControls = <
> => {
const state = useTableControlState(args);
const derivedState = getLocalTableControlDerivedState({ ...args, ...state });
const { columnState } = state;
return useTableControlProps({
...args,
...state,
Expand All @@ -42,5 +43,7 @@ export const useLocalTableControls = <
...args,
isEqual: (a, b) => a[args.idProperty] === b[args.idProperty],
}),
idProperty: args.idProperty,
...columnState,
});
};
6 changes: 6 additions & 0 deletions client/src/app/hooks/table-controls/useTableControlProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const useTableControlProps = <
isSelectionEnabled,
isExpansionEnabled,
isActiveItemEnabled,
columnState: { columns },
} = args;

const columnKeys = objectKeys(columnNames);
Expand Down Expand Up @@ -171,6 +172,10 @@ export const useTableControlProps = <
},
});

const getColumnVisibility = (columnKey: TColumnKey) => {
return columns.find((column) => column.id === columnKey)?.isVisible ?? true;
};

return {
...args,
numColumnsBeforeData,
Expand All @@ -191,6 +196,7 @@ export const useTableControlProps = <
getSelectCheckboxTdProps,
getSingleExpandButtonTdProps,
getExpandedContentTdProps,
getColumnVisibility,
},
};
};
15 changes: 15 additions & 0 deletions client/src/app/hooks/table-controls/useTableControlState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useSortState } from "./sorting";
import { usePaginationState } from "./pagination";
import { useActiveItemState } from "./active-item";
import { useExpansionState } from "./expansion";
import { useColumnState } from "./column/useColumnState";

/**
* Provides the "source of truth" state for all table features.
Expand Down Expand Up @@ -66,12 +67,26 @@ export const useTableControlState = <
...args,
persistTo: getPersistTo("activeItem"),
});

const { columnNames, tableName } = args;

const initialColumns = Object.entries(columnNames).map(([id, label]) => ({
id: id as TColumnKey,
label: label as string,
isVisible: true,
}));

const columnState = useColumnState<TColumnKey>({
columnsKey: tableName,
initialColumns,
});
return {
...args,
filterState,
sortState,
paginationState,
expansionState,
activeItemState,
columnState,
};
};
Loading

0 comments on commit e2a0503

Please sign in to comment.