Skip to content

Commit

Permalink
Merge pull request #318 from qoretechnologies/foxhoundn/enhancement-a…
Browse files Browse the repository at this point in the history
…dd-keymapper-317

Foxhoundn/enhancement-add-keymapper-317
  • Loading branch information
Foxhoundn authored Aug 10, 2023
2 parents fe88401 + 1a57a72 commit 71c8554
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 15 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@qoretechnologies/reqore",
"version": "0.36.3",
"version": "0.36.4",
"description": "ReQore is a highly theme-able and modular UI library for React",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/components/ExportModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ReqoreTabs, { IReqoreTabsProps } from '../Tabs';
import ReqoreTabsContent from '../Tabs/content';

export interface IReqoreExportModalProps extends IReqoreModalProps {
data: { [key: string]: any } | any[];
data: { [key: string]: unknown } | unknown[];
sendNotificationOnCopy?: boolean;
tabsOptions?: Omit<IReqoreTabsProps, 'tabs'>;
}
Expand Down
20 changes: 17 additions & 3 deletions src/components/KeyValueTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@ import { SIZE_TO_PX } from '../../constants/sizes';
import { TReqoreIntent } from '../../constants/theme';
import { IReqoreIconName } from '../../types/icons';
import { IReqoreButtonProps } from '../Button';
import { IReqoreExportModalProps } from '../ExportModal';
import { IReqorePanelProps } from '../Panel';
import ReqoreTable, { IReqoreTableColumn, IReqoreTableProps, IReqoreTableRowData } from '../Table';
import ReqoreTable, {
IReqoreTableColumn,
IReqoreTableProps,
IReqoreTableRowData,
TReqoreTableColumnContent,
} from '../Table';
import { IReqoreTableValueProps, ReqoreTableValue } from '../Table/value';

export type TReqoreKeyValueTablePrimitiveValue = string | number | boolean | null | undefined;
export type TReqoreKeyValueTableValue =
| TReqoreKeyValueTablePrimitiveValue
| TReqoreKeyValueTablePrimitiveValue[]
| { [key: string]: TReqoreKeyValueTableValue };
export type TReqoreKeyValueTableExportMapper = (
data: { tableKey: TReqoreTableColumnContent; value: TReqoreTableColumnContent }[]
) => IReqoreExportModalProps['data'];

export interface IReqoreKeyValueTableProps
extends IReqorePanelProps,
Expand Down Expand Up @@ -50,20 +59,25 @@ export interface IReqoreKeyValueTableProps
minValueWidth?: number;
defaultValueFilter?: string | number;

keyRenderer?: (keyLabel: string | number) => string | number;

valueRenderer?: (
data: IReqoreTableRowData,
defaultComponent?: ({ value }: IReqoreTableValueProps) => any
) => any;

exportMapper?: TReqoreKeyValueTableExportMapper;
}

export const ReqoreKeyValueTable = ({
data,
keyLabel,
keyIcon,
keyRenderer,
valueLabel,
valueIcon,
valueRenderer,
keyColumnIntent = 'muted',
keyColumnIntent,
minValueWidth = 100,
maxKeyWidth = 200,
keyAlign = 'left',
Expand Down Expand Up @@ -92,7 +106,7 @@ export const ReqoreKeyValueTable = ({
},

cell: {
content: 'title',
content: keyRenderer ? ({ tableKey }) => keyRenderer(tableKey) : 'title',
},
},
{
Expand Down
41 changes: 34 additions & 7 deletions src/components/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import { useQueryWithDelay } from '../../hooks/useQueryWithDelay';
import { IReqoreIntent, IReqoreTooltip } from '../../types/global';
import { IReqoreButtonProps, TReqoreBadge } from '../Button';
import { IReqoreDropdownItem } from '../Dropdown/list';
import { ReqoreExportModal } from '../ExportModal';
import { IReqoreExportModalProps, ReqoreExportModal } from '../ExportModal';
import ReqoreInput, { IReqoreInputProps } from '../Input';
import { TReqoreKeyValueTableExportMapper } from '../KeyValueTable';
import { IReqorePanelAction, IReqorePanelProps, IReqorePanelSubAction } from '../Panel';
import ReqoreTableBody from './body';
import ReqoreTableHeader, { IReqoreCustomHeaderCellComponent } from './header';
Expand All @@ -43,15 +44,17 @@ import {
import { IReqoreTableRowOptions } from './row';

export type TReqoreTableColumnContent =
| React.FC<{ [key: string]: any; _selectId?: string | number; _size: TSizes; _dataId: string }>
| ((data: IReqoreTableRowData) => any)
| 'time-ago'
| 'tag'
| `tag:${TReqoreIntent}`
| `tag:#${string}`
| 'title'
| `title:${TReqoreIntent}`
| 'text'
| `text:${TReqoreIntent}`;
| `text:${TReqoreIntent}`
| string
| number;

export interface IReqoreTableColumn extends IReqoreIntent {
dataId: string;
Expand Down Expand Up @@ -136,6 +139,10 @@ export interface IReqoreTableProps extends IReqorePanelProps {
headerCellComponent?: IReqoreCustomHeaderCellComponent;
rowComponent?: IReqoreTableRowOptions['rowComponent'];
bodyCellComponent?: IReqoreTableRowOptions['cellComponent'];

exportMapper?:
| TReqoreKeyValueTableExportMapper
| ((data: unknown[]) => IReqoreExportModalProps['data']);
}

export interface IReqoreTableStyle {
Expand Down Expand Up @@ -178,6 +185,26 @@ const StyledTablesWrapper = styled.div`
overflow: hidden;
`;

export interface IReqoreTableExportModalProps {
data: unknown;
onClose: () => void;
exportMapper?: IReqoreTableProps['exportMapper'];
}

const ReqoreTableExportModal = ({ data, onClose, exportMapper }) => {
const fixedData = useMemo(() => {
let _fixedData = removeInternalData(data);

if (exportMapper) {
_fixedData = exportMapper(_fixedData);
}

return _fixedData;
}, [data, exportMapper]);

return <ReqoreExportModal data={fixedData} onClose={onClose} />;
};

const ReqoreTable = ({
className,
height,
Expand Down Expand Up @@ -210,6 +237,7 @@ const ReqoreTable = ({
onSelectClick,
paging,
exportable,
exportMapper,
...rest
}: IReqoreTableProps) => {
const leftTableRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -734,11 +762,10 @@ const ReqoreTable = ({
{(pagedData) => (
<>
{showExportModal && (
<ReqoreExportModal
data={removeInternalData(
showExportModal === 'current' ? pagedData : transformedData
)}
<ReqoreTableExportModal
data={showExportModal === 'current' ? pagedData : transformedData}
onClose={() => setShowExportModal(undefined)}
exportMapper={exportMapper}
/>
)}
<StyledTablesWrapper className='reqore-table-wrapper'>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Table/row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ const ReqoreTableRow = ({
</ReqoreP>
);
default:
return <ReqoreP className='reqore-table-text'>{data[dataId]}</ReqoreP>;
return <ReqoreP className='reqore-table-text'>{content}</ReqoreP>;
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ export const getLineCount = (value: string | null): number => {
// to a CSV string
export const convertToCSV = (objArray: any[]): string => {
const header = Object.keys(objArray[0]).join(',');
const rows = objArray.map((obj) => Object.values(obj).join(','));
const rows = objArray.map((obj) =>
Object.values(obj)
.map((value) => JSON.stringify(value))
.join(',')
);

return [header, ...rows].join('\n');
};

Expand Down
30 changes: 29 additions & 1 deletion src/stories/KeyValueTable/KeyValueTable.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { StoryObj } from '@storybook/react';
import { userEvent } from '@storybook/testing-library';
import { fireEvent, userEvent, waitFor, within } from '@storybook/testing-library';
import { noop } from 'lodash';
import ReqoreIcon from '../../components/Icon';
import { IReqoreKeyValueTableProps, ReqoreKeyValueTable } from '../../components/KeyValueTable';
Expand Down Expand Up @@ -263,6 +263,12 @@ export const CustomPaging: Story = {
},
};

export const CustomKeyRenderer: Story = {
args: {
keyRenderer: (label) => `${label}_custom`,
},
};

export const CustomValueRenderer: Story = {
args: {
valueRenderer: ({ value, tableKey }, Component): TReqoreTableColumnContent | JSX.Element => {
Expand All @@ -281,3 +287,25 @@ export const CustomValueRenderer: Story = {
},
},
};

export const CustomExportMapper: Story = {
args: {
exportable: true,
exportMapper: (data) => {
return data.reduce(
(acc, row) => ({
...acc,
[row.tableKey.toString()]: row.value,
}),
{}
);
},
},
play: async ({ canvasElement, ...rest }) => {
const canvas = within(canvasElement);
// @ts-expect-error
await ExportableTable.play({ canvasElement, ...rest });
await fireEvent.click(canvas.getAllByText('Export full data')[0]);
await waitFor(() => canvas.findAllByText('Export data'), { timeout: 5000 });
},
};

0 comments on commit 71c8554

Please sign in to comment.