@evenicanpm/portal-table-ui 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -5
- package/src/auth/auth-context.tsx +86 -0
- package/src/features/table/components/dashboard/index.tsx +1 -0
- package/src/features/table/components/dashboard/table/actions.ts +59 -0
- package/src/features/table/components/dashboard/table/data-mask-map.ts +26 -0
- package/src/features/table/components/dashboard/table/details/details.tsx +164 -0
- package/src/features/table/components/dashboard/table/details/index.ts +1 -0
- package/src/features/table/components/dashboard/table/details/label.tsx +26 -0
- package/src/features/table/components/dashboard/table/details/rows/downloads.tsx +26 -0
- package/src/features/table/components/dashboard/table/details/rows/index.ts +3 -0
- package/src/features/table/components/dashboard/table/details/rows/primitive.tsx +26 -0
- package/src/features/table/components/dashboard/table/details/rows/table.tsx +74 -0
- package/src/features/table/components/dashboard/table/details/styles.ts +18 -0
- package/src/features/table/components/dashboard/table/filter-render-map.tsx +9 -0
- package/src/features/table/components/dashboard/table/filters/date-filter.tsx +31 -0
- package/src/features/table/components/dashboard/table/filters/status-filter.tsx +36 -0
- package/src/features/table/components/dashboard/table/index.ts +2 -0
- package/src/features/table/components/dashboard/table/no-results.tsx +26 -0
- package/src/features/table/components/dashboard/table/status-pill.tsx +18 -0
- package/src/features/table/components/dashboard/table/table-header.tsx +62 -0
- package/src/features/table/components/dashboard/table/table-input.tsx +94 -0
- package/src/features/table/components/dashboard/table/table-row/action-button.tsx +39 -0
- package/src/features/table/components/dashboard/table/table-row/table-row.tsx +96 -0
- package/src/features/table/components/dashboard/table/table-row-skeleton.tsx +36 -0
- package/src/features/table/components/dashboard/table/table.tsx +250 -0
- package/src/features/table/components/dashboard/table-dashboard.tsx +71 -0
- package/src/features/table/index.ts +14 -0
- package/src/features/table/logic/index.ts +23 -0
- package/src/features/table/logic/resolvers.ts +68 -0
- package/src/features/table/logic/transformers.ts +56 -0
- package/src/features/table/logic/types.ts +8 -0
- package/src/features/table/types/handlers.ts +71 -0
- package/src/features/table/types/index.ts +70 -0
- package/src/features/table/types/queries.ts +34 -0
- package/src/features/table/types/schemas.ts +50 -0
- package/src/index.ts +65 -0
- package/src/portal.tsx +68 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { method, multi } from "@arrows/multimethod";
|
|
2
|
+
import type { Column } from "@evenicanpm/portal-types-schemas";
|
|
3
|
+
import type * as Types from "../types";
|
|
4
|
+
import type { FilterRequest } from "./types";
|
|
5
|
+
|
|
6
|
+
/** MULTIMETHOD FOR FILTERS
|
|
7
|
+
* Allows multiple implementations
|
|
8
|
+
* based on multiple column properties.
|
|
9
|
+
* Priotizes column name, but also can
|
|
10
|
+
* use data type
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export const resolveFilterUI = multi(
|
|
14
|
+
(req: FilterRequest, handlers: Types.Handlers.FilterRenderMap) => {
|
|
15
|
+
if (handlers?.[req.filterName]) return "BY_NAME";
|
|
16
|
+
if (handlers?.[req.filterType]) return "BY_TYPE";
|
|
17
|
+
return "NONE";
|
|
18
|
+
},
|
|
19
|
+
method(
|
|
20
|
+
"BY_NAME",
|
|
21
|
+
(req: FilterRequest, handlers: Types.Handlers.FilterRenderMap) =>
|
|
22
|
+
handlers[req.filterName],
|
|
23
|
+
),
|
|
24
|
+
method(
|
|
25
|
+
"BY_TYPE",
|
|
26
|
+
(req: FilterRequest, handlers: Types.Handlers.FilterRenderMap) =>
|
|
27
|
+
handlers[req.filterType],
|
|
28
|
+
),
|
|
29
|
+
method("NONE", () => () => null),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Dispatch identifies which properties are
|
|
34
|
+
* in handler, then provides corresponding method
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export const resolveDataMask = multi(
|
|
38
|
+
(col: Column, handlers: Types.Handlers.DataMaskMap) => {
|
|
39
|
+
if (!col?.DataMask) return "SKIP";
|
|
40
|
+
if (handlers?.[col?.DataType]) return "BY_TYPE";
|
|
41
|
+
if (handlers?.[col?.Data]) return "BY_NAME";
|
|
42
|
+
return "SKIP";
|
|
43
|
+
},
|
|
44
|
+
method(
|
|
45
|
+
"BY_TYPE",
|
|
46
|
+
(col: Column, handlers: Types.Handlers.DataMaskMap) =>
|
|
47
|
+
handlers?.[col?.DataType],
|
|
48
|
+
),
|
|
49
|
+
method(
|
|
50
|
+
"BY_NAME",
|
|
51
|
+
(col: Column, handlers: Types.Handlers.DataMaskMap) =>
|
|
52
|
+
handlers?.[col?.Data],
|
|
53
|
+
),
|
|
54
|
+
method("SKIP", () => (value: string | number) => value),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Simpler, doesn't need multimethod cause only dispatches on column name
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
export const resolveCellUI = (
|
|
62
|
+
col: Column,
|
|
63
|
+
handlers: Types.Handlers.CellRenderMap,
|
|
64
|
+
) => {
|
|
65
|
+
if (Object.hasOwn(handlers, col.Data)) return handlers?.[col?.Data];
|
|
66
|
+
|
|
67
|
+
return (value: string | number) => value;
|
|
68
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Column } from "@evenicanpm/portal-types-schemas";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* These are pure static functions that include business rules
|
|
5
|
+
* and data manipulation to get the data into the correct
|
|
6
|
+
* form for rendering.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Gets filters and returns an array of the
|
|
13
|
+
* active filters and corresponding options
|
|
14
|
+
* in FilterRequest
|
|
15
|
+
*/
|
|
16
|
+
export const getActiveFilters = (columns: Column[] | undefined) => {
|
|
17
|
+
return columns
|
|
18
|
+
?.filter((c) => c?.IsFilterable)
|
|
19
|
+
?.flatMap((c) =>
|
|
20
|
+
c?.Filters?.map((f) => ({
|
|
21
|
+
filterName: c.Data,
|
|
22
|
+
filterOptions: f.FilterOptions,
|
|
23
|
+
filterType: f.FilterType ?? c.DataType,
|
|
24
|
+
})),
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Filters and sorts visible cols
|
|
30
|
+
*/
|
|
31
|
+
export const getVisibleColumns = (columns: Column[] | undefined) =>
|
|
32
|
+
columns
|
|
33
|
+
?.filter(
|
|
34
|
+
(column): column is Column & { ColumnOrder: number } =>
|
|
35
|
+
typeof column.ColumnOrder === "number",
|
|
36
|
+
)
|
|
37
|
+
.sort((a, b) => a.ColumnOrder - b.ColumnOrder);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
*/
|
|
42
|
+
export const getVisibleDetails = (columns: Column[] | undefined) =>
|
|
43
|
+
columns
|
|
44
|
+
?.filter((col) => col.DisplayOrder)
|
|
45
|
+
?.sort((a, b) => {
|
|
46
|
+
if (a?.DisplayOrder && b?.DisplayOrder) {
|
|
47
|
+
return a?.DisplayOrder - b?.DisplayOrder;
|
|
48
|
+
}
|
|
49
|
+
return -1;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Filters and sorts visible cols
|
|
54
|
+
*/
|
|
55
|
+
export const getSearchableColumns = (columns: Column[] | undefined) =>
|
|
56
|
+
columns?.filter((column) => column?.IsSearchable);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { FilterOption } from "@evenicanpm/portal-types-schemas";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @group View Handlers
|
|
6
|
+
*/
|
|
7
|
+
export type DataMaskMap = Record<string, MaskingFunction>;
|
|
8
|
+
export type MaskingFunction = (
|
|
9
|
+
value: string | number,
|
|
10
|
+
dataMask: string,
|
|
11
|
+
) => string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Uses column names as keys and maps out
|
|
15
|
+
* value with specific JSX for specific column names.
|
|
16
|
+
*
|
|
17
|
+
*
|
|
18
|
+
* e.g. Status -> MUIChip
|
|
19
|
+
*
|
|
20
|
+
* @group View Handlers
|
|
21
|
+
*/
|
|
22
|
+
export interface CellRenderMap {
|
|
23
|
+
[ColumnName: string]: (
|
|
24
|
+
value: string | number | string[],
|
|
25
|
+
) => React.ReactElement;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface FilterProps {
|
|
29
|
+
filterName: string;
|
|
30
|
+
filterOptions: FilterOption[];
|
|
31
|
+
value: Record<string, string>;
|
|
32
|
+
setValue: React.Dispatch<React.SetStateAction<Record<string, string>>>;
|
|
33
|
+
resetPagination: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* Provides render methods for particular filter
|
|
39
|
+
* types. Filter types currently come from DataTypes.
|
|
40
|
+
*
|
|
41
|
+
* Note: Naive solution is to trust that project injects filter
|
|
42
|
+
* render methods for all columns with filters.We can then have a fallback for
|
|
43
|
+
* general data types.
|
|
44
|
+
*
|
|
45
|
+
* @group View Handlers
|
|
46
|
+
*/
|
|
47
|
+
export interface FilterRenderMap {
|
|
48
|
+
[ColumnName: string]: (props: FilterProps) => React.ReactElement;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @group View Handlers
|
|
54
|
+
*/
|
|
55
|
+
export interface EmptyStateProps {
|
|
56
|
+
label: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type NoResultsComponent = (props: EmptyStateProps) => React.ReactElement;
|
|
60
|
+
|
|
61
|
+
export interface DetailsRenderMap {
|
|
62
|
+
[columnName: string]: (props: {
|
|
63
|
+
[columnName: string]:
|
|
64
|
+
| string
|
|
65
|
+
| number
|
|
66
|
+
| object
|
|
67
|
+
| string[]
|
|
68
|
+
| number[]
|
|
69
|
+
| object[];
|
|
70
|
+
}) => React.ReactNode;
|
|
71
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # Table System: Module Registry
|
|
3
|
+
*
|
|
4
|
+
* This registry defines the structural blueprints for the Table system modules.
|
|
5
|
+
* Architecture driven by an array of Resource types which are equipped with
|
|
6
|
+
* configuration and render handlers responsible for rendering a table.
|
|
7
|
+
*
|
|
8
|
+
* ---
|
|
9
|
+
*
|
|
10
|
+
* ### 1. Queries (queries.ts)
|
|
11
|
+
* API Contracts. The raw shapes of server responses. These act as the transport
|
|
12
|
+
* layer for data before it is mapped into the system's primary models.
|
|
13
|
+
*
|
|
14
|
+
* ### 2. Schemas (schemas.ts)
|
|
15
|
+
* System Models. The primary blueprints—such as Column, Filter, and Resource—often
|
|
16
|
+
* derived from API definitions. These are the vocabulary used to drive the module.
|
|
17
|
+
*
|
|
18
|
+
* ### 3. State (state.ts)
|
|
19
|
+
* View Configuration. The dynamic parameters tracking how resources are
|
|
20
|
+
* filtered, sorted, and paginated in the current view.
|
|
21
|
+
*
|
|
22
|
+
* ### 4. Handlers (handlers.ts)
|
|
23
|
+
* Logic Registries. Objects indexed by column or resource type that map
|
|
24
|
+
* logic (like filtering and data masking) to specific parts of the system.
|
|
25
|
+
*
|
|
26
|
+
* ---
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* ## File descriptions
|
|
30
|
+
* ```
|
|
31
|
+
* ├── components // UI
|
|
32
|
+
* │ └── dashboard // displays multiple tables with tabs
|
|
33
|
+
* │ ├── index.tsx
|
|
34
|
+
* │ ├── table // individual table component
|
|
35
|
+
* │ │ ├── details
|
|
36
|
+
* │ │ │ ├── details.tsx // the details page
|
|
37
|
+
* │ │ │ ├── index.ts
|
|
38
|
+
* │ │ │ ├── label.tsx // labels used on details page
|
|
39
|
+
* │ │ │ ├── rows // individual rows for different details
|
|
40
|
+
* │ │ │ │ ├── downloads.tsx // download button for "documents" field
|
|
41
|
+
* │ │ │ │ ├── index.ts
|
|
42
|
+
* │ │ │ │ ├── primitive.tsx // simple text or number details field
|
|
43
|
+
* │ │ │ │ └── table.tsx // for complex object data (displays in table)
|
|
44
|
+
* │ │ │ └── styles.ts
|
|
45
|
+
* │ │ ├── status-pill.tsx // status pill used across table and details
|
|
46
|
+
* │ │ ├── table-input.tsx // table search bar
|
|
47
|
+
* │ │ └── table.tsx // actual table component
|
|
48
|
+
* │ └── table-dashboard.tsx // actual dashboard component
|
|
49
|
+
* ├── index.ts
|
|
50
|
+
* ├── logic // handles data transformations
|
|
51
|
+
* │ ├── index.ts
|
|
52
|
+
* │ ├── resolvers.ts // multi methods that just handle resolving the maps
|
|
53
|
+
* │ ├── transformers.ts // pure functions just for simple data transformations
|
|
54
|
+
* │ └── types.ts // types specifically for the transformations
|
|
55
|
+
* ├── queries // handles data fetching with react-query
|
|
56
|
+
* │ └── useTableQueries.tsx
|
|
57
|
+
* └── types // global types for feature
|
|
58
|
+
* ├── handlers.ts // types for handler maps (masks, renders, filters)
|
|
59
|
+
* ├── index.ts
|
|
60
|
+
* ├── queries.ts // types for data coming over the wire
|
|
61
|
+
* ├── schemas.ts // core system types (Resource)
|
|
62
|
+
* └── state.ts // types for transient state data (filter state)
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @packageDocumentation
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
export * as Handlers from "./handlers";
|
|
69
|
+
export * as Queries from "./queries";
|
|
70
|
+
export * as Schemas from "./schemas";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ViewConfig } from "@evenicanpm/portal-types-schemas";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* These are data types returned from API Backend
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* A single row in the data table response object.
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
export type Row = Record<
|
|
15
|
+
string,
|
|
16
|
+
string | number | string[] | Record<string, string>[] | unknown
|
|
17
|
+
>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* The response type defined in TDD for row data.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
export interface TableRows {
|
|
25
|
+
items: number;
|
|
26
|
+
data: Row[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* Response type of data from table config
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
export type TableConfig = ViewConfig;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { TableViewParams } from "@evenicanpm/portal-types-schemas";
|
|
2
|
+
import type {
|
|
3
|
+
CellRenderMap,
|
|
4
|
+
DataMaskMap,
|
|
5
|
+
DetailsRenderMap,
|
|
6
|
+
FilterRenderMap,
|
|
7
|
+
NoResultsComponent,
|
|
8
|
+
} from "./handlers";
|
|
9
|
+
import type { TableRows } from "./queries";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* These are primary domain models and the source of truth for table system.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Status maps
|
|
17
|
+
*/
|
|
18
|
+
export type StatusTextMap = Record<number | string, string>;
|
|
19
|
+
|
|
20
|
+
export type StatusColor = "success" | "primary" | "warning" | "error";
|
|
21
|
+
|
|
22
|
+
export type StatusColorMap = Record<number | string, StatusColor>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resource Definition
|
|
26
|
+
*/
|
|
27
|
+
export interface Resource {
|
|
28
|
+
name: string;
|
|
29
|
+
label: string;
|
|
30
|
+
idField: string;
|
|
31
|
+
|
|
32
|
+
// Data Handlers
|
|
33
|
+
rowsQueryFn: (displaySettings: TableViewParams) => {
|
|
34
|
+
queryKey: readonly unknown[];
|
|
35
|
+
queryFn: () => Promise<TableRows>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// UI Renderers & Mappings
|
|
39
|
+
cellRenderMap?: CellRenderMap;
|
|
40
|
+
dataMaskMap?: DataMaskMap;
|
|
41
|
+
filterRenderMap?: FilterRenderMap;
|
|
42
|
+
noResultsComponent?: NoResultsComponent;
|
|
43
|
+
|
|
44
|
+
// Optional Details view
|
|
45
|
+
detailsRenderMap?: DetailsRenderMap;
|
|
46
|
+
|
|
47
|
+
// State Visuals
|
|
48
|
+
statusTextMap: StatusTextMap;
|
|
49
|
+
statusColorMap: StatusColorMap;
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main entry point for the **e4Portal** library.
|
|
3
|
+
* All public functions are exported from here.
|
|
4
|
+
*
|
|
5
|
+
* The primary export of this package is the `Portal` React compound-component.
|
|
6
|
+
* The `Portal` component is the top-level that contains the auth, rbac and any other
|
|
7
|
+
* functionality that is not related to specific features. Specific features (e.g. `Table`)
|
|
8
|
+
* are modularized and exported as compond components attached to the main `Portal` component.
|
|
9
|
+
*
|
|
10
|
+
* ## Usage
|
|
11
|
+
*
|
|
12
|
+
* ```tsx
|
|
13
|
+
*
|
|
14
|
+
* import { Portal } from "@evenicanpm/portal";
|
|
15
|
+
*
|
|
16
|
+
* return (
|
|
17
|
+
* <Portal>
|
|
18
|
+
* <Portal.Table resources={resources}/>
|
|
19
|
+
* </Portal>
|
|
20
|
+
* );
|
|
21
|
+
*```
|
|
22
|
+
* To explore package hierarchy, navigate to the `Portal` link in the components group below.
|
|
23
|
+
* `TableProps` will be the main interface used to setup the `Table` feature for Copperstate implementation.
|
|
24
|
+
*
|
|
25
|
+
* ## Table Feature Usage
|
|
26
|
+
* ```tsx
|
|
27
|
+
* const PortalView = () => {
|
|
28
|
+
* const { data: session, status } = useSession(); // authentication + token
|
|
29
|
+
* const { data: userData, isPending } = getUser.useData(); // D365 User Info
|
|
30
|
+
* const { mutateAsync } = useSessionLogout();
|
|
31
|
+
*
|
|
32
|
+
*
|
|
33
|
+
* const invoicesResource = {
|
|
34
|
+
* name: "invoices",
|
|
35
|
+
* label: "Invoices",
|
|
36
|
+
* detailsFields: ["Code", "AccountName", "Total", "Status"],
|
|
37
|
+
* rowsQueryFn: getInvoices,
|
|
38
|
+
* configQueryFn: getInvoicesTable,
|
|
39
|
+
* idField: "Code",
|
|
40
|
+
* dataMaskHandlers,
|
|
41
|
+
* columnRenderHandlers: fieldRenderMap,
|
|
42
|
+
* filterRenderHandlers: filterRenderHandlers,
|
|
43
|
+
* };
|
|
44
|
+
*
|
|
45
|
+
* const resources = [
|
|
46
|
+
* invoicesResource,
|
|
47
|
+
* // DEFINE MORE RESOURCES HERE
|
|
48
|
+
* ];
|
|
49
|
+
*
|
|
50
|
+
* return (
|
|
51
|
+
* <Container>
|
|
52
|
+
* <Portal session={authObject} logout={handleLogout}>
|
|
53
|
+
* <Portal.Table resources={resources} />
|
|
54
|
+
* </Portal>
|
|
55
|
+
* </Container>
|
|
56
|
+
* )
|
|
57
|
+
*};
|
|
58
|
+
* ```
|
|
59
|
+
* @module e4 Portal
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
export type { Session } from "./auth/auth-context";
|
|
63
|
+
export { Portal, type PortalProps } from "./portal";
|
|
64
|
+
|
|
65
|
+
export { Table } from "./features/table";
|
package/src/portal.tsx
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { FlexBox } from "@evenicanpm/ui";
|
|
2
|
+
import type { PropsWithChildren } from "react";
|
|
3
|
+
import {
|
|
4
|
+
type AuthProviderProps,
|
|
5
|
+
PortalAuthProvider,
|
|
6
|
+
} from "./auth/auth-context";
|
|
7
|
+
import { TableDashboard } from "./features/table/components/dashboard/table-dashboard";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Main Entry point properties into portal package
|
|
11
|
+
*
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
interface PortalProps extends AuthProviderProps {
|
|
15
|
+
// Add Portal Specific Properties Here
|
|
16
|
+
// ie. roles
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The main **e4Portal** entry point.
|
|
21
|
+
* * This is a React Functional Component that provides the core context
|
|
22
|
+
* and layout for the application. It is required to wrap all components
|
|
23
|
+
* that use the library's hooks or sub-components.
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
|
+
* @param props - The properties passed to the Portal component.
|
|
27
|
+
* @returns A React Element rendering the main application structure.
|
|
28
|
+
*/
|
|
29
|
+
const Portal = ({
|
|
30
|
+
session,
|
|
31
|
+
logout,
|
|
32
|
+
children,
|
|
33
|
+
}: PropsWithChildren<PortalProps>) => {
|
|
34
|
+
// Not Logged In
|
|
35
|
+
if (!session?.email) {
|
|
36
|
+
return (
|
|
37
|
+
<FlexBox mt={5} width="100%" justifyContent="center">
|
|
38
|
+
Please login to view the portal.
|
|
39
|
+
</FlexBox>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Logged In yes
|
|
44
|
+
return (
|
|
45
|
+
<PortalAuthProvider session={session} logout={logout}>
|
|
46
|
+
{children}
|
|
47
|
+
</PortalAuthProvider>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* # Feature: Table
|
|
54
|
+
* This is the table feature component.
|
|
55
|
+
* @params props
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
Portal.Table = TableDashboard;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
*
|
|
62
|
+
* # Feature: Settings
|
|
63
|
+
* This is the table feature component.
|
|
64
|
+
* @params props
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
export { Portal, type PortalProps };
|