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

Add DataGrid (unstyled) #1808

Merged
merged 34 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
50bbec5
fix: add material-react-table
KevinGhadyani-Okta May 31, 2023
9190f7f
fix: upgraded Prettier
KevinGhadyani-Okta Jun 12, 2023
1a35fe0
feat: added DataGrid
KevinGhadyani-Okta May 31, 2023
25b4d21
fix: added tsbuildinfo to speed up TS compiles
KevinGhadyani-Okta May 31, 2023
a067a1f
fix: removed unused dependencies from Storybook
KevinGhadyani-Okta Jun 12, 2023
92dd0d2
fix: updated DataGrid story for Storybook v7
KevinGhadyani-Okta Jun 6, 2023
17d0e1f
feat: updated DataGrid with more functionality
KevinGhadyani-Okta Jun 9, 2023
95d249f
fix: added notes to DataGrid and commented out Reports
KevinGhadyani-Okta Jun 12, 2023
50eee69
fix: removed unused imports from DataGrid
KevinGhadyani-Okta Jun 12, 2023
a54e37e
fix: upgraded material-react-table
KevinGhadyani-Okta Jun 12, 2023
dee7766
fix: removed unsused comment in DataGrid
KevinGhadyani-Okta Jun 12, 2023
5e3e216
fix: split DataGrid into 2 components
KevinGhadyani-Okta Jun 13, 2023
39ee64d
fix: added translation interpolation and plurality
KevinGhadyani-Okta Jun 13, 2023
1bf11f2
feat: added PaginatedDataGrid
KevinGhadyani-Okta Jun 21, 2023
c290d39
Merge remote-tracking branch 'origin/develop' into kg/OKTA-612737
KevinGhadyani-Okta Jun 22, 2023
28db116
fix: minor alphabetization in Select
KevinGhadyani-Okta Jun 22, 2023
537d41d
fix: pagination works now in DataGrid
KevinGhadyani-Okta Jun 22, 2023
87fcbcc
fix: removed InfinitelyScrolledDataGrid
KevinGhadyani-Okta Jun 22, 2023
e2a58ad
fix: minor code positioning
KevinGhadyani-Okta Jun 22, 2023
3cd5ee9
fix: renamed DataGrid to DataTable
KevinGhadyani-Okta Jun 23, 2023
8187024
fix: renamed table and fixed checkboxes
KevinGhadyani-Okta Jun 27, 2023
a21e23f
fix: removed unused DataGrid component
KevinGhadyani-Okta Jun 28, 2023
d6b40af
fix: incorrectly named i18nKey values
KevinGhadyani-Okta Jun 28, 2023
c8fbe84
fix: removed old Table stories
KevinGhadyani-Okta Jun 28, 2023
49e4a54
fix: stories using Table now use StaticTable
KevinGhadyani-Okta Jun 28, 2023
e9cd8b3
Merge remote-tracking branch 'origin/develop' into kg/OKTA-612737
KevinGhadyani-Okta Jun 29, 2023
feae5b1
fix: incorrect children type in OdysseyTranslationProvider
KevinGhadyani-Okta Jun 29, 2023
c810477
fix: story imports use @storybook/blocks instead of @storybook/addon-…
KevinGhadyani-Okta Jun 29, 2023
701361a
fix: missing Table components in RTL stories
KevinGhadyani-Okta Jun 29, 2023
f9cb55a
fix: updated TokenTables to properly render new brand tokens
KevinGhadyani-Okta Jun 29, 2023
b5b622d
fix: removed unused import
KevinGhadyani-Okta Jun 30, 2023
9b992c5
fix: added console.error where we had console.log
KevinGhadyani-Okta Jun 30, 2023
e8015f0
fix: axe testing bug
KevinGhadyani-Okta Jun 30, 2023
a20da0a
Merge remote-tracking branch 'origin/develop' into kg/OKTA-612737
KevinGhadyani-Okta Jun 30, 2023
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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"lerna": "^6.5.1",
"lint-staged": "^11.1.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.4.0",
"prettier": "^2.8.8",
"stylelint": "^14.13.0"
},
"version": "0.5.0",
Expand Down
1 change: 1 addition & 0 deletions packages/odyssey-react-mui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@mui/utils": "^5.11.2",
"@okta/odyssey-design-tokens": "workspace:*",
"i18next": "^22.4.15",
"material-react-table": "^1.14.0",
"react-i18next": "^12.2.2"
},
"devDependencies": {
Expand Down
1 change: 0 additions & 1 deletion packages/odyssey-react-mui/src/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export interface MenuItemProps

const MenuItem = ({ isDestructive, ...props }: MenuItemProps) => {
const { closeMenu } = useContext(MenuContext);
console.log(closeMenu);

return (
<MuiMenuItem
Expand Down
4 changes: 2 additions & 2 deletions packages/odyssey-react-mui/src/OdysseyTranslationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and limitations under the License.
*/

import { ReactElement, useEffect } from "react";
import { ReactNode, useEffect } from "react";

import { SupportedLanguages } from "./OdysseyTranslationProvider.types";

Expand All @@ -22,7 +22,7 @@ export type TranslationOverrides = {
};

type OdysseyTranslationProviderProps = {
children: ReactElement;
children: ReactNode;
languageCode?: SupportedLanguages;
translationOverrides?: TranslationOverrides;
};
Expand Down
271 changes: 271 additions & 0 deletions packages/odyssey-react-mui/src/PaginatedTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
/*!
* Copyright (c) 2022-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

import { AlertProps, TablePaginationProps, Typography } from "@mui/material";
import MaterialReactTable, {
MRT_PaginationState,
type MRT_ColumnFiltersState,
type MRT_RowSelectionState,
type MRT_TableInstance,
type MRT_Virtualizer,
} from "material-react-table";
import {
FunctionComponent,
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { Trans, useTranslation } from "react-i18next";

import type {
DefaultMaterialReactTableData,
MaterialReactTableProps,
} from "./materialReactTableTypes";

export type PaginatedTableProps<TData extends DefaultMaterialReactTableData> = {
columns: MaterialReactTableProps<TData>["columns"];
data: MaterialReactTableProps<TData>["data"];
fetchMoreData?: () => void;
getRowId?: MaterialReactTableProps<TData>["getRowId"];
hasError?: boolean;
hasRowSelection?: boolean;
initialState?: MaterialReactTableProps<TData>["initialState"];
isFetching?: boolean;
onGlobalFilterChange?: MaterialReactTableProps<TData>["onGlobalFilterChange"];
onPaginationChange?: MaterialReactTableProps<TData>["onPaginationChange"];
onRowSelectionChange?: MaterialReactTableProps<TData>["onRowSelectionChange"];
rowsPerPage?: number;
state?: MaterialReactTableProps<TData>["state"];
ToolbarButtons?: FunctionComponent<
{ table: MRT_TableInstance<TData> } & unknown
>;
};

const PaginatedTable = <TData extends DefaultMaterialReactTableData>({
columns,
data,
fetchMoreData,
getRowId,
hasError,
hasRowSelection,
initialState,
isFetching,
onGlobalFilterChange,
onPaginationChange,
onRowSelectionChange: onRowSelectionChangeProp,
rowsPerPage = 10,
state,
ToolbarButtons,
}: PaginatedTableProps<TData>) => {
const { t } = useTranslation();

const rowVirtualizerInstanceRef =
useRef<MRT_Virtualizer<HTMLDivElement, HTMLTableRowElement>>(null);

const [columnFilters, setColumnFilters] = useState<MRT_ColumnFiltersState>(
[]
);

const [globalFilter, setGlobalFilter] = useState<string>();

useEffect(() => {
if (globalFilter) {
onGlobalFilterChange?.(globalFilter);
}
}, [globalFilter, onGlobalFilterChange]);

useEffect(() => {
try {
// Scroll to top of table when sorting or filters change.
rowVirtualizerInstanceRef.current?.scrollToIndex?.(0);
} catch (error) {
console.error(error);
}
}, [columnFilters, globalFilter]);

const totalFetchedRows = data.length ?? 0;

const renderBottomToolbarCustomActions = useCallback(
() =>
fetchMoreData ? (
<Typography>
<Trans
count={totalFetchedRows}
i18nKey="table.fetchedrows.text"
values={{
totalRows: totalFetchedRows,
}}
/>
</Typography>
) : (
<Typography>
<Trans
count={totalFetchedRows}
i18nKey="table.rows.text"
values={{
totalRows: totalFetchedRows,
}}
/>
</Typography>
),
[fetchMoreData, totalFetchedRows]
);

const renderTopToolbarCustomActions = useCallback<
Exclude<
MaterialReactTableProps<TData>["renderTopToolbarCustomActions"],
undefined
>
>(
({ table }) => <>{ToolbarButtons && <ToolbarButtons table={table} />}</>,
[ToolbarButtons]
);

const [rowSelection, setRowSelection] = useState<MRT_RowSelectionState>({});

useEffect(() => {
onRowSelectionChangeProp?.(rowSelection);
}, [onRowSelectionChangeProp, rowSelection]);

const [pagination, setPagination] = useState<MRT_PaginationState>(
initialState?.pagination || {
pageIndex: 0,
pageSize: rowsPerPage,
}
);

const dataLengthRef = useRef(data.length);

const updatePagination = useCallback(
(paginationFunction) => {
if (data.length === dataLengthRef.current) {
setPagination((previousPagination) => {
const nextPagination = paginationFunction(previousPagination);
return nextPagination;
});
} else {
dataLengthRef.current = data.length;
}
},
[data.length]
);

useEffect(() => {
const numberOfPages = Math.floor(data.length / pagination.pageSize);

if (!isFetching && pagination.pageIndex > numberOfPages - 1) {
fetchMoreData?.();
}
}, [
data.length,
fetchMoreData,
isFetching,
pagination.pageIndex,
pagination.pageSize,
]);

useEffect(() => {
onPaginationChange?.({
pageIndex: pagination.pageIndex,
pageSize: pagination.pageSize,
});
}, [onPaginationChange, pagination.pageIndex, pagination.pageSize]);

const modifiedInitialState = useMemo(
() => ({
pagination,
...initialState,
}),
[initialState, pagination]
);

const modifiedState = useMemo(
() => ({
...state,
pagination: {
pageIndex: pagination.pageIndex,
pageSize: pagination.pageSize,
},
rowSelection,
}),
[pagination.pageIndex, pagination.pageSize, rowSelection, state]
);

const muiToolbarAlertBannerProps: AlertProps = useMemo(
() =>
hasError
? {
children: t("table.error"),
severity: "error",
}
: {},
[hasError, t]
);

const muiTablePaginationProps: Partial<
Omit<TablePaginationProps, "rowsPerPage">
> = useMemo(
() => ({
rowsPerPageOptions: [],
showFirstButton: false,
showLastButton: false,
}),
[]
);

const muiCheckboxStyles = useCallback(
(theme) =>
typeof theme.components?.MuiCheckbox?.styleOverrides?.root === "function"
? theme.components?.MuiCheckbox?.styleOverrides?.root?.({
ownerState: {},
theme,
})
: "",
[]
);

return (
<MaterialReactTable
columns={columns}
data={data}
enableMultiRowSelection={hasRowSelection}
enablePagination
enableRowSelection={hasRowSelection}
enableSorting={false}
getRowId={getRowId}
initialState={modifiedInitialState}
muiSelectAllCheckboxProps={{ sx: muiCheckboxStyles }}
muiSelectCheckboxProps={{ sx: muiCheckboxStyles }}
muiTablePaginationProps={muiTablePaginationProps}
muiToolbarAlertBannerProps={muiToolbarAlertBannerProps}
onColumnFiltersChange={setColumnFilters}
onGlobalFilterChange={setGlobalFilter}
onPaginationChange={updatePagination}
onRowSelectionChange={setRowSelection}
renderBottomToolbarCustomActions={renderBottomToolbarCustomActions}
renderTopToolbarCustomActions={renderTopToolbarCustomActions}
rowVirtualizerInstanceRef={rowVirtualizerInstanceRef}
rowVirtualizerProps={{ overscan: 4 }}
state={modifiedState}
/>
);
};

const MemoizedPaginatedTable = memo(PaginatedTable) as typeof PaginatedTable;

// @ts-expect-error | This is going to error because the component isn't and can't be defined as a `FunctionComponent`, and therefore, doesn't have a `displayName` prop.
MemoizedPaginatedTable.displayName = "PaginatedTable";

export { MemoizedPaginatedTable as PaginatedTable };
6 changes: 3 additions & 3 deletions packages/odyssey-react-mui/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import { Field } from "./Field";

export type SelectOption = {
text: string;
value?: string;
type?: "heading" | "option";
value?: string;
};

export type SelectProps = {
Expand Down Expand Up @@ -179,14 +179,14 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
const renderFieldComponent = useCallback(
() => (
<MuiSelect
children={children}
id={idOverride}
name={idOverride}
multiple={isMultiSelect}
name={idOverride}
onBlur={onBlur}
onChange={onChange}
onFocus={onFocus}
ref={ref}
children={children}
renderValue={isMultiSelect ? renderValue : undefined}
value={selectedValue}
/>
Expand Down
Loading