@hitachivantara/uikit-cli 6.0.1

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.
Files changed (109) hide show
  1. package/README.md +46 -0
  2. package/package.json +68 -0
  3. package/src/app-shell.js +106 -0
  4. package/src/baselines/app-shell/vite/_gitignore +30 -0
  5. package/src/baselines/app-shell/vite/_oxlintrc.json +5 -0
  6. package/src/baselines/app-shell/vite/_package.json +55 -0
  7. package/src/baselines/app-shell/vite/public/locales/en/example.json +8 -0
  8. package/src/baselines/app-shell/vite/src/lib/data/config.ts +15 -0
  9. package/src/baselines/app-shell/vite/src/lib/i18n.ts +44 -0
  10. package/src/baselines/app-shell/vite/src/pages/Example/index.tsx +25 -0
  11. package/src/baselines/app-shell/vite/src/providers/Provider.tsx +31 -0
  12. package/src/baselines/app-shell/vite/src/tests/mocks.ts +1 -0
  13. package/src/baselines/app-shell/vite/src/tests/providers.tsx +13 -0
  14. package/src/baselines/app-shell/vite/src/tests/setupTests.ts +24 -0
  15. package/src/baselines/app-shell/vite/src/types/theme.d.ts +8 -0
  16. package/src/baselines/app-shell/vite/src/types/vite-env.d.ts +1 -0
  17. package/src/baselines/app-shell/vite/tsconfig.json +10 -0
  18. package/src/baselines/app-shell/vite/tsconfig.node.json +9 -0
  19. package/src/baselines/app-shell/vite/uno.config.ts +6 -0
  20. package/src/baselines/app-shell/vite/vite.config.ts +45 -0
  21. package/src/baselines/vite/_gitignore +30 -0
  22. package/src/baselines/vite/_oxlintrc.json +5 -0
  23. package/src/baselines/vite/_package.json +53 -0
  24. package/src/baselines/vite/index.html +18 -0
  25. package/src/baselines/vite/public/favicon.ico +0 -0
  26. package/src/baselines/vite/public/locales/en/common.json +16 -0
  27. package/src/baselines/vite/public/locales/en/home.json +4 -0
  28. package/src/baselines/vite/public/logo192.png +0 -0
  29. package/src/baselines/vite/src/App.tsx +31 -0
  30. package/src/baselines/vite/src/assets/HitachiLogo.tsx +27 -0
  31. package/src/baselines/vite/src/components/common/Loading/Loading.test.tsx +18 -0
  32. package/src/baselines/vite/src/components/common/Loading/Loading.tsx +15 -0
  33. package/src/baselines/vite/src/components/common/Loading/index.ts +1 -0
  34. package/src/baselines/vite/src/context/NavigationContext.tsx +67 -0
  35. package/src/baselines/vite/src/lib/i18n.ts +29 -0
  36. package/src/baselines/vite/src/main.tsx +12 -0
  37. package/src/baselines/vite/src/pages/Home/index.tsx +13 -0
  38. package/src/baselines/vite/src/pages/NotFound/NotFound.tsx +39 -0
  39. package/src/baselines/vite/src/pages/NotFound/index.tsx +1 -0
  40. package/src/baselines/vite/src/pages/layout/navigation.tsx +82 -0
  41. package/src/baselines/vite/src/routes.tsx +14 -0
  42. package/src/baselines/vite/src/tests/mocks.ts +1 -0
  43. package/src/baselines/vite/src/tests/providers.tsx +13 -0
  44. package/src/baselines/vite/src/tests/setupTests.ts +24 -0
  45. package/src/baselines/vite/src/types/theme.d.ts +8 -0
  46. package/src/baselines/vite/src/vite-env.d.ts +1 -0
  47. package/src/baselines/vite/tsconfig.json +10 -0
  48. package/src/baselines/vite/tsconfig.node.json +9 -0
  49. package/src/baselines/vite/uno.config.ts +6 -0
  50. package/src/baselines/vite/vite.config.ts +31 -0
  51. package/src/contents.js +63 -0
  52. package/src/create.js +172 -0
  53. package/src/index.js +22 -0
  54. package/src/navigation.js +21 -0
  55. package/src/package.js +37 -0
  56. package/src/plop-templates/README.md.hbs +10 -0
  57. package/src/plop-templates/app-shell/app-shell.config.ts.hbs +54 -0
  58. package/src/plop-templates/app-shell/index.html.hbs +15 -0
  59. package/src/plopfile.js +61 -0
  60. package/src/templates/AssetInventory/CardView.tsx +167 -0
  61. package/src/templates/AssetInventory/ListView.tsx +56 -0
  62. package/src/templates/AssetInventory/data.tsx +255 -0
  63. package/src/templates/AssetInventory/index.tsx +198 -0
  64. package/src/templates/AssetInventory/usePaginationData.ts +158 -0
  65. package/src/templates/Canvas/Context.tsx +49 -0
  66. package/src/templates/Canvas/ListView.tsx +189 -0
  67. package/src/templates/Canvas/Node.tsx +203 -0
  68. package/src/templates/Canvas/Sidebar.tsx +51 -0
  69. package/src/templates/Canvas/StatusEdge.tsx +75 -0
  70. package/src/templates/Canvas/StickyNode.tsx +475 -0
  71. package/src/templates/Canvas/Table.tsx +202 -0
  72. package/src/templates/Canvas/TreeView.tsx +211 -0
  73. package/src/templates/Canvas/dependencies.json +7 -0
  74. package/src/templates/Canvas/index.tsx +363 -0
  75. package/src/templates/Canvas/styles.tsx +41 -0
  76. package/src/templates/Canvas/utils.tsx +70 -0
  77. package/src/templates/Dashboard/GridPanel.tsx +33 -0
  78. package/src/templates/Dashboard/Kpi.tsx +107 -0
  79. package/src/templates/Dashboard/Map.styles.ts +681 -0
  80. package/src/templates/Dashboard/Map.tsx +71 -0
  81. package/src/templates/Dashboard/data.ts +67 -0
  82. package/src/templates/Dashboard/dependencies.json +11 -0
  83. package/src/templates/Dashboard/index.tsx +173 -0
  84. package/src/templates/DetailsView/KPIs.tsx +70 -0
  85. package/src/templates/DetailsView/MetadataItem.tsx +35 -0
  86. package/src/templates/DetailsView/Properties.tsx +127 -0
  87. package/src/templates/DetailsView/Table.tsx +104 -0
  88. package/src/templates/DetailsView/data.ts +67 -0
  89. package/src/templates/DetailsView/index.tsx +102 -0
  90. package/src/templates/DetailsView/usePaginationData.ts +155 -0
  91. package/src/templates/DetailsView/utils.ts +51 -0
  92. package/src/templates/Form/index.tsx +107 -0
  93. package/src/templates/KanbanBoard/ColumnContainer.tsx +89 -0
  94. package/src/templates/KanbanBoard/TaskCard.tsx +130 -0
  95. package/src/templates/KanbanBoard/data.tsx +140 -0
  96. package/src/templates/KanbanBoard/dependencies.json +6 -0
  97. package/src/templates/KanbanBoard/index.tsx +179 -0
  98. package/src/templates/KanbanBoard/styles.tsx +76 -0
  99. package/src/templates/KanbanBoard/types.ts +21 -0
  100. package/src/templates/ListView/Indicator.tsx +42 -0
  101. package/src/templates/ListView/Kpi.tsx +120 -0
  102. package/src/templates/ListView/Table.tsx +55 -0
  103. package/src/templates/ListView/data.tsx +179 -0
  104. package/src/templates/ListView/dependencies.json +5 -0
  105. package/src/templates/ListView/index.tsx +245 -0
  106. package/src/templates/ListView/usePaginationData.ts +158 -0
  107. package/src/templates/Welcome/index.tsx +101 -0
  108. package/src/templates/package.json +30 -0
  109. package/src/utils.js +37 -0
@@ -0,0 +1,179 @@
1
+ import useSWR from "swr";
2
+ import {
3
+ HvBulkActionsProps,
4
+ HvColor,
5
+ HvTableColumnConfig,
6
+ HvTooltip,
7
+ } from "@hitachivantara/uikit-react-core";
8
+ import {
9
+ IconType,
10
+ Level0Good,
11
+ Level1,
12
+ Level2Average,
13
+ Level3Bad,
14
+ Refresh,
15
+ } from "@hitachivantara/uikit-react-icons";
16
+
17
+ import {
18
+ DataObject,
19
+ delay,
20
+ ServerPaginationProps,
21
+ useServerPagination,
22
+ } from "./usePaginationData";
23
+
24
+ // --- Table data utils ---
25
+
26
+ export interface ListViewEntry extends DataObject {
27
+ id?: string;
28
+ name?: string;
29
+ description?: string;
30
+ serverId?: number;
31
+ created?: string;
32
+ build?: string;
33
+ status?: number;
34
+ }
35
+
36
+ const TooltipIcon = ({
37
+ title,
38
+ Icon,
39
+ color,
40
+ }: {
41
+ title: string;
42
+ Icon: IconType;
43
+ color: HvColor;
44
+ }) => (
45
+ <HvTooltip title={title}>
46
+ <Icon iconSize="XS" color={color} />
47
+ </HvTooltip>
48
+ );
49
+
50
+ export const getStatusIcon = (status?: ListViewEntry["status"]) => {
51
+ switch (status) {
52
+ case 0:
53
+ return <TooltipIcon title="Success" Icon={Level0Good} color="positive" />;
54
+ case 1:
55
+ return <TooltipIcon title="Error" Icon={Level3Bad} color="negative" />;
56
+ case 2:
57
+ return <TooltipIcon title="Open" Icon={Level2Average} color="warning" />;
58
+ default:
59
+ return <TooltipIcon title="Unassigned" Icon={Level1} color="info" />;
60
+ }
61
+ };
62
+
63
+ export const getColumns = (): HvTableColumnConfig<ListViewEntry, string>[] => [
64
+ {
65
+ Header: "Status",
66
+ accessor: "status",
67
+ style: { width: 40 },
68
+ Cell: ({ value }: { value: any }) => getStatusIcon(value),
69
+ },
70
+ { Header: "Name", accessor: "name", style: { minWidth: 200 } },
71
+ { Header: "Description", accessor: "description", style: { minWidth: 200 } },
72
+ { Header: "Server ID", accessor: "serverId", style: { width: 120 } },
73
+ { Header: "Created", accessor: "created" },
74
+ { Header: "Build", accessor: "build", style: { width: 120 } },
75
+ ];
76
+
77
+ export const actions: HvBulkActionsProps["actions"] = [
78
+ { id: "refresh", label: "Refresh", icon: <Refresh /> },
79
+ ];
80
+
81
+ const entries = [
82
+ { name: "Previous", description: "Clean Data Logs" },
83
+ { name: "Home", description: "Review Log" },
84
+ { name: "Carriage", description: "Deploy Cloud Run" },
85
+ { name: "Black", description: "Clean Session" },
86
+ { name: "Forward", description: "Update Build" },
87
+ ];
88
+
89
+ const getDate = (i: number): string => {
90
+ return new Date(2018, 4, i * 3).toISOString().slice(0, 10);
91
+ };
92
+
93
+ const getServerID = (i: number): number => Math.floor(100000000 + 17 * i);
94
+
95
+ const getOption = <T,>(opts: T[], i: number) => opts[i % opts.length];
96
+
97
+ export const createEntry = (i: number): ListViewEntry => {
98
+ const entry = getOption(entries, i);
99
+ const serverId = getServerID(i);
100
+
101
+ return {
102
+ id: `${i + 1}`,
103
+ name: entry.name,
104
+ description: entry.description,
105
+ serverId,
106
+ created: getDate(i),
107
+ build: btoa(String(serverId)).slice(5),
108
+ status: i % 4,
109
+ };
110
+ };
111
+
112
+ // --- Trend data utils ---
113
+
114
+ export type TrendData = (string | number)[][];
115
+
116
+ export const getTrendData = (variation: string): TrendData => {
117
+ if (variation === "up") {
118
+ return [
119
+ ["Count", "Requests"],
120
+ ["1", 265],
121
+ ["2", 734],
122
+ ["3", 1420],
123
+ ["4", 2780],
124
+ ];
125
+ }
126
+
127
+ return [
128
+ ["Count", "Requests"],
129
+ ["1", 2780],
130
+ ["2", 1420],
131
+ ["3", 734],
132
+ ["4", 265],
133
+ ];
134
+ };
135
+
136
+ // --- Data & Endpoints ---
137
+ const db = [...Array(20).keys()].map(createEntry);
138
+
139
+ const countByStatus = (status: number) =>
140
+ db.filter((entry) => entry.status === status).length || 0;
141
+
142
+ const requestsSummary = {
143
+ success: {
144
+ count: countByStatus(0),
145
+ data: getTrendData("up"),
146
+ variation: "up",
147
+ },
148
+ error: {
149
+ count: countByStatus(1),
150
+ data: getTrendData("down"),
151
+ variation: "down",
152
+ },
153
+ open: {
154
+ count: countByStatus(2),
155
+ data: getTrendData("down"),
156
+ variation: "down",
157
+ },
158
+ unassign: {
159
+ count: countByStatus(3),
160
+ data: getTrendData("up"),
161
+ variation: "up",
162
+ },
163
+ };
164
+
165
+ export interface PaginationDataProps
166
+ extends Omit<ServerPaginationProps<ListViewEntry>, "endpoint" | "db"> {}
167
+
168
+ export const usePaginationData = (props: PaginationDataProps) => {
169
+ return useServerPagination({ endpoint: "/requests", db, ...props });
170
+ };
171
+
172
+ export const useSummaryData = () => {
173
+ return useSWR("/requests/summary", async () => {
174
+ // Loading
175
+ await delay(800);
176
+
177
+ return requestsSummary;
178
+ });
179
+ };
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "react-google-charts": "^4.0.0"
4
+ }
5
+ }
@@ -0,0 +1,245 @@
1
+ import { useEffect, useId, useMemo, useState } from "react";
2
+ import { css } from "@emotion/css";
3
+ import {
4
+ HvActionsGenericProps,
5
+ HvBulkActions,
6
+ HvButton,
7
+ HvControls,
8
+ HvGlobalActions,
9
+ HvGrid,
10
+ HvGridProps,
11
+ HvLeftControl,
12
+ HvLeftControlProps,
13
+ HvLoadingContainer,
14
+ HvPagination,
15
+ HvRightControl,
16
+ theme,
17
+ useHvBulkActions,
18
+ useHvData,
19
+ useHvFilters,
20
+ useHvGlobalFilter,
21
+ useHvPagination,
22
+ useHvRowSelection,
23
+ useHvSortBy,
24
+ } from "@hitachivantara/uikit-react-core";
25
+
26
+ import {
27
+ actions,
28
+ getColumns,
29
+ ListViewEntry,
30
+ PaginationDataProps,
31
+ usePaginationData,
32
+ useSummaryData,
33
+ } from "./data";
34
+ import { Kpi } from "./Kpi";
35
+ import { Table } from "./Table";
36
+
37
+ const classes = {
38
+ paddingTop: css({
39
+ paddingTop: theme.space.md,
40
+ }),
41
+ marginTop: css({
42
+ marginTop: theme.space.md,
43
+ }),
44
+ };
45
+
46
+ const INIT_PAGE_SIZE = 5;
47
+
48
+ const ListView = () => {
49
+ const breakpoints: HvGridProps = { xl: 3, lg: 3, md: 3, sm: 6, xs: 12 };
50
+ const listId = useId();
51
+
52
+ const [kpiSelection, setKpiSelection] = useState<number | undefined>();
53
+
54
+ const [params, setParams] = useState<PaginationDataProps>({
55
+ limit: INIT_PAGE_SIZE,
56
+ skip: 0,
57
+ });
58
+
59
+ const {
60
+ data: { pages, data },
61
+ loading,
62
+ } = usePaginationData(params);
63
+
64
+ const { data: indicatorData, isLoading: indicatorLoading } = useSummaryData();
65
+
66
+ const columns = useMemo(() => getColumns(), []);
67
+
68
+ const instance = useHvData<ListViewEntry, string>(
69
+ {
70
+ data,
71
+ columns,
72
+ manualPagination: true,
73
+ autoResetPage: false,
74
+ manualFilters: true,
75
+ autoResetFilters: true,
76
+ pageCount: pages,
77
+ initialState: { pageSize: INIT_PAGE_SIZE },
78
+ },
79
+ useHvGlobalFilter,
80
+ useHvFilters,
81
+ useHvSortBy,
82
+ useHvPagination,
83
+ useHvRowSelection,
84
+ useHvBulkActions,
85
+ );
86
+
87
+ useEffect(() => {
88
+ const { pageSize = INIT_PAGE_SIZE, pageIndex = 0 } = instance.state;
89
+
90
+ setParams((prev) => ({
91
+ ...prev,
92
+ limit: pageSize,
93
+ skip: pageSize * pageIndex,
94
+ }));
95
+ }, [instance.state]);
96
+
97
+ useEffect(() => {
98
+ instance.gotoPage?.(0);
99
+ setParams((prev) => ({
100
+ ...prev,
101
+ skip: 0,
102
+ filter:
103
+ instance.state.filters && instance.state.filters?.length > 0
104
+ ? instance.state.filters[0]
105
+ : undefined,
106
+ }));
107
+ }, [instance, instance.state.filters]);
108
+
109
+ const bulkActionProps = instance.getHvBulkActionsProps?.();
110
+
111
+ const handleAction: HvActionsGenericProps["onAction"] = (event, action) => {
112
+ if (action.id === "refresh") {
113
+ instance.gotoPage?.(0);
114
+ setKpiSelection(undefined);
115
+ setParams((prev) => ({
116
+ ...prev,
117
+ skip: 0,
118
+ filter: undefined,
119
+ }));
120
+ }
121
+ };
122
+
123
+ const handleSearch: HvLeftControlProps["onSearch"] = (e, value) => {
124
+ instance.gotoPage?.(0);
125
+ setParams((prev) => ({
126
+ ...prev,
127
+ skip: 0,
128
+ search: value,
129
+ }));
130
+ };
131
+
132
+ return (
133
+ <>
134
+ <HvGlobalActions title="Requests" backButton={false}>
135
+ <HvButton variant="primary">Request Server</HvButton>
136
+ </HvGlobalActions>
137
+
138
+ <HvGrid container className={classes.paddingTop}>
139
+ <HvGrid item {...breakpoints}>
140
+ <Kpi
141
+ title="Success Requests"
142
+ color="positive"
143
+ status={0}
144
+ instance={instance}
145
+ kpiSelection={kpiSelection}
146
+ setKpiSelection={setKpiSelection}
147
+ loading={indicatorLoading}
148
+ count={indicatorData?.success.count}
149
+ variation={indicatorData?.success.variation}
150
+ trendData={indicatorData?.success.data}
151
+ />
152
+ </HvGrid>
153
+ <HvGrid item {...breakpoints}>
154
+ <Kpi
155
+ title="Error Requests"
156
+ color="negative"
157
+ status={1}
158
+ instance={instance}
159
+ kpiSelection={kpiSelection}
160
+ setKpiSelection={setKpiSelection}
161
+ loading={indicatorLoading}
162
+ count={indicatorData?.error.count}
163
+ variation={indicatorData?.error.variation}
164
+ trendData={indicatorData?.error.data}
165
+ />
166
+ </HvGrid>
167
+ <HvGrid item {...breakpoints}>
168
+ <Kpi
169
+ title="Open Requests"
170
+ color="warning"
171
+ status={2}
172
+ instance={instance}
173
+ kpiSelection={kpiSelection}
174
+ setKpiSelection={setKpiSelection}
175
+ loading={indicatorLoading}
176
+ count={indicatorData?.open.count}
177
+ variation={indicatorData?.open.variation}
178
+ trendData={indicatorData?.open.data}
179
+ />
180
+ </HvGrid>
181
+ <HvGrid item {...breakpoints}>
182
+ <Kpi
183
+ title="Unassigned Requests"
184
+ color="info"
185
+ status={3}
186
+ instance={instance}
187
+ kpiSelection={kpiSelection}
188
+ setKpiSelection={setKpiSelection}
189
+ loading={indicatorLoading}
190
+ count={indicatorData?.unassign.count}
191
+ variation={indicatorData?.unassign.variation}
192
+ trendData={indicatorData?.unassign.data}
193
+ />
194
+ </HvGrid>
195
+ </HvGrid>
196
+
197
+ <HvControls
198
+ className={classes.paddingTop}
199
+ defaultView="card"
200
+ callbacks={instance}
201
+ >
202
+ <HvLeftControl
203
+ placeholder="Search"
204
+ onSearch={handleSearch}
205
+ searchProps={{
206
+ inputProps: {
207
+ "aria-label": "Search",
208
+ "aria-controls": listId,
209
+ },
210
+ }}
211
+ />
212
+ <HvRightControl hideSortBy />
213
+ </HvControls>
214
+
215
+ <HvBulkActions
216
+ className={classes.marginTop}
217
+ {...bulkActionProps}
218
+ numTotal={data.length}
219
+ numSelected={instance.selectedFlatRows.length}
220
+ maxVisibleActions={2}
221
+ onSelectAll={() => bulkActionProps?.onSelectAll()}
222
+ onSelectAllPages={() => bulkActionProps?.onSelectAllPages()}
223
+ actions={actions}
224
+ actionsDisabled={false}
225
+ onAction={handleAction}
226
+ checkboxProps={{
227
+ "aria-controls": listId,
228
+ }}
229
+ />
230
+
231
+ <HvLoadingContainer hidden={!loading}>
232
+ <div className={classes.marginTop}>
233
+ <Table instance={instance} id={listId} />
234
+ {instance.page?.length > 1 && (
235
+ <HvPagination {...instance.getHvPaginationProps?.()} />
236
+ )}
237
+ </div>
238
+ </HvLoadingContainer>
239
+ </>
240
+ );
241
+ };
242
+
243
+ export { ListView as Component };
244
+
245
+ export default ListView;
@@ -0,0 +1,158 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import useSWR from "swr";
3
+
4
+ // --- Types ---
5
+
6
+ export type DataObject = Record<string, string | number | undefined>;
7
+
8
+ export interface ServerPaginationProps<T extends DataObject = DataObject> {
9
+ endpoint: string;
10
+ db: T[];
11
+ limit: number;
12
+ skip: number;
13
+ sort?: string;
14
+ order?: "desc" | "asc";
15
+ filter?: { id: string; value: string | number };
16
+ search?: string;
17
+ }
18
+
19
+ export interface PaginationData<T extends DataObject = DataObject> {
20
+ data: T[];
21
+ total: number;
22
+ pages: number;
23
+ }
24
+
25
+ // --- Utils ---
26
+
27
+ export const delay = (ms = 500) =>
28
+ new Promise((resolve) => {
29
+ setTimeout(() => resolve("Time passed"), ms);
30
+ });
31
+
32
+ const searchObj = (entry: DataObject, search: string) => {
33
+ return Object.keys(entry)
34
+ .filter((key) => key !== "id" && key !== "statusColor")
35
+ .find(
36
+ (key) =>
37
+ entry[key]?.toString().toLowerCase().search(search.toLowerCase()) !==
38
+ -1,
39
+ )?.length;
40
+ };
41
+
42
+ // --- Pagination hook ---
43
+
44
+ export function useServerPagination<T extends DataObject = DataObject>({
45
+ endpoint,
46
+ db,
47
+ limit,
48
+ skip,
49
+ sort,
50
+ order = "desc",
51
+ filter,
52
+ search,
53
+ }: ServerPaginationProps<T>) {
54
+ const initialState: PaginationData<T> = {
55
+ data: [],
56
+ pages: 0,
57
+ total: 0,
58
+ };
59
+ const [currData, setCurrData] = useState(initialState);
60
+ const [deleting, setDeleting] = useState(false);
61
+ const [allData, setAllData] = useState<T[]>(db);
62
+
63
+ const fetcher = useCallback(async () => {
64
+ // Loading
65
+ await delay(800);
66
+
67
+ const items =
68
+ search || filter
69
+ ? allData.filter((entry) => {
70
+ let keep = true;
71
+
72
+ if (search) {
73
+ keep = !!searchObj(
74
+ entry as Record<string, string | number>,
75
+ search,
76
+ );
77
+ }
78
+ if (filter && keep) {
79
+ keep =
80
+ entry[filter.id]?.toString().toLowerCase() ===
81
+ filter.value.toString().toLowerCase();
82
+ }
83
+
84
+ return keep;
85
+ })
86
+ : [...allData];
87
+
88
+ return {
89
+ data: items
90
+ .sort(
91
+ sort
92
+ ? (a, b) => {
93
+ return order === "desc"
94
+ ? (b[sort] || "")
95
+ .toString()
96
+ .localeCompare((a[sort] || "").toString(), undefined, {
97
+ numeric: true,
98
+ sensitivity: "base",
99
+ })
100
+ : (a[sort] || "")
101
+ .toString()
102
+ .localeCompare((b[sort] || "").toString(), undefined, {
103
+ numeric: true,
104
+ sensitivity: "base",
105
+ });
106
+ }
107
+ : undefined,
108
+ )
109
+ .slice(skip, skip + limit),
110
+ total: items.length,
111
+ pages: Math.ceil(items.length / limit),
112
+ };
113
+ }, [allData, filter, limit, order, search, skip, sort]);
114
+
115
+ const { data, isLoading, mutate } = useSWR<PaginationData<T>>(() => {
116
+ const params = new URLSearchParams({
117
+ skip: skip.toString(),
118
+ limit: limit.toString(),
119
+ ...(sort && { sort, order }),
120
+ ...(search && { search }),
121
+ ...(filter && { [filter.id]: filter.value }),
122
+ });
123
+
124
+ return `${endpoint}?${params.toString()}`;
125
+ }, fetcher);
126
+
127
+ // Prevents data from updating to undefined when loading (this crashes useHvData)
128
+ useEffect(() => {
129
+ if (!isLoading && data) {
130
+ setCurrData(data);
131
+ }
132
+ }, [isLoading, data]);
133
+
134
+ const deleteEntries = useCallback(
135
+ async (ids: string[]) => {
136
+ setDeleting(true);
137
+
138
+ setAllData((prev) =>
139
+ prev.filter((entry: any) => entry.id && !ids.includes(entry.id)),
140
+ );
141
+
142
+ const refreshedData = await fetcher();
143
+
144
+ mutate(refreshedData);
145
+
146
+ await delay(800);
147
+
148
+ setDeleting(false);
149
+ },
150
+ [fetcher, mutate],
151
+ );
152
+
153
+ return {
154
+ deleteEntries,
155
+ data: currData,
156
+ loading: isLoading || deleting,
157
+ };
158
+ }
@@ -0,0 +1,101 @@
1
+ import { css } from "@emotion/css";
2
+ import {
3
+ HvGrid,
4
+ HvInput,
5
+ HvTypography,
6
+ theme,
7
+ } from "@hitachivantara/uikit-react-core";
8
+ import { Heart, Palette } from "@hitachivantara/uikit-react-icons";
9
+
10
+ const classes = {
11
+ root: css({
12
+ height: "100%",
13
+ padding: theme.space.xl,
14
+ background: `linear-gradient(70deg, ${theme.colors.bgPage} 55%, transparent 55%), linear-gradient(180deg, ${theme.colors.primary}, #000)`,
15
+ }),
16
+ glossaryContainer: css({
17
+ margin: theme.spacing("sm", 0),
18
+ display: "flex",
19
+ flexDirection: "column",
20
+ gap: theme.space.xs,
21
+ }),
22
+ imageContainer: css({
23
+ display: "flex",
24
+ alignItems: "center",
25
+
26
+ img: { maxHeight: "450px" },
27
+ }),
28
+ };
29
+
30
+ const Welcome = () => {
31
+ return (
32
+ <div className={classes.root}>
33
+ <HvGrid container>
34
+ <HvGrid item xs={6}>
35
+ <HvGrid container>
36
+ <HvGrid item xs={8}>
37
+ <HvTypography variant="title1">
38
+ Welcome to the NEXT UI Kit
39
+ </HvTypography>
40
+ </HvGrid>
41
+ <HvGrid item xs={8}>
42
+ <HvTypography variant="label">
43
+ The NEXT UI Kit is a composable and accessible component library
44
+ that gives you the foundation to build your NEXT application
45
+ faster and consistently.
46
+ </HvTypography>
47
+ </HvGrid>
48
+ <HvGrid item xs={8}>
49
+ <HvInput type="search" placeholder="What are you looking for?" />
50
+ </HvGrid>
51
+ <HvGrid item xs={6}>
52
+ <div className={classes.glossaryContainer}>
53
+ <Palette iconSize="M" />
54
+ <HvTypography variant="title4" component="p">
55
+ Themeable
56
+ </HvTypography>
57
+ <HvTypography>
58
+ Use available Design System or customize it to match your
59
+ design needs.
60
+ </HvTypography>
61
+ </div>
62
+ </HvGrid>
63
+ <HvGrid item xs={6}>
64
+ <div className={classes.glossaryContainer}>
65
+ <Heart iconSize="M" />
66
+ <HvTypography variant="title4" component="p">
67
+ Community
68
+ </HvTypography>
69
+ <HvTypography>
70
+ We welcome all feedback in order to produce the best
71
+ experience for our users.
72
+ </HvTypography>
73
+ </div>
74
+ </HvGrid>
75
+ </HvGrid>
76
+ </HvGrid>
77
+ <HvGrid item xs={6} display="flex">
78
+ <div className={classes.imageContainer}>
79
+ <img
80
+ alt="Monitor showing a dashboard built with UI Kit components"
81
+ src="https://lumada-design.github.io/assets/template-preview.webp"
82
+ />
83
+ </div>
84
+ </HvGrid>
85
+ <HvGrid item xs={12}>
86
+ <HvTypography
87
+ link
88
+ component="a"
89
+ href="https://pentaho.github.io/uikit-docs/master/"
90
+ >
91
+ More details
92
+ </HvTypography>
93
+ </HvGrid>
94
+ </HvGrid>
95
+ </div>
96
+ );
97
+ };
98
+
99
+ export { Welcome as Component };
100
+
101
+ export default Welcome;