Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data Table Fixes #1104

Merged
merged 3 commits into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"root": true,
"ignorePatterns": ["**/*"],
"plugins": ["@nx/eslint-plugin"],
"plugins": ["@nx/eslint-plugin", "eslint-plugin-react-compiler"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"rules": {
"@typescript-eslint/explicit-member-accessibility": "off",
Expand Down Expand Up @@ -43,6 +43,7 @@
{
"files": ["*.tsx"],
"rules": {
"react-compiler/react-compiler": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": "warn"
}
Expand Down
18 changes: 18 additions & 0 deletions apps/jetstream/src/main.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
@import '@salesforce-ux/design-system/scss/_design-tokens';

@layer rdg.rdg-checkbox-input {
.rdg-checkbox-input {
inline-size: 14px; /* Override the width */
block-size: 14px; /* Override the height */
// background-color: #0176d3; /* Example: add a custom background */
// accent-color: white;
}
}

// TODO: play around with this as we can potentially figure out how to style the checkbox

// .rdg .rdg-checkbox-input {
// // inline-size: 25px !important;
// // block-size: 25px !important;
// background-color: white !important; /* Ensure it overrides */
// accent-color: #0176d3 !important; /* Ensure it overrides */
// }

html {
background-color: rgb(17, 24, 39);
}
Expand Down
16 changes: 3 additions & 13 deletions libs/features/deploy/src/utils/deploy-metadata.utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,7 @@ import {
SalesforceDeployHistoryType,
SalesforceOrgUi,
} from '@jetstream/types';
import {
ColumnWithFilter,
Grid,
Icon,
SelectFormatter,
SelectHeaderGroupRenderer,
SelectHeaderRenderer,
setColumnFromType,
Spinner,
} from '@jetstream/ui';
import { ColumnWithFilter, Grid, Icon, SelectFormatter, SelectHeaderGroupRenderer, setColumnFromType, Spinner } from '@jetstream/ui';
import { composeQuery, getField, Query } from '@jetstreamapp/soql-parser-js';
import { formatISO } from 'date-fns/formatISO';
import { parseISO } from 'date-fns/parseISO';
Expand Down Expand Up @@ -232,16 +223,15 @@ export function getColumnDefinitions(): ColumnWithFilter<DeployMetadataTableRow>
</Grid>
);
}
return <SelectFormatter {...args} />;
return SelectColumn.renderCell?.(args) || <SelectFormatter {...args} />;
},
renderHeaderCell: SelectHeaderRenderer,
renderGroupCell: (args) => {
const { childRows } = args;
// Don't allow selection if child rows are loading
if (childRows.length === 0 || (childRows.length === 1 && (childRows[0].loading || !childRows[0].metadata))) {
return null;
}
return <SelectHeaderGroupRenderer {...args} />;
return SelectColumn.renderGroupCell?.(args) || <SelectHeaderGroupRenderer {...args} />;
},
colSpan: (args) => {
if (args.type === 'ROW') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { css } from '@emotion/react';
import { orderValues } from '@jetstream/shared/utils';
import { AutoFullHeightContainer, ColumnWithFilter, ContextMenuActionData, ContextMenuItem, DataTree } from '@jetstream/ui';
import { ContextMenuItem } from '@jetstream/types';
import { AutoFullHeightContainer, ColumnWithFilter, ContextMenuActionData, DataTree } from '@jetstream/ui';
import copyToClipboard from 'copy-to-clipboard';
import groupBy from 'lodash/groupBy';
import { FunctionComponent, useCallback, useEffect, useState } from 'react';
Expand Down
15 changes: 15 additions & 0 deletions libs/types/src/lib/ui/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,21 @@ export interface DropDownItem<T = any> {
metadata?: T;
}

export interface ContextMenuItem<T = any> {
subheader?: string;
label: string | ReactNode;
value: T;
icon?: {
type: string;
icon: string;
description?: string;
}; // FIXME: unable to import cross module boundaries
trailingDivider?: boolean;
disabled?: boolean;
title?: string;
metadata?: T;
}

export interface QueryFieldHeader {
label: string;
accessor: string;
Expand Down
2 changes: 1 addition & 1 deletion libs/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export * from './lib/form/combobox/ComboboxWithItems';
export * from './lib/form/combobox/ComboboxWithItemsTypeAhead';
export * from './lib/form/combobox/ComboboxWithItemsVirtual';
export * from './lib/form/combobox/useFieldListItemsWithDrillIn';
export * from './lib/form/context-menu/ContextMenu';
export * from './lib/form/controlled-inputs/ControlledInput';
export * from './lib/form/controlled-inputs/ControlledTextarea';
export * from './lib/form/date-time/DateTime';
Expand Down Expand Up @@ -113,7 +114,6 @@ export * from './lib/nav/Navbar';
export * from './lib/nav/NavbarAppLauncher';
export * from './lib/nav/NavbarItem';
export * from './lib/nav/NavbarMenuItems';
export * from './lib/popover/ContextMenu';
export * from './lib/popover/Popover';
export * from './lib/popover/PopoverErrorButton';
export * from './lib/progress-indicator/ProgressIndicator';
Expand Down
79 changes: 51 additions & 28 deletions libs/ui/src/lib/data-table/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { SalesforceOrgUi } from '@jetstream/types';
import { ContextMenuItem, SalesforceOrgUi } from '@jetstream/types';
import { forwardRef } from 'react';
import DataGrid, { DataGridProps, SortColumn } from 'react-data-grid';
import 'react-data-grid/lib/styles.css';
import { ContextMenuContext, ContextMenuItem } from '../popover/ContextMenu';
import { ContextMenu } from '../form/context-menu/ContextMenu';
import { DataTableFilterContext, DataTableGenericContext } from './data-table-context';
import './data-table-styles.scss';
import { ColumnWithFilter, ContextMenuActionData, RowWithKey } from './data-table-types';
Expand Down Expand Up @@ -76,10 +76,13 @@ export const DataTable = forwardRef<any, DataTableProps<any>>(
reorderedColumns,
filterSetValues,
filteredRows,
contextMenuProps,
setSortColumns,
updateFilter,
handleReorderColumns,
handleCellKeydown,
handleCellContextMenu,
handleCloseContextMenu,
} = useDataTable({
data,
columns: _columns,
Expand All @@ -100,33 +103,53 @@ export const DataTable = forwardRef<any, DataTableProps<any>>(
});

return (
<ContextMenuContext.Provider value={new Map()}>
<DataTableGenericContext.Provider value={{ ...context, rows: filteredRows, columns }}>
<DataTableFilterContext.Provider
value={{
filterSetValues,
filters,
portalRefForFilters: context?.portalRefForFilters,
updateFilter,
}}
>
<DataGrid
data-id={gridId}
className="rdg-light fill-grid"
columns={reorderedColumns}
rows={filteredRows}
renderers={renderers}
sortColumns={sortColumns}
onSortColumnsChange={setSortColumns}
rowKeyGetter={getRowKey}
defaultColumnOptions={{ resizable: true, sortable: true, ...rest.defaultColumnOptions }}
onCellKeyDown={handleCellKeydown}
onColumnsReorder={handleReorderColumns}
{...rest}
<DataTableGenericContext.Provider value={{ ...context, rows: filteredRows, columns }}>
<DataTableFilterContext.Provider
value={{
filterSetValues,
filters,
portalRefForFilters: context?.portalRefForFilters,
updateFilter,
}}
>
<DataGrid
data-id={gridId}
className="rdg-light fill-grid"
columns={reorderedColumns}
rows={filteredRows}
// @ts-expect-error Types are incorrect, but they are generic and difficult to get correct
renderers={renderers}
sortColumns={sortColumns}
onSortColumnsChange={setSortColumns}
// @ts-expect-error Types are incorrect, but they are generic and difficult to get correct
rowKeyGetter={getRowKey}
defaultColumnOptions={{ resizable: true, sortable: true, ...rest.defaultColumnOptions } as any}
// @ts-expect-error Types are incorrect, but they are generic and difficult to get correct
onCellKeyDown={handleCellKeydown}
onColumnsReorder={handleReorderColumns}
// @ts-expect-error Types are incorrect, but they are generic and difficult to get correct
onCellContextMenu={handleCellContextMenu}
{...rest}
/>
{contextMenuProps && contextMenuItems && contextMenuAction && (
<ContextMenu
parentElement={contextMenuProps.element}
items={contextMenuItems}
onSelected={(item) => {
contextMenuAction(item, {
row: filteredRows[contextMenuProps.rowIdx] as T,
rowIdx: contextMenuProps.rowIdx,
rows: filteredRows as T[],
column: columns[contextMenuProps.rowIdx],
columns,
});
handleCloseContextMenu();
}}
onClose={handleCloseContextMenu}
/>
</DataTableFilterContext.Provider>
</DataTableGenericContext.Provider>
</ContextMenuContext.Provider>
)}
</DataTableFilterContext.Provider>
</DataTableGenericContext.Provider>
);
}
);
12 changes: 9 additions & 3 deletions libs/ui/src/lib/data-table/DataTableEditors.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FocusTrap } from '@headlessui/react';
import { logger } from '@jetstream/shared/client-logger';
import { SFDC_BLANK_PICKLIST_VALUE } from '@jetstream/shared/constants';
import { describeSObject, query } from '@jetstream/shared/data';
Expand Down Expand Up @@ -59,7 +60,7 @@ function DataTableEditorPopover({
ref={popoverRef}
isOpen
referenceElement={referenceElement as any}
className={`slds-popover slds-popover slds-popover_edit`}
className="slds-popover slds-popover slds-popover_edit"
role="dialog"
offset={[0, -28.5]}
usePortal
Expand All @@ -69,7 +70,11 @@ function DataTableEditorPopover({
}
}}
>
{referenceElement && <div className="slds-p-around_x-small">{children}</div>}
{referenceElement && (
<FocusTrap>
<div className="slds-p-around_x-small">{children}</div>
</FocusTrap>
)}
</PopoverContainer>
</OutsideClickHandler>
);
Expand Down Expand Up @@ -247,6 +252,7 @@ export function DataTableEditorDate<TRow extends { _idx: number }, TSummaryRow>(
className="d-block"
initialSelectedDate={currDate}
openOnInit
inputProps={{ autoFocus: true }}
onChange={(value) => {
/** setTimeout is used to avoid a React error about flushSync being called during a render */
setTimeout(() => {
Expand Down Expand Up @@ -328,7 +334,7 @@ export const dataTableEditorRecordLookup = ({ sobject }: { sobject: string }) =>
);

if (!org || !sobject) {
return <DataTableEditorText column={column} onClose={onClose} onRowChange={onRowChange} row={row} />;
return <DataTableEditorText rowIdx={row._idx} column={column} onClose={onClose} onRowChange={onRowChange} row={row} />;
}

return (
Expand Down
30 changes: 6 additions & 24 deletions libs/ui/src/lib/data-table/DataTableRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,29 +56,9 @@ export function configIdLinkRenderer(serverUrl: string, org: SalesforceOrgUi, sk

// HEADER RENDERERS

/**
* SELECT ALL CHECKBOX HEADER
*/
export function SelectHeaderRenderer<T>(props: RenderHeaderCellProps<T>) {
const { column } = props;
const [isRowSelected, onRowSelectionChange] = useRowSelection();

return (
<Checkbox
id={`checkbox-${column.name}_header`} // TODO: need way to get row id
label="Select all"
hideLabel
checked={isRowSelected}
onChange={(checked) => onRowSelectionChange({ type: 'HEADER', checked })}
// WAITING ON: https://github.com/adazzle/react-data-grid/issues/3058
// indeterminate={props.row.getIsSomeSelected()}
/>
);
}

export function SelectHeaderGroupRenderer<T>(props: RenderGroupCellProps<T>) {
const { column, groupKey, row, childRows } = props;
const [isRowSelected, onRowSelectionChange] = useRowSelection();
const { isRowSelectionDisabled, isRowSelected, onRowSelectionChange } = useRowSelection();

return (
<DataTableSelectedContext.Consumer>
Expand All @@ -88,8 +68,9 @@ export function SelectHeaderGroupRenderer<T>(props: RenderGroupCellProps<T>) {
label="Select all"
hideLabel
checked={isRowSelected}
disabled={isRowSelectionDisabled}
indeterminate={selectedRowIds.size > 0 && childRows.some((childRow) => selectedRowIds.has((getRowKey || getRowId)(childRow)))}
onChange={(checked) => onRowSelectionChange({ type: 'ROW', row: row, checked, isShiftClick: false })}
onChange={(checked) => onRowSelectionChange({ row: row, checked, isShiftClick: false })}
/>
)}
</DataTableSelectedContext.Consumer>
Expand Down Expand Up @@ -511,15 +492,16 @@ export function GenericRenderer(RenderCellProps: RenderCellProps<RowWithKey>) {

export function SelectFormatter<T>(props: RenderCellProps<T>) {
const { column, row } = props;
const [isRowSelected, onRowSelectionChange] = useRowSelection();
const { isRowSelectionDisabled, isRowSelected, onRowSelectionChange } = useRowSelection();

return (
<Checkbox
id={`checkbox-${column.name}-${getRowId(row)}`} // TODO: need way to get row id
label="Select row"
hideLabel
checked={isRowSelected}
onChange={(checked) => onRowSelectionChange({ type: 'ROW', row, checked, isShiftClick: false })}
disabled={isRowSelectionDisabled}
onChange={(checked) => onRowSelectionChange({ row, checked, isShiftClick: false })}
/>
);
}
Expand Down
3 changes: 1 addition & 2 deletions libs/ui/src/lib/data-table/DataTableSubqueryRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { queryMore } from '@jetstream/shared/data';
import { copyRecordsToClipboard, formatNumber } from '@jetstream/shared/ui-utils';
import { flattenRecord } from '@jetstream/shared/utils';
import { Maybe, QueryResult, SalesforceOrgUi } from '@jetstream/types';
import { ContextMenuItem, Maybe, QueryResult, SalesforceOrgUi } from '@jetstream/types';
import { FunctionComponent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { RenderCellProps } from 'react-data-grid';
import RecordDownloadModal from '../file-download-modal/RecordDownloadModal';
import Grid from '../grid/Grid';
import AutoFullHeightContainer from '../layout/AutoFullHeightContainer';
import Modal from '../modal/Modal';
import { ContextMenuItem } from '../popover/ContextMenu';
import Icon from '../widgets/Icon';
import Spinner from '../widgets/Spinner';
import { DataTable } from './DataTable';
Expand Down
Loading
Loading