@nethru/ui 1.0.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.
Files changed (42) hide show
  1. package/README.md +28 -0
  2. package/dist/Accordion.js +41 -0
  3. package/dist/AccordionDetails.js +15 -0
  4. package/dist/AccordionSummary.js +25 -0
  5. package/dist/AlertDialog.js +48 -0
  6. package/dist/AppBar.js +64 -0
  7. package/dist/Checkbox.js +17 -0
  8. package/dist/ConfirmDialog.js +54 -0
  9. package/dist/DataGrid.js +129 -0
  10. package/dist/Dialog.js +26 -0
  11. package/dist/FormLabel.js +18 -0
  12. package/dist/Frame.js +43 -0
  13. package/dist/GroupSelect.js +65 -0
  14. package/dist/ListItem.js +19 -0
  15. package/dist/ListItemDivider.js +13 -0
  16. package/dist/ListItemGrid.js +12 -0
  17. package/dist/ListItemText.js +35 -0
  18. package/dist/MainHeader.js +56 -0
  19. package/dist/SearchTextField.js +22 -0
  20. package/dist/Section.js +17 -0
  21. package/dist/Select.js +40 -0
  22. package/dist/Slider.js +31 -0
  23. package/dist/Snackbar.js +44 -0
  24. package/dist/StatusChip.js +19 -0
  25. package/dist/Switch.js +32 -0
  26. package/dist/TextField.js +23 -0
  27. package/dist/error/Error.js +63 -0
  28. package/dist/error/HttpError.js +33 -0
  29. package/dist/index.js +29 -0
  30. package/dist/samples/global.sample.css +48 -0
  31. package/dist/samples/menu.sample.json +303 -0
  32. package/dist/sidebar/MenuToggler.js +18 -0
  33. package/dist/sidebar/MenuTree.js +95 -0
  34. package/dist/sidebar/MenuTreeGroup.js +65 -0
  35. package/dist/sidebar/PrimaryMenu.js +47 -0
  36. package/dist/sidebar/SecondaryMenu.js +36 -0
  37. package/dist/sidebar/Sidebar.js +52 -0
  38. package/dist/sidebar/SidebarContext.js +118 -0
  39. package/dist/sidebar/css/primary.module.css +80 -0
  40. package/dist/sidebar/css/sidebar.module.css +50 -0
  41. package/dist/variables.js +6 -0
  42. package/package.json +61 -0
@@ -0,0 +1,303 @@
1
+ [
2
+ {
3
+ "id": "0",
4
+ "name": "모니터링",
5
+ "href": "/monitor",
6
+ "sections": [
7
+ {
8
+ "id": "01",
9
+ "name": "",
10
+ "menu": [
11
+ {
12
+ "id": "011",
13
+ "name": "대시보드",
14
+ "href": "/report/dashboard",
15
+ "submenu": []
16
+ }
17
+ ]
18
+ },
19
+ {
20
+ "id": "02",
21
+ "name": "태스크",
22
+ "menu": [
23
+ {
24
+ "id": "021",
25
+ "name": "수집",
26
+ "href": "/report/collect",
27
+ "submenu": []
28
+ },
29
+ {
30
+ "id": "022",
31
+ "name": "변환",
32
+ "href": "/report/convert",
33
+ "submenu": []
34
+ },
35
+ {
36
+ "id": "023",
37
+ "name": "전송",
38
+ "href": "/report/transport",
39
+ "submenu": []
40
+ }
41
+ ]
42
+ }
43
+ ]
44
+ },
45
+ {
46
+ "id": "1",
47
+ "name": "태깅",
48
+ "href": "/tagging",
49
+ "sections": [
50
+ {
51
+ "id": "10",
52
+ "name": "",
53
+ "menu": [
54
+ {
55
+ "id": "101",
56
+ "name": "태그",
57
+ "href": "/tagging/tag",
58
+ "submenu": []
59
+ },
60
+ {
61
+ "id": "102",
62
+ "name": "트리거",
63
+ "href": "/tagging/trigger",
64
+ "submenu": []
65
+ },
66
+ {
67
+ "id": "103",
68
+ "name": "변수",
69
+ "href": "/tagging/variable",
70
+ "submenu": []
71
+ },
72
+ {
73
+ "id": "104",
74
+ "name": "변수 그룹",
75
+ "href": "/tagging/vgroup",
76
+ "submenu": []
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "id": "11",
82
+ "name": "",
83
+ "menu": [
84
+ {
85
+ "id": "111",
86
+ "name": "디버그 뷰",
87
+ "href": "/tagging/debugview",
88
+ "submenu": []
89
+ }
90
+ ]
91
+ }
92
+ ]
93
+ },
94
+ {
95
+ "id": "2",
96
+ "name": "태스크",
97
+ "href": "/task",
98
+ "sections": [
99
+ {
100
+ "id": "21",
101
+ "name": "",
102
+ "menu": [
103
+ {
104
+ "id": "211",
105
+ "name": "모니터링",
106
+ "href": "/task/monitor",
107
+ "submenu": []
108
+ }
109
+ ]
110
+ },
111
+ {
112
+ "id": "22",
113
+ "name": "수집",
114
+ "menu": [
115
+ {
116
+ "id": "221",
117
+ "name": "관리",
118
+ "href": "/task/collect",
119
+ "container": false,
120
+ "submenu": []
121
+ },
122
+ {
123
+ "id": "222",
124
+ "name": "수집 결과",
125
+ "href": "/task/collect/result",
126
+ "submenu": []
127
+ },
128
+ {
129
+ "id": "223",
130
+ "name": "실행 로그",
131
+ "href": "/task/collect/console",
132
+ "container": false,
133
+ "submenu": []
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "id": "23",
139
+ "name": "변환",
140
+ "menu": [
141
+ {
142
+ "id": "231",
143
+ "name": "관리",
144
+ "href": "/task/convert/list",
145
+ "submenu": []
146
+ },
147
+ {
148
+ "id": "232",
149
+ "name": "변환 결과",
150
+ "href": "/task/convert/result",
151
+ "submenu": []
152
+ },
153
+ {
154
+ "id": "234",
155
+ "name": "실행 로그",
156
+ "href": "/task/convert/console",
157
+ "container": false,
158
+ "submenu": []
159
+ }
160
+ ]
161
+ },
162
+ {
163
+ "id": "24",
164
+ "name": "전송",
165
+ "menu": [
166
+ {
167
+ "id": "241",
168
+ "name": "관리",
169
+ "href": "/task/transport/list",
170
+ "submenu": []
171
+ },
172
+ {
173
+ "id": "242",
174
+ "name": "전송 결과",
175
+ "href": "/task/transport/result",
176
+ "submenu": []
177
+ },
178
+ {
179
+ "id": "243",
180
+ "name": "실행 로그",
181
+ "href": "/task/transport/console",
182
+ "container": false,
183
+ "submenu": []
184
+ }
185
+ ]
186
+ }
187
+ ]
188
+ },
189
+ {
190
+ "id": "3",
191
+ "name": "카프카",
192
+ "href": "/kafka",
193
+ "sections": [
194
+ {
195
+ "id": "31",
196
+ "name": "모니터링",
197
+ "menu": [
198
+ {
199
+ "id": "311",
200
+ "name": "시스템",
201
+ "href": "/kafka/monitor/system",
202
+ "submenu": []
203
+ },
204
+ {
205
+ "id": "312",
206
+ "name": "처리 및 지연",
207
+ "href": "/kafka/monitor/lag",
208
+ "submenu": []
209
+ }
210
+ ]
211
+ },
212
+ {
213
+ "id": "32",
214
+ "name": "브로커",
215
+ "menu": [
216
+ {
217
+ "id": "321",
218
+ "name": "관리",
219
+ "href": "/kafka/broker/edit",
220
+ "container": false,
221
+ "submenu": []
222
+ },
223
+ {
224
+ "id": "322",
225
+ "name": "실행 로그",
226
+ "href": "/kafka/broker/console",
227
+ "container": false,
228
+ "submenu": []
229
+ }
230
+ ]
231
+ },
232
+ {
233
+ "id": "33",
234
+ "name": "커넥트",
235
+ "menu": [
236
+ {
237
+ "id": "331",
238
+ "name": "관리",
239
+ "href": "/kafka/connect/edit",
240
+ "submenu": []
241
+ },
242
+ {
243
+ "id": "332",
244
+ "name": "실행 로그",
245
+ "href": "/kafka/connect/console",
246
+ "container": false,
247
+ "submenu": []
248
+ }
249
+ ]
250
+ },
251
+ {
252
+ "id": "34",
253
+ "name": "토픽",
254
+ "menu": [
255
+ {
256
+ "id": "341",
257
+ "name": "관리",
258
+ "href": "/kafka/topic",
259
+ "submenu": []
260
+ }
261
+ ]
262
+ }
263
+ ]
264
+ },
265
+ {
266
+ "id": "4",
267
+ "name": "관리",
268
+ "href": "/settings",
269
+ "last": true,
270
+ "sections": [
271
+ {
272
+ "id": "41",
273
+ "name": "",
274
+ "menu": [
275
+ {
276
+ "id": "411",
277
+ "name": "에이전트 관리",
278
+ "href": "/settings/agent",
279
+ "submenu": []
280
+ },
281
+ {
282
+ "id": "412",
283
+ "name": "컨테이너 관리",
284
+ "href": "/settings/container",
285
+ "submenu": []
286
+ },
287
+ {
288
+ "id": "413",
289
+ "name": "실행 로그 설정",
290
+ "href": "/settings/consolelog",
291
+ "submenu": []
292
+ },
293
+ {
294
+ "id": "414",
295
+ "name": "회원 관리",
296
+ "href": "/settings/account",
297
+ "submenu": []
298
+ }
299
+ ]
300
+ }
301
+ ]
302
+ }
303
+ ]
@@ -0,0 +1,18 @@
1
+ import { Box } from '@mui/material';
2
+ import NavigateBeforeIcon from '@mui/icons-material/NavigateBefore';
3
+ import NavigateNextIcon from '@mui/icons-material/NavigateNext';
4
+ import styles from './css/sidebar.module.css';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ export default function MenuToggler({
8
+ closed,
9
+ onClick
10
+ }) {
11
+ return /*#__PURE__*/_jsx(Box, {
12
+ className: `${styles.toggler} ${closed ? styles.closed : styles.opened}`,
13
+ children: /*#__PURE__*/_jsxs(Box, {
14
+ onClick: onClick,
15
+ children: [!closed && /*#__PURE__*/_jsx(NavigateBeforeIcon, {}), closed && /*#__PURE__*/_jsx(NavigateNextIcon, {})]
16
+ })
17
+ });
18
+ }
@@ -0,0 +1,95 @@
1
+ import { useNavigate } from "react-router-dom";
2
+ import { getMenuTreeStates, useSidebarContext } from "./SidebarContext";
3
+ import { TreeItem, TreeView } from "@mui/x-tree-view";
4
+ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
5
+ import ArrowRightIcon from '@mui/icons-material/ArrowRight';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const HAS_CHILDREN = "has-children";
8
+ export default function MenuTree({
9
+ id,
10
+ data
11
+ }) {
12
+ const styles = {
13
+ paddingRight: '18px',
14
+ '.MuiTreeItem-content': {
15
+ padding: '7px 8px'
16
+ },
17
+ '.MuiTreeItem-content.Mui-selected': {
18
+ backgroundColor: 'rgba(25, 118, 210, 0.2)'
19
+ },
20
+ '.MuiTreeItem-content .MuiTreeItem-label': {
21
+ fontSize: '0.9rem'
22
+ },
23
+ 'li.has-children > .MuiTreeItem-content': {
24
+ backgroundColor: 'transparent'
25
+ }
26
+ };
27
+ const naviate = useNavigate();
28
+ const {
29
+ states,
30
+ dispatch
31
+ } = useSidebarContext();
32
+ const {
33
+ expanded
34
+ } = getMenuTreeStates(states, id);
35
+ const handleSelect = (event, ids) => {
36
+ dispatch({
37
+ type: "treeItemSelected",
38
+ id,
39
+ ids,
40
+ hasChildren: hasChildren(event.target)
41
+ });
42
+ const node = getNode(ids);
43
+ if (node && node.href) naviate(node.href);
44
+ };
45
+ const handleToggle = (event, ids) => {
46
+ dispatch({
47
+ type: "treeItemExpanded",
48
+ id,
49
+ ids
50
+ });
51
+ };
52
+ return /*#__PURE__*/_jsx(TreeView, {
53
+ defaultCollapseIcon: /*#__PURE__*/_jsx(ArrowDropDownIcon, {}),
54
+ defaultExpandIcon: /*#__PURE__*/_jsx(ArrowRightIcon, {}),
55
+ sx: styles,
56
+ selected: states.activeSecondaryItem || '',
57
+ expanded: expanded,
58
+ onNodeSelect: handleSelect,
59
+ onNodeToggle: handleToggle,
60
+ children: render(data)
61
+ });
62
+ function render(nodes) {
63
+ return nodes ? nodes.map(node => /*#__PURE__*/_jsx(TreeItem, {
64
+ nodeId: node.id,
65
+ label: node.name,
66
+ className: node.submenu.length > 0 ? HAS_CHILDREN : "",
67
+ children: render(node.submenu)
68
+ }, node.id)) : null;
69
+ }
70
+ function hasChildren(element) {
71
+ const target = findTreeItemRoot(element);
72
+ return target ? hasClass(target, HAS_CHILDREN) : false;
73
+ }
74
+ function findTreeItemRoot(element) {
75
+ while (element) {
76
+ if (hasClass(element, "MuiTreeItem-root")) break;
77
+ element = element.parentElement;
78
+ }
79
+ return element;
80
+ }
81
+ function hasClass(element, className) {
82
+ return [...element.classList].includes(className);
83
+ }
84
+ function getNode(id, nodes) {
85
+ nodes = nodes || data;
86
+ for (let node of nodes) {
87
+ if (node.id === id) return node;
88
+ if (node.submenu.length > 0) {
89
+ const child = getNode(id, node.submenu);
90
+ if (child) return child;
91
+ }
92
+ }
93
+ return null;
94
+ }
95
+ }
@@ -0,0 +1,65 @@
1
+ import { getMenuGroupStates, useSidebarContext } from './SidebarContext';
2
+ import Accordion from '@mui/material/Accordion';
3
+ import AccordionSummary from '@mui/material/AccordionSummary';
4
+ import AccordionDetails from '@mui/material/AccordionDetails';
5
+ import Typography from '@mui/material/Typography';
6
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
7
+ import { variables } from '../variables';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ import { jsxs as _jsxs } from "react/jsx-runtime";
10
+ export default function MenuTreeGroup({
11
+ id,
12
+ title,
13
+ children
14
+ }) {
15
+ const styles = {
16
+ backgroundColor: variables.bodyBackgroundColor,
17
+ boxShadow: 'none',
18
+ '&:before': {
19
+ display: 'none'
20
+ },
21
+ '&.Mui-expanded': {
22
+ margin: 0
23
+ },
24
+ '.MuiSvgIcon-root': {
25
+ width: '0.9em',
26
+ height: '0.9em'
27
+ },
28
+ '.MuiAccordionSummary-root.Mui-expanded': {
29
+ minHeight: '48px'
30
+ },
31
+ '.MuiAccordionSummary-content.Mui-expanded': {
32
+ margin: 0
33
+ },
34
+ '.MuiAccordionDetails-root': {
35
+ padding: '0 16px 0 8px'
36
+ }
37
+ };
38
+ const {
39
+ states,
40
+ dispatch
41
+ } = useSidebarContext();
42
+ const expanded = getMenuGroupStates(states, id);
43
+ const handleChange = (event, expanded) => {
44
+ dispatch({
45
+ type: "menuGroupExpanded",
46
+ id,
47
+ expanded
48
+ });
49
+ };
50
+ return /*#__PURE__*/_jsxs(Accordion, {
51
+ expanded: expanded,
52
+ onChange: handleChange,
53
+ square: true,
54
+ sx: styles,
55
+ children: [/*#__PURE__*/_jsx(AccordionSummary, {
56
+ expandIcon: /*#__PURE__*/_jsx(ExpandMoreIcon, {}),
57
+ children: /*#__PURE__*/_jsx(Typography, {
58
+ variant: "body2",
59
+ children: title
60
+ })
61
+ }), /*#__PURE__*/_jsx(AccordionDetails, {
62
+ children: children
63
+ })]
64
+ });
65
+ }
@@ -0,0 +1,47 @@
1
+ import { Link } from 'react-router-dom';
2
+ import { Box, Stack } from '@mui/material';
3
+ import { useSidebarContext } from "./SidebarContext";
4
+ import styles from './css/primary.module.css';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ export default function PrimaryMenu({
8
+ items
9
+ }) {
10
+ const {
11
+ states,
12
+ icons
13
+ } = useSidebarContext();
14
+ return /*#__PURE__*/_jsx(Stack, {
15
+ className: styles.container,
16
+ children: items.map(item => /*#__PURE__*/_jsx(MenuItem, {
17
+ icon: icons[item.href],
18
+ active: item.id === states.activePrimaryItem,
19
+ last: item.last,
20
+ ...item
21
+ }, item.href))
22
+ });
23
+ }
24
+ function MenuItem({
25
+ name,
26
+ icon,
27
+ href,
28
+ active,
29
+ last
30
+ }) {
31
+ return /*#__PURE__*/_jsx(Link, {
32
+ to: href,
33
+ className: last ? 'mt-auto' : '',
34
+ children: /*#__PURE__*/_jsxs(Box, {
35
+ className: `${styles['nav-item']} ${active && styles.active}`,
36
+ children: [active && /*#__PURE__*/_jsx(Box, {
37
+ className: styles.highlight
38
+ }), /*#__PURE__*/_jsx(Box, {
39
+ className: styles.icon,
40
+ children: icon
41
+ }), /*#__PURE__*/_jsx(Box, {
42
+ className: styles.text,
43
+ children: name
44
+ })]
45
+ })
46
+ });
47
+ }
@@ -0,0 +1,36 @@
1
+ import { Divider, Stack } from '@mui/material';
2
+ import MenuTreeGroup from './MenuTreeGroup';
3
+ import MenuTree from './MenuTree';
4
+ import styles from './css/sidebar.module.css';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ export default function SecondaryMenu({
7
+ sections,
8
+ closed
9
+ }) {
10
+ return /*#__PURE__*/_jsx(Stack, {
11
+ className: `${styles.secondary} ${closed ? styles.closed : styles.opened}`,
12
+ children: sections.map((section, index) => {
13
+ let jsx = [];
14
+ jsx.push(index > 0 ? /*#__PURE__*/_jsx(Divider, {
15
+ sx: {
16
+ ml: 2,
17
+ mr: 2
18
+ }
19
+ }, `${section.id}_${index}`) : null);
20
+ jsx.push(section.name ? /*#__PURE__*/_jsx(MenuTreeGroup, {
21
+ id: section.id,
22
+ title: section.name,
23
+ children: /*#__PURE__*/_jsx(MenuTree, {
24
+ id: section.id,
25
+ data: section.menu
26
+ })
27
+ }, section.id) : /*#__PURE__*/_jsx("div", {
28
+ children: /*#__PURE__*/_jsx(MenuTree, {
29
+ id: section.id,
30
+ data: section.menu
31
+ })
32
+ }, section.id));
33
+ return jsx;
34
+ })
35
+ });
36
+ }
@@ -0,0 +1,52 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useLocation } from "react-router-dom";
3
+ import { useSidebarContext } from "./SidebarContext";
4
+ import { Stack } from "@mui/material";
5
+ import PrimaryMenu from "./PrimaryMenu";
6
+ import SecondaryMenu from "./SecondaryMenu";
7
+ import MenuToggler from "./MenuToggler";
8
+ import styles from './css/sidebar.module.css';
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ import { jsxs as _jsxs } from "react/jsx-runtime";
11
+ export default function Sidebar() {
12
+ const [sections, setSections] = useState();
13
+ const {
14
+ menu,
15
+ states,
16
+ dispatch
17
+ } = useSidebarContext();
18
+ const {
19
+ menuClosed: closed
20
+ } = states;
21
+ const location = useLocation();
22
+ useEffect(() => {
23
+ dispatch({
24
+ type: 'updateActiveItems',
25
+ href: location.pathname,
26
+ menu
27
+ });
28
+ // eslint-disable-next-line react-hooks/exhaustive-deps
29
+ }, [menu, location.pathname]);
30
+ useEffect(() => {
31
+ const activeItem = menu.find(item => item.id === states.activePrimaryItem);
32
+ setSections(activeItem ? activeItem.sections : []);
33
+ // eslint-disable-next-line react-hooks/exhaustive-deps
34
+ }, [states]);
35
+ return /*#__PURE__*/_jsxs(Stack, {
36
+ className: `${styles.container} ${closed || isEmpty(sections) ? styles.closed : styles.opened}`,
37
+ children: [/*#__PURE__*/_jsx(PrimaryMenu, {
38
+ items: menu
39
+ }), /*#__PURE__*/_jsx(SecondaryMenu, {
40
+ sections: sections ? sections : [],
41
+ closed: !isEmpty(sections) ? closed : true
42
+ }), !isEmpty(sections) && /*#__PURE__*/_jsx(MenuToggler, {
43
+ closed: closed,
44
+ onClick: () => dispatch({
45
+ type: "secondaryMenuToggled"
46
+ })
47
+ })]
48
+ });
49
+ }
50
+ function isEmpty(list) {
51
+ return list && list.length === 0;
52
+ }