@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.
- package/README.md +46 -0
- package/package.json +68 -0
- package/src/app-shell.js +106 -0
- package/src/baselines/app-shell/vite/_gitignore +30 -0
- package/src/baselines/app-shell/vite/_oxlintrc.json +5 -0
- package/src/baselines/app-shell/vite/_package.json +55 -0
- package/src/baselines/app-shell/vite/public/locales/en/example.json +8 -0
- package/src/baselines/app-shell/vite/src/lib/data/config.ts +15 -0
- package/src/baselines/app-shell/vite/src/lib/i18n.ts +44 -0
- package/src/baselines/app-shell/vite/src/pages/Example/index.tsx +25 -0
- package/src/baselines/app-shell/vite/src/providers/Provider.tsx +31 -0
- package/src/baselines/app-shell/vite/src/tests/mocks.ts +1 -0
- package/src/baselines/app-shell/vite/src/tests/providers.tsx +13 -0
- package/src/baselines/app-shell/vite/src/tests/setupTests.ts +24 -0
- package/src/baselines/app-shell/vite/src/types/theme.d.ts +8 -0
- package/src/baselines/app-shell/vite/src/types/vite-env.d.ts +1 -0
- package/src/baselines/app-shell/vite/tsconfig.json +10 -0
- package/src/baselines/app-shell/vite/tsconfig.node.json +9 -0
- package/src/baselines/app-shell/vite/uno.config.ts +6 -0
- package/src/baselines/app-shell/vite/vite.config.ts +45 -0
- package/src/baselines/vite/_gitignore +30 -0
- package/src/baselines/vite/_oxlintrc.json +5 -0
- package/src/baselines/vite/_package.json +53 -0
- package/src/baselines/vite/index.html +18 -0
- package/src/baselines/vite/public/favicon.ico +0 -0
- package/src/baselines/vite/public/locales/en/common.json +16 -0
- package/src/baselines/vite/public/locales/en/home.json +4 -0
- package/src/baselines/vite/public/logo192.png +0 -0
- package/src/baselines/vite/src/App.tsx +31 -0
- package/src/baselines/vite/src/assets/HitachiLogo.tsx +27 -0
- package/src/baselines/vite/src/components/common/Loading/Loading.test.tsx +18 -0
- package/src/baselines/vite/src/components/common/Loading/Loading.tsx +15 -0
- package/src/baselines/vite/src/components/common/Loading/index.ts +1 -0
- package/src/baselines/vite/src/context/NavigationContext.tsx +67 -0
- package/src/baselines/vite/src/lib/i18n.ts +29 -0
- package/src/baselines/vite/src/main.tsx +12 -0
- package/src/baselines/vite/src/pages/Home/index.tsx +13 -0
- package/src/baselines/vite/src/pages/NotFound/NotFound.tsx +39 -0
- package/src/baselines/vite/src/pages/NotFound/index.tsx +1 -0
- package/src/baselines/vite/src/pages/layout/navigation.tsx +82 -0
- package/src/baselines/vite/src/routes.tsx +14 -0
- package/src/baselines/vite/src/tests/mocks.ts +1 -0
- package/src/baselines/vite/src/tests/providers.tsx +13 -0
- package/src/baselines/vite/src/tests/setupTests.ts +24 -0
- package/src/baselines/vite/src/types/theme.d.ts +8 -0
- package/src/baselines/vite/src/vite-env.d.ts +1 -0
- package/src/baselines/vite/tsconfig.json +10 -0
- package/src/baselines/vite/tsconfig.node.json +9 -0
- package/src/baselines/vite/uno.config.ts +6 -0
- package/src/baselines/vite/vite.config.ts +31 -0
- package/src/contents.js +63 -0
- package/src/create.js +172 -0
- package/src/index.js +22 -0
- package/src/navigation.js +21 -0
- package/src/package.js +37 -0
- package/src/plop-templates/README.md.hbs +10 -0
- package/src/plop-templates/app-shell/app-shell.config.ts.hbs +54 -0
- package/src/plop-templates/app-shell/index.html.hbs +15 -0
- package/src/plopfile.js +61 -0
- package/src/templates/AssetInventory/CardView.tsx +167 -0
- package/src/templates/AssetInventory/ListView.tsx +56 -0
- package/src/templates/AssetInventory/data.tsx +255 -0
- package/src/templates/AssetInventory/index.tsx +198 -0
- package/src/templates/AssetInventory/usePaginationData.ts +158 -0
- package/src/templates/Canvas/Context.tsx +49 -0
- package/src/templates/Canvas/ListView.tsx +189 -0
- package/src/templates/Canvas/Node.tsx +203 -0
- package/src/templates/Canvas/Sidebar.tsx +51 -0
- package/src/templates/Canvas/StatusEdge.tsx +75 -0
- package/src/templates/Canvas/StickyNode.tsx +475 -0
- package/src/templates/Canvas/Table.tsx +202 -0
- package/src/templates/Canvas/TreeView.tsx +211 -0
- package/src/templates/Canvas/dependencies.json +7 -0
- package/src/templates/Canvas/index.tsx +363 -0
- package/src/templates/Canvas/styles.tsx +41 -0
- package/src/templates/Canvas/utils.tsx +70 -0
- package/src/templates/Dashboard/GridPanel.tsx +33 -0
- package/src/templates/Dashboard/Kpi.tsx +107 -0
- package/src/templates/Dashboard/Map.styles.ts +681 -0
- package/src/templates/Dashboard/Map.tsx +71 -0
- package/src/templates/Dashboard/data.ts +67 -0
- package/src/templates/Dashboard/dependencies.json +11 -0
- package/src/templates/Dashboard/index.tsx +173 -0
- package/src/templates/DetailsView/KPIs.tsx +70 -0
- package/src/templates/DetailsView/MetadataItem.tsx +35 -0
- package/src/templates/DetailsView/Properties.tsx +127 -0
- package/src/templates/DetailsView/Table.tsx +104 -0
- package/src/templates/DetailsView/data.ts +67 -0
- package/src/templates/DetailsView/index.tsx +102 -0
- package/src/templates/DetailsView/usePaginationData.ts +155 -0
- package/src/templates/DetailsView/utils.ts +51 -0
- package/src/templates/Form/index.tsx +107 -0
- package/src/templates/KanbanBoard/ColumnContainer.tsx +89 -0
- package/src/templates/KanbanBoard/TaskCard.tsx +130 -0
- package/src/templates/KanbanBoard/data.tsx +140 -0
- package/src/templates/KanbanBoard/dependencies.json +6 -0
- package/src/templates/KanbanBoard/index.tsx +179 -0
- package/src/templates/KanbanBoard/styles.tsx +76 -0
- package/src/templates/KanbanBoard/types.ts +21 -0
- package/src/templates/ListView/Indicator.tsx +42 -0
- package/src/templates/ListView/Kpi.tsx +120 -0
- package/src/templates/ListView/Table.tsx +55 -0
- package/src/templates/ListView/data.tsx +179 -0
- package/src/templates/ListView/dependencies.json +5 -0
- package/src/templates/ListView/index.tsx +245 -0
- package/src/templates/ListView/usePaginationData.ts +158 -0
- package/src/templates/Welcome/index.tsx +101 -0
- package/src/templates/package.json +30 -0
- 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,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;
|