@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,140 @@
1
+ import {
2
+ Copy,
3
+ Edit,
4
+ Magnifier,
5
+ Success,
6
+ } from "@hitachivantara/uikit-react-icons";
7
+
8
+ import { Column, Task } from "./types";
9
+
10
+ export const columns: Column[] = [
11
+ {
12
+ id: "col1",
13
+ title: "Draft",
14
+ color: "info",
15
+ icon: <Edit color="info" />,
16
+ },
17
+ {
18
+ id: "col2",
19
+ title: "To Review",
20
+ color: "negativeStrong",
21
+ icon: <Copy color="negativeStrong" />,
22
+ },
23
+ {
24
+ id: "col3",
25
+ title: "In Review",
26
+ color: "warningStrong",
27
+ icon: <Magnifier color="warningStrong" />,
28
+ },
29
+ {
30
+ id: "col4",
31
+ title: "Reviewed",
32
+ color: "positiveStrong",
33
+ icon: <Success color="positiveStrong" />,
34
+ },
35
+ ];
36
+
37
+ export const tasks: Task[] = [
38
+ {
39
+ id: "task1",
40
+ columnId: "col1",
41
+ title: "Task 1",
42
+ statusLevel: 1,
43
+ },
44
+ {
45
+ id: "task2",
46
+ columnId: "col1",
47
+ title: "Task 2",
48
+ statusLevel: 2,
49
+ },
50
+ {
51
+ id: "task3",
52
+ columnId: "col2",
53
+ title: "Task 3",
54
+ statusLevel: 3,
55
+ users: [
56
+ {
57
+ name: "Ben",
58
+ avatar: "https://i.imgur.com/56Eeg1g.png",
59
+ },
60
+ {
61
+ name: "Beatrice",
62
+ avatar: "https://i.imgur.com/bE7vg3N.png",
63
+ },
64
+ {
65
+ name: "Wayne",
66
+ avatar: "https://i.imgur.com/ea22egF.png",
67
+ },
68
+ ],
69
+ },
70
+ {
71
+ id: "task4",
72
+ columnId: "col2",
73
+ title: "Task 4",
74
+ statusLevel: 2,
75
+ },
76
+ {
77
+ id: "task5",
78
+ columnId: "col2",
79
+ title: "Task 5",
80
+ statusLevel: 4,
81
+ users: [
82
+ {
83
+ name: "Beatrice",
84
+ avatar: "https://i.imgur.com/bE7vg3N.png",
85
+ },
86
+ {
87
+ name: "Wayne",
88
+ avatar: "https://i.imgur.com/ea22egF.png",
89
+ },
90
+ ],
91
+ },
92
+ {
93
+ id: "task6",
94
+ columnId: "col3",
95
+ title: "Task 6",
96
+ statusLevel: 5,
97
+ users: [
98
+ {
99
+ name: "Ben",
100
+ avatar: "https://i.imgur.com/56Eeg1g.png",
101
+ },
102
+ {
103
+ name: "Beatrice",
104
+ avatar: "https://i.imgur.com/bE7vg3N.png",
105
+ },
106
+ {
107
+ name: "Wayne",
108
+ avatar: "https://i.imgur.com/ea22egF.png",
109
+ },
110
+ {
111
+ name: "Clara Soul",
112
+ avatar: "https://i.imgur.com/6sYhSb6.png",
113
+ },
114
+ ],
115
+ },
116
+ {
117
+ id: "task7",
118
+ columnId: "col4",
119
+ title: "Task 7",
120
+ statusLevel: 2,
121
+ users: [
122
+ {
123
+ name: "Ben",
124
+ avatar: "https://i.imgur.com/56Eeg1g.png",
125
+ },
126
+ ],
127
+ },
128
+ {
129
+ id: "task8",
130
+ columnId: "col4",
131
+ title: "Task 8",
132
+ statusLevel: 3,
133
+ },
134
+ {
135
+ id: "task9",
136
+ columnId: "col4",
137
+ title: "Task 9",
138
+ statusLevel: 3,
139
+ },
140
+ ];
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "@hitachivantara/uikit-react-lab": "latest",
4
+ "@hitachivantara/uikit-react-pentaho": "latest"
5
+ }
6
+ }
@@ -0,0 +1,179 @@
1
+ import { useMemo, useState } from "react";
2
+ import {
3
+ DndContext,
4
+ DragEndEvent,
5
+ DragOverEvent,
6
+ DragOverlay,
7
+ DragStartEvent,
8
+ PointerSensor,
9
+ useSensor,
10
+ useSensors,
11
+ } from "@dnd-kit/core";
12
+ import { arrayMove, SortableContext } from "@dnd-kit/sortable";
13
+
14
+ import { ColumnContainer } from "./ColumnContainer";
15
+ import { columns as defaultColumns, tasks as defaultTasks } from "./data";
16
+ import classes from "./styles";
17
+ import { TaskCard } from "./TaskCard";
18
+ import { Column, Task } from "./types";
19
+
20
+ const KanbanBoard = () => {
21
+ const sensors = useSensors(
22
+ useSensor(PointerSensor, {
23
+ activationConstraint: {
24
+ distance: 2,
25
+ },
26
+ }),
27
+ );
28
+
29
+ const [tasks, setTasks] = useState<Task[]>(defaultTasks);
30
+ const [columns, setColumns] = useState<Column[]>(defaultColumns);
31
+ const [activeColumn, setActiveColumn] = useState<Column | null>(null);
32
+ const [activeTask, setActiveTask] = useState<Task | null>(null);
33
+ const [creatingTask, setCreatingTask] = useState<boolean>(false);
34
+
35
+ const columnsId = useMemo(() => columns.map((col) => col.id), [columns]);
36
+
37
+ const onDragStart = (event: DragStartEvent) => {
38
+ if (event.active.data.current?.type === "Column") {
39
+ setActiveColumn(event.active.data.current.column);
40
+ }
41
+
42
+ if (event.active.data.current?.type === "Task") {
43
+ setActiveTask(event.active.data.current.task);
44
+ }
45
+ };
46
+
47
+ const onDragEnd = (event: DragEndEvent) => {
48
+ setActiveColumn(null);
49
+ setActiveTask(null);
50
+
51
+ const { active, over } = event;
52
+ if (!over) return;
53
+
54
+ const activeId = active.id;
55
+ const overId = over.id;
56
+
57
+ if (activeId === overId) return;
58
+
59
+ const isActiveAColumn = active.data.current?.type === "Column";
60
+ if (!isActiveAColumn) return;
61
+
62
+ setColumns((cs) => {
63
+ const activeColumnIndex = cs.findIndex((col) => col.id === activeId);
64
+ const overColumnIndex = cs.findIndex((col) => col.id === overId);
65
+
66
+ return arrayMove(cs, activeColumnIndex, overColumnIndex);
67
+ });
68
+ };
69
+
70
+ const onDragOver = (event: DragOverEvent) => {
71
+ const { active, over } = event;
72
+ console.log(active, over);
73
+ if (!over) return;
74
+
75
+ const activeId = active.id;
76
+ const overId = over.id;
77
+
78
+ if (activeId === overId) return;
79
+
80
+ const isActiveATask = active.data.current?.type === "Task";
81
+ const isOverATask = over.data.current?.type === "Task";
82
+
83
+ if (!isActiveATask) return;
84
+
85
+ // Dropping a Task over another Task
86
+ if (isActiveATask && isOverATask) {
87
+ setTasks((ts) => {
88
+ const activeIndex = ts.findIndex((t) => t.id === activeId);
89
+ const overIndex = ts.findIndex((t) => t.id === overId);
90
+
91
+ if (ts[activeIndex].columnId !== ts[overIndex].columnId) {
92
+ ts[activeIndex].columnId = ts[overIndex].columnId;
93
+ return arrayMove(ts, activeIndex, overIndex - 1);
94
+ }
95
+
96
+ return arrayMove(ts, activeIndex, overIndex);
97
+ });
98
+ }
99
+
100
+ const isOverAColumn = over.data.current?.type === "Column";
101
+
102
+ // Dropping a Task over a Column
103
+ if (isActiveATask && isOverAColumn) {
104
+ setTasks((ts) => {
105
+ const activeIndex = ts.findIndex((t) => t.id === activeId);
106
+
107
+ ts[activeIndex].columnId = overId.toString();
108
+ return arrayMove(ts, activeIndex, activeIndex);
109
+ });
110
+ }
111
+ };
112
+
113
+ const addTask = async (columnId: string) => {
114
+ try {
115
+ setCreatingTask(true);
116
+
117
+ const highestId = tasks.reduce((acc, task) => {
118
+ const taskId = Number.parseInt(task.id.replace("task", ""), 10);
119
+ return taskId > acc ? taskId : acc;
120
+ }, 0);
121
+
122
+ setTasks((ts) => [
123
+ ...ts,
124
+ {
125
+ id: `task${highestId + 1}`,
126
+ columnId,
127
+ title: `Task ${highestId + 1}`,
128
+ },
129
+ ]);
130
+ } finally {
131
+ setCreatingTask(false);
132
+ }
133
+ };
134
+
135
+ const deleteTask = (taskId: string) => {
136
+ const newTasks = tasks.filter((task) => task.id !== taskId);
137
+ setTasks(newTasks);
138
+ };
139
+
140
+ return (
141
+ <div className={classes.root}>
142
+ <DndContext
143
+ sensors={sensors}
144
+ onDragStart={onDragStart}
145
+ onDragEnd={onDragEnd}
146
+ onDragOver={onDragOver}
147
+ >
148
+ <div className={classes.board}>
149
+ <SortableContext items={columnsId}>
150
+ {columns.map((column) => (
151
+ <ColumnContainer
152
+ key={column.id}
153
+ column={column}
154
+ tasks={tasks.filter((task) => task.columnId === column.id)}
155
+ addTask={addTask}
156
+ deleteTask={deleteTask}
157
+ addEnabled={!creatingTask}
158
+ />
159
+ ))}
160
+ </SortableContext>
161
+ </div>
162
+
163
+ <DragOverlay>
164
+ {activeColumn && (
165
+ <ColumnContainer
166
+ column={activeColumn}
167
+ tasks={tasks.filter((task) => task.columnId === activeColumn.id)}
168
+ />
169
+ )}
170
+ {activeTask && <TaskCard task={activeTask} deleteTask={deleteTask} />}
171
+ </DragOverlay>
172
+ </DndContext>
173
+ </div>
174
+ );
175
+ };
176
+
177
+ export { KanbanBoard as Component };
178
+
179
+ export default KanbanBoard;
@@ -0,0 +1,76 @@
1
+ import { css } from "@emotion/css";
2
+ import { theme } from "@hitachivantara/uikit-react-core";
3
+
4
+ const styles = {
5
+ root: css({
6
+ marginTop: theme.space.md,
7
+ }),
8
+ board: css({
9
+ display: "flex",
10
+ gap: theme.space.sm,
11
+ }),
12
+ columnContainer: css({
13
+ // This is needed because we need to have a set height on the column container so that
14
+ // dnd-kit will work. In some edge cases (when content of the column is a single item with
15
+ // a certain height) drag between columns wouldn't work.
16
+ height: 100,
17
+ width: "100%",
18
+ }),
19
+ column: css({
20
+ flex: 1,
21
+ padding: theme.spacing("sm", "xs"),
22
+ borderRadius: theme.radii.large,
23
+ backgroundColor: theme.colors.primaryDimmed,
24
+ }),
25
+ columnHeader: css({
26
+ display: "flex",
27
+ flexDirection: "row",
28
+ justifyContent: "space-between",
29
+ alignItems: "center",
30
+ marginBottom: theme.space.lg,
31
+ padding: theme.spacing(0, "xs"),
32
+ "&:hover": {
33
+ cursor: "grab",
34
+ },
35
+ }),
36
+ columnTitle: css({
37
+ display: "flex",
38
+ alignItems: "center",
39
+ gap: theme.space.xs,
40
+ }),
41
+ columnCards: css({}),
42
+ count: css({
43
+ borderRadius: theme.radii.full,
44
+ width: 20,
45
+ height: 20,
46
+ backgroundColor: theme.colors.border,
47
+ display: "grid",
48
+ placeItems: "center",
49
+ }),
50
+ card: css({
51
+ borderRadius: theme.radii.round,
52
+ }),
53
+ cardHeader: css({
54
+ "&:hover": {
55
+ cursor: "grab",
56
+ },
57
+ backgroundColor: theme.colors.bgContainer,
58
+ zIndex: 200,
59
+ borderRadius: `${theme.radii.round} ${theme.radii.round} 0 0`,
60
+ }),
61
+ cardDeleteIcon: css({
62
+ position: "absolute",
63
+ top: theme.space.xs,
64
+ right: theme.space.xs,
65
+ }),
66
+ cardSemanticBar: css({
67
+ height: 20,
68
+ borderRadius: theme.radii.round,
69
+ top: -2,
70
+ }),
71
+ cardActions: css({
72
+ borderTop: "none",
73
+ }),
74
+ };
75
+
76
+ export default styles;
@@ -0,0 +1,21 @@
1
+ import { HvColor } from "@hitachivantara/uikit-react-core";
2
+
3
+ export type Column = {
4
+ id: string;
5
+ title: string;
6
+ color?: HvColor;
7
+ icon?: React.ReactNode;
8
+ };
9
+
10
+ export type User = {
11
+ name: string;
12
+ avatar: string;
13
+ };
14
+
15
+ export type Task = {
16
+ id: string;
17
+ columnId: Column["id"];
18
+ title: string;
19
+ users?: User[];
20
+ statusLevel?: number;
21
+ };
@@ -0,0 +1,42 @@
1
+ import ReactChart from "react-google-charts";
2
+
3
+ import { TrendData } from "./data";
4
+
5
+ interface IndicatorProps {
6
+ data?: TrendData;
7
+ variation?: string;
8
+ }
9
+
10
+ export const Indicator = ({ data, variation }: IndicatorProps) => (
11
+ <div style={{ pointerEvents: "none", marginRight: -4 }}>
12
+ <ReactChart
13
+ width="50px"
14
+ height="32px"
15
+ chartType="AreaChart"
16
+ loader={<div>Loading Chart</div>}
17
+ data={data}
18
+ options={{
19
+ legend: "none",
20
+ colors: variation === "up" ? ["green"] : ["red"],
21
+ tooltip: {
22
+ trigger: "none",
23
+ },
24
+ hAxis: {
25
+ minValue: 0,
26
+ maxValue: 10,
27
+ gridlines: {
28
+ color: "transparent",
29
+ },
30
+ baselineColor: "transparent",
31
+ },
32
+ backgroundColor: "transparent",
33
+ vAxis: {
34
+ gridlines: {
35
+ color: "transparent",
36
+ },
37
+ baselineColor: "transparent",
38
+ },
39
+ }}
40
+ />
41
+ </div>
42
+ );
@@ -0,0 +1,120 @@
1
+ import { css, cx } from "@emotion/css";
2
+ import {
3
+ HvCard,
4
+ HvCardProps,
5
+ HvLoading,
6
+ HvTableInstance,
7
+ HvTypography,
8
+ theme,
9
+ } from "@hitachivantara/uikit-react-core";
10
+ import { BottomXS, TopXS } from "@hitachivantara/uikit-react-icons";
11
+
12
+ import { getStatusIcon, ListViewEntry, TrendData } from "./data";
13
+ import { Indicator } from "./Indicator";
14
+
15
+ const classes = {
16
+ container: css({
17
+ padding: theme.space.sm,
18
+ }),
19
+ card: css({
20
+ cursor: "pointer",
21
+ width: "100%",
22
+ padding: 0,
23
+ textAlign: "left",
24
+ }),
25
+ title: css({
26
+ margin: `${theme.space.xs} 0`,
27
+ }),
28
+ content: css({
29
+ display: "flex",
30
+ alignItems: "center",
31
+ }),
32
+ variation: css({
33
+ display: "flex",
34
+ flex: 1,
35
+ justifyContent: "flex-end",
36
+ alignItems: "center",
37
+ }),
38
+ selected: css({
39
+ outline: `1px solid ${theme.colors.borderDisabled}`,
40
+ }),
41
+ loading: css({
42
+ margin: `${theme.space.xs} 0`,
43
+ }),
44
+ };
45
+
46
+ interface KpiProps {
47
+ title: string;
48
+ count?: number;
49
+ color: HvCardProps["statusColor"];
50
+ variation?: string;
51
+ status: number;
52
+ instance: HvTableInstance<ListViewEntry, string>;
53
+ kpiSelection: number | undefined;
54
+ setKpiSelection: (value: number | undefined) => void;
55
+ trendData?: TrendData;
56
+ loading?: boolean;
57
+ }
58
+
59
+ export const Kpi = ({
60
+ title,
61
+ count,
62
+ color,
63
+ variation,
64
+ status,
65
+ instance,
66
+ kpiSelection,
67
+ trendData,
68
+ loading,
69
+ setKpiSelection,
70
+ }: KpiProps) => {
71
+ const handleKpiClick = () => {
72
+ setKpiSelection(status);
73
+ if (status !== kpiSelection) {
74
+ instance?.setFilter?.("status", `${status}`);
75
+ } else {
76
+ instance?.setFilter?.("status", "");
77
+ setKpiSelection(undefined);
78
+ }
79
+ };
80
+
81
+ return (
82
+ <HvCard
83
+ id={`kpi${status}`}
84
+ selectable
85
+ selected={status === kpiSelection}
86
+ bgcolor="bgContainer"
87
+ statusColor={color}
88
+ onClick={handleKpiClick}
89
+ className={cx(classes.card, {
90
+ [classes.selected]: status === kpiSelection,
91
+ })}
92
+ icon={getStatusIcon(status)}
93
+ tabIndex={0}
94
+ >
95
+ <div className={classes.container}>
96
+ <HvTypography variant="label">{title}</HvTypography>
97
+ {loading ? (
98
+ <HvLoading className={classes.loading} small />
99
+ ) : (
100
+ <div className={classes.content}>
101
+ <HvTypography variant="title2" className={classes.title}>
102
+ {count}
103
+ </HvTypography>
104
+ <div className={classes.variation}>
105
+ <Indicator variation={variation} data={trendData} />
106
+ {variation === "up" ? (
107
+ <TopXS title="Up" color="positive" />
108
+ ) : (
109
+ <BottomXS title="Up" color="negative" />
110
+ )}
111
+ <div>
112
+ <HvTypography variant="caption1">vs last 24h.</HvTypography>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ )}
117
+ </div>
118
+ </HvCard>
119
+ );
120
+ };
@@ -0,0 +1,55 @@
1
+ import { useMemo } from "react";
2
+ import {
3
+ HvTable,
4
+ HvTableBody,
5
+ HvTableCell,
6
+ HvTableContainer,
7
+ HvTableHead,
8
+ HvTableHeader,
9
+ HvTableInstance,
10
+ HvTableRow,
11
+ } from "@hitachivantara/uikit-react-core";
12
+
13
+ import { getColumns, ListViewEntry } from "./data";
14
+
15
+ interface TableProps {
16
+ instance: HvTableInstance<ListViewEntry, string>;
17
+ id?: string;
18
+ }
19
+
20
+ export const Table = ({ instance, id }: TableProps) => {
21
+ const columns = useMemo(() => getColumns(), []);
22
+
23
+ return (
24
+ <HvTableContainer style={{ padding: "2px" }} id={id}>
25
+ <HvTable variant="listrow" {...instance.getTableProps()}>
26
+ <HvTableHead>
27
+ <HvTableRow>
28
+ <HvTableCell variant="listcheckbox" />
29
+ {columns.map((col) => (
30
+ <HvTableHeader key={col.Header}>{col.Header}</HvTableHeader>
31
+ ))}
32
+ </HvTableRow>
33
+ </HvTableHead>
34
+ <HvTableBody withNavigation {...instance.getTableBodyProps()}>
35
+ {instance.page.map((row) => {
36
+ instance.prepareRow(row);
37
+ const { key, ...rowProps } = row.getRowProps();
38
+ return (
39
+ <HvTableRow key={key} {...rowProps}>
40
+ {row.cells.map((cell) => {
41
+ const { key: cellKey, ...cellProps } = cell.getCellProps();
42
+ return (
43
+ <HvTableCell key={cellKey} {...cellProps}>
44
+ {cell.render("Cell")}
45
+ </HvTableCell>
46
+ );
47
+ })}
48
+ </HvTableRow>
49
+ );
50
+ })}
51
+ </HvTableBody>
52
+ </HvTable>
53
+ </HvTableContainer>
54
+ );
55
+ };