@visns-studio/visns-components 4.10.47 → 5.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.
- package/package.json +28 -30
- package/src/components/cms/Field.jsx +39 -63
- package/src/components/crm/Breadcrumb.jsx +2 -18
- package/src/components/crm/DataGrid.jsx +23 -379
- package/src/components/crm/Field.jsx +16 -215
- package/src/components/crm/Form.jsx +81 -79
- package/src/components/crm/MultiSelect.jsx +25 -71
- package/src/components/crm/Navigation.jsx +7 -11
- package/src/components/crm/QrCode.jsx +8 -12
- package/src/components/crm/QuickAction.jsx +1 -0
- package/src/components/crm/generic/GenericAuth.jsx +2 -6
- package/src/components/crm/generic/GenericDashboard.jsx +30 -340
- package/src/components/crm/generic/GenericDetail.jsx +37 -80
- package/src/components/crm/generic/GenericDynamic.jsx +76 -94
- package/src/components/crm/generic/GenericFormBuilder.jsx +19 -79
- package/src/components/crm/generic/GenericIndex.jsx +1 -2
- package/src/components/crm/generic/styles/GenericDetail.module.scss +0 -51
- package/src/components/crm/generic/styles/GenericFormBuilder.module.scss +0 -5
- package/src/components/crm/styles/DataGrid.module.scss +25 -0
- package/src/components/crm/styles/Field.module.scss +0 -210
- package/src/components/crm/styles/Form.module.scss +0 -78
- package/src/components/crm/styles/Navigation.module.scss +4 -10
- package/src/components/crm/styles/QrCode.module.scss +0 -18
- package/src/index.js +0 -8
- package/src/components/crm/generic/styles/GenericDashboard.module.scss +0 -325
- package/src/components/crm/sketch/SketchField.jsx +0 -395
- package/src/components/crm/sketch/arrow.jsx +0 -108
- package/src/components/crm/sketch/circle.jsx +0 -75
- package/src/components/crm/sketch/default-tool.jsx +0 -16
- package/src/components/crm/sketch/fabrictool.jsx +0 -22
- package/src/components/crm/sketch/history.jsx +0 -144
- package/src/components/crm/sketch/json/config.json +0 -14
- package/src/components/crm/sketch/line.jsx +0 -64
- package/src/components/crm/sketch/pan.jsx +0 -48
- package/src/components/crm/sketch/pencil.jsx +0 -36
- package/src/components/crm/sketch/rectangle-label-object.jsx +0 -69
- package/src/components/crm/sketch/rectangle-label.jsx +0 -93
- package/src/components/crm/sketch/rectangle.jsx +0 -76
- package/src/components/crm/sketch/select.jsx +0 -16
- package/src/components/crm/sketch/tools.jsx +0 -11
- package/src/components/crm/sketch/utils.jsx +0 -67
|
@@ -1,94 +1,49 @@
|
|
|
1
|
-
import React, { useEffect, useState
|
|
2
|
-
import CustomFetch from './Fetch';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
3
2
|
import SelectList from './SelectList';
|
|
4
3
|
import Select, { createFilter } from 'react-select';
|
|
5
|
-
import CreatableSelect from 'react-select/creatable';
|
|
6
4
|
import styles from './styles/AsyncSelect.module.scss';
|
|
7
5
|
|
|
8
6
|
function MultiSelect({
|
|
9
7
|
className,
|
|
10
|
-
inputValue
|
|
8
|
+
inputValue,
|
|
11
9
|
multi,
|
|
12
10
|
onChange,
|
|
13
|
-
options
|
|
11
|
+
options,
|
|
14
12
|
placeholder,
|
|
15
13
|
settings,
|
|
16
14
|
style,
|
|
17
|
-
isCreatable = false,
|
|
18
|
-
creatableConfig = {},
|
|
19
15
|
}) {
|
|
20
16
|
const [selectOptions, setSelectOptions] = useState([]);
|
|
21
|
-
const [selectValue, setSelectValue] = useState([]);
|
|
22
|
-
const prevInputValueRef = useRef();
|
|
23
17
|
|
|
24
18
|
useEffect(() => {
|
|
25
|
-
|
|
26
|
-
? options.map((a) => ({
|
|
27
|
-
value: a.id,
|
|
28
|
-
label: a.label || a.name || a.description || 'Unknown',
|
|
29
|
-
...a,
|
|
30
|
-
}))
|
|
31
|
-
: [];
|
|
32
|
-
setSelectOptions(_options);
|
|
33
|
-
}, [options]);
|
|
19
|
+
let _options = [];
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const _values = Array.isArray(inputValue)
|
|
42
|
-
? inputValue.map((a) => ({
|
|
43
|
-
value: a.id,
|
|
44
|
-
label: a.label || a.name || a.description || 'Unknown',
|
|
45
|
-
...a,
|
|
46
|
-
}))
|
|
47
|
-
: inputValue && typeof inputValue === 'object'
|
|
48
|
-
? [
|
|
49
|
-
{
|
|
50
|
-
value: inputValue.id,
|
|
51
|
-
label:
|
|
52
|
-
inputValue.label ||
|
|
53
|
-
inputValue.name ||
|
|
54
|
-
inputValue.description ||
|
|
55
|
-
'Unknown',
|
|
56
|
-
...inputValue,
|
|
57
|
-
},
|
|
58
|
-
]
|
|
59
|
-
: [];
|
|
21
|
+
if (options.length > 0) {
|
|
22
|
+
options.forEach((a) => {
|
|
23
|
+
let _optionItem = {
|
|
24
|
+
value: a.id,
|
|
25
|
+
label: a.label,
|
|
26
|
+
};
|
|
60
27
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
28
|
+
Object.keys(a).forEach((b) => {
|
|
29
|
+
if (b !== 'id') {
|
|
30
|
+
_optionItem = {
|
|
31
|
+
..._optionItem,
|
|
32
|
+
[b]: a[b],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
65
36
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const res = await CustomFetch(
|
|
69
|
-
creatableConfig.url,
|
|
70
|
-
creatableConfig.method,
|
|
71
|
-
{ label: inputValue }
|
|
72
|
-
);
|
|
37
|
+
_options.push(_optionItem);
|
|
38
|
+
});
|
|
73
39
|
|
|
74
|
-
|
|
75
|
-
const newOption = {
|
|
76
|
-
value: res.data.id,
|
|
77
|
-
label: res.data.label || inputValue,
|
|
78
|
-
...res.data,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
setSelectOptions((prevOptions) => [...prevOptions, newOption]);
|
|
82
|
-
setSelectValue((prevValues) => [...prevValues, newOption]);
|
|
83
|
-
}
|
|
40
|
+
setSelectOptions(_options);
|
|
84
41
|
}
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const SelectComponent = isCreatable ? CreatableSelect : Select;
|
|
42
|
+
}, [options]);
|
|
88
43
|
|
|
89
44
|
return (
|
|
90
|
-
<
|
|
91
|
-
closeMenuOnSelect={
|
|
45
|
+
<Select
|
|
46
|
+
closeMenuOnSelect={multi ? false : true}
|
|
92
47
|
isClearable
|
|
93
48
|
isSearchable
|
|
94
49
|
isMulti={multi}
|
|
@@ -114,8 +69,7 @@ function MultiSelect({
|
|
|
114
69
|
: '52px',
|
|
115
70
|
}),
|
|
116
71
|
}}
|
|
117
|
-
value={
|
|
118
|
-
onCreateOption={handleCreate}
|
|
72
|
+
value={inputValue}
|
|
119
73
|
placeholder={placeholder ? placeholder : 'Select...'}
|
|
120
74
|
/>
|
|
121
75
|
);
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
Calendar,
|
|
10
10
|
ChatDots,
|
|
11
11
|
Clipboard,
|
|
12
|
-
CloudUpload,
|
|
13
12
|
DoubleSword,
|
|
14
13
|
Draft,
|
|
15
14
|
Envelope,
|
|
@@ -236,8 +235,6 @@ function Navigation({
|
|
|
236
235
|
};
|
|
237
236
|
|
|
238
237
|
const renderSetting = (n) => {
|
|
239
|
-
const isActive = location.pathname === n.url; // Check if current path matches setting URL
|
|
240
|
-
|
|
241
238
|
const iconComponents = {
|
|
242
239
|
bug: Bug,
|
|
243
240
|
calendar: Calendar,
|
|
@@ -247,18 +244,15 @@ function Navigation({
|
|
|
247
244
|
signOut: SignOut,
|
|
248
245
|
};
|
|
249
246
|
|
|
250
|
-
const IconComponent = iconComponents[n.icon];
|
|
251
|
-
const settingClasses = isActive ? `${styles.active}` : ''; // Add active class if URLs match
|
|
252
|
-
|
|
253
247
|
if (n.id === 'notifications') {
|
|
254
248
|
return (
|
|
255
|
-
<li
|
|
249
|
+
<li>
|
|
256
250
|
<Notification setSystemAuth={setSystemAuth} />
|
|
257
251
|
</li>
|
|
258
252
|
);
|
|
259
253
|
} else if (n.id === 'switchAccount') {
|
|
260
254
|
return (
|
|
261
|
-
<li
|
|
255
|
+
<li>
|
|
262
256
|
<SwitchAccount
|
|
263
257
|
setSystemAuth={setSystemAuth}
|
|
264
258
|
setting={n}
|
|
@@ -267,8 +261,9 @@ function Navigation({
|
|
|
267
261
|
</li>
|
|
268
262
|
);
|
|
269
263
|
} else if (n.id === 'logout') {
|
|
264
|
+
const IconComponent = iconComponents[n.icon];
|
|
270
265
|
return (
|
|
271
|
-
<li
|
|
266
|
+
<li>
|
|
272
267
|
<button
|
|
273
268
|
title={n.label}
|
|
274
269
|
data-tooltip-id="system-tooltip"
|
|
@@ -280,8 +275,10 @@ function Navigation({
|
|
|
280
275
|
</li>
|
|
281
276
|
);
|
|
282
277
|
} else {
|
|
278
|
+
const IconComponent = iconComponents[n.icon];
|
|
279
|
+
|
|
283
280
|
return (
|
|
284
|
-
<li
|
|
281
|
+
<li>
|
|
285
282
|
<Link
|
|
286
283
|
to={n.url}
|
|
287
284
|
data-tooltip-id="system-tooltip"
|
|
@@ -305,7 +302,6 @@ function Navigation({
|
|
|
305
302
|
calendar: Calendar,
|
|
306
303
|
chatDots: ChatDots,
|
|
307
304
|
clipboard: Clipboard,
|
|
308
|
-
cloudUpload: CloudUpload,
|
|
309
305
|
doubleSword: DoubleSword,
|
|
310
306
|
draft: Draft,
|
|
311
307
|
envelope: Envelope,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import ReactToPrint from 'react-to-print';
|
|
3
3
|
|
|
4
4
|
import CustomFetch from './Fetch';
|
|
5
5
|
import styles from './styles/QrCode.module.scss';
|
|
6
6
|
|
|
7
7
|
const QrCode = ({ config, dataId }) => {
|
|
8
|
-
const
|
|
9
|
-
const reactToPrintFn = useReactToPrint({ contentRef });
|
|
8
|
+
const printComponentRef = useRef();
|
|
10
9
|
const [qrCodeData, setQrCodeData] = useState({
|
|
11
10
|
logo: '',
|
|
12
11
|
qrCode: '',
|
|
@@ -27,13 +26,9 @@ const QrCode = ({ config, dataId }) => {
|
|
|
27
26
|
fetchQrCode(config);
|
|
28
27
|
}, []);
|
|
29
28
|
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
console.info(qrCodeData);
|
|
32
|
-
}, [qrCodeData]);
|
|
33
|
-
|
|
34
29
|
return (
|
|
35
30
|
<>
|
|
36
|
-
<div className={styles.gridtxt} ref={
|
|
31
|
+
<div className={styles.gridtxt} ref={printComponentRef}>
|
|
37
32
|
{qrCodeData.logo && qrCodeData.logo !== '' && (
|
|
38
33
|
<ul className={styles.customer__overview}>
|
|
39
34
|
<li
|
|
@@ -57,7 +52,7 @@ const QrCode = ({ config, dataId }) => {
|
|
|
57
52
|
textAlign: 'center',
|
|
58
53
|
}}
|
|
59
54
|
>
|
|
60
|
-
{qrCodeData.title
|
|
55
|
+
{qrCodeData.title}
|
|
61
56
|
</li>
|
|
62
57
|
</ul>
|
|
63
58
|
<ul className={styles.customer__overview}>
|
|
@@ -76,9 +71,10 @@ const QrCode = ({ config, dataId }) => {
|
|
|
76
71
|
</ul>
|
|
77
72
|
</div>
|
|
78
73
|
<div className={styles.polActions}>
|
|
79
|
-
<
|
|
80
|
-
Print
|
|
81
|
-
|
|
74
|
+
<ReactToPrint
|
|
75
|
+
trigger={() => <button className="btn">Print</button>}
|
|
76
|
+
content={() => printComponentRef.current}
|
|
77
|
+
/>
|
|
82
78
|
</div>
|
|
83
79
|
</>
|
|
84
80
|
);
|
|
@@ -51,12 +51,8 @@ const GenericAuth = ({
|
|
|
51
51
|
const updateAuthStatus = async () => {
|
|
52
52
|
try {
|
|
53
53
|
const { data } = await CustomFetch('/ajax/user/profile', 'GET');
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
setUserProfile(data);
|
|
57
|
-
setIsAuthenticated(true);
|
|
58
|
-
}
|
|
59
|
-
|
|
54
|
+
setUserProfile(data);
|
|
55
|
+
setIsAuthenticated(true);
|
|
60
56
|
setIsLoading(false);
|
|
61
57
|
|
|
62
58
|
if (location.pathname.split('/')[1] === 'login') {
|
|
@@ -1,352 +1,42 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import styles from './styles/GenericDashboard.module.scss';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { toast } from 'react-toastify';
|
|
3
|
+
import CustomFetch from '../../crm/Fetch';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
function GenericDashboard({ setting, userProfile }) {
|
|
5
|
+
const GenericDashboard = ({ userProfile }) => {
|
|
9
6
|
const [data, setData] = useState([]);
|
|
10
|
-
const [dropdown, setDropdown] = useState({ filters: [] });
|
|
11
|
-
const [selectedFilters, setSelectedFilters] = useState({});
|
|
12
|
-
const [filterValues, setFilterValues] = useState({});
|
|
13
|
-
const [errorMessage, setErrorMessage] = useState('');
|
|
14
|
-
|
|
15
|
-
const customStyles = {
|
|
16
|
-
control: (base) => ({
|
|
17
|
-
...base,
|
|
18
|
-
height: '51px',
|
|
19
|
-
minHeight: '51px',
|
|
20
|
-
padding: '0',
|
|
21
|
-
borderColor: '#ced4da',
|
|
22
|
-
borderRadius: '5px',
|
|
23
|
-
boxShadow: 'none',
|
|
24
|
-
'&:hover': {
|
|
25
|
-
borderColor: '#80bdff',
|
|
26
|
-
},
|
|
27
|
-
}),
|
|
28
|
-
valueContainer: (base) => ({
|
|
29
|
-
...base,
|
|
30
|
-
height: '51px',
|
|
31
|
-
padding: '0 8px',
|
|
32
|
-
display: 'flex',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
}),
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const fetchDropdownData = async () => {
|
|
38
|
-
try {
|
|
39
|
-
const response = await CustomFetch(
|
|
40
|
-
setting.api.dropdownUrl,
|
|
41
|
-
'POST',
|
|
42
|
-
{}
|
|
43
|
-
);
|
|
44
|
-
setDropdown((prevState) => ({
|
|
45
|
-
...prevState,
|
|
46
|
-
filters: response?.data?.data || [],
|
|
47
|
-
}));
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.error('Error fetching dropdown data:', error);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const fetchData = async () => {
|
|
54
|
-
try {
|
|
55
|
-
const filters = Object.keys(filterValues).reduce((acc, key) => {
|
|
56
|
-
if (filterValues[key]) {
|
|
57
|
-
acc[key] = filterValues[key];
|
|
58
|
-
}
|
|
59
|
-
return acc;
|
|
60
|
-
}, {});
|
|
61
|
-
|
|
62
|
-
const response = await CustomFetch(
|
|
63
|
-
setting.api.fetchDataUrl,
|
|
64
|
-
'POST',
|
|
65
|
-
filters
|
|
66
|
-
);
|
|
67
|
-
setData(response?.data?.data || []);
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error('Error fetching data:', error);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const handleFilterChange = (filterId, value) => {
|
|
74
|
-
setFilterValues((prevValues) => ({
|
|
75
|
-
...prevValues,
|
|
76
|
-
[filterId]: value,
|
|
77
|
-
}));
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
fetchDropdownData();
|
|
82
|
-
}, []);
|
|
83
|
-
|
|
84
|
-
useEffect(() => {
|
|
85
|
-
fetchData();
|
|
86
|
-
}, [filterValues]);
|
|
87
7
|
|
|
88
8
|
return (
|
|
89
|
-
<div className=
|
|
90
|
-
<div className=
|
|
91
|
-
<div className=
|
|
92
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
>
|
|
103
|
-
<label htmlFor={filter.startDateId}>
|
|
104
|
-
{filter.startDateLabel ||
|
|
105
|
-
'Start Date'}
|
|
106
|
-
</label>
|
|
107
|
-
<input
|
|
108
|
-
id={filter.startDateId}
|
|
109
|
-
type="date"
|
|
110
|
-
value={
|
|
111
|
-
filterValues[
|
|
112
|
-
filter.startDateId
|
|
113
|
-
] || ''
|
|
114
|
-
}
|
|
115
|
-
onChange={(e) =>
|
|
116
|
-
handleFilterChange(
|
|
117
|
-
filter.startDateId,
|
|
118
|
-
e.target.value
|
|
119
|
-
)
|
|
120
|
-
}
|
|
121
|
-
/>
|
|
122
|
-
<label htmlFor={filter.endDateId}>
|
|
123
|
-
{filter.endDateLabel || 'End Date'}
|
|
124
|
-
</label>
|
|
125
|
-
<input
|
|
126
|
-
id={filter.endDateId}
|
|
127
|
-
type="date"
|
|
128
|
-
value={
|
|
129
|
-
filterValues[
|
|
130
|
-
filter.endDateId
|
|
131
|
-
] || ''
|
|
132
|
-
}
|
|
133
|
-
onChange={(e) =>
|
|
134
|
-
handleFilterChange(
|
|
135
|
-
filter.endDateId,
|
|
136
|
-
e.target.value
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
/>
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
142
|
-
case 'dropdown':
|
|
143
|
-
return (
|
|
144
|
-
<div
|
|
145
|
-
key={index}
|
|
146
|
-
className={styles.filterField}
|
|
147
|
-
>
|
|
148
|
-
<label htmlFor={filter.id}>
|
|
149
|
-
{filter.label || 'Select Option'}
|
|
150
|
-
</label>
|
|
151
|
-
<Select
|
|
152
|
-
id={filter.id}
|
|
153
|
-
isMulti={filter.isMulti}
|
|
154
|
-
options={dropdown.filters.map(
|
|
155
|
-
(option) => ({
|
|
156
|
-
value: option.id,
|
|
157
|
-
label: option.label,
|
|
158
|
-
})
|
|
159
|
-
)}
|
|
160
|
-
styles={customStyles}
|
|
161
|
-
value={selectedFilters[filter.id]}
|
|
162
|
-
onChange={(value) =>
|
|
163
|
-
handleFilterChange(
|
|
164
|
-
filter.id,
|
|
165
|
-
value
|
|
166
|
-
)
|
|
167
|
-
}
|
|
168
|
-
/>
|
|
169
|
-
</div>
|
|
170
|
-
);
|
|
171
|
-
default:
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
})}
|
|
175
|
-
<div className={styles.filterActions}>
|
|
176
|
-
<button onClick={fetchData} className="btn btn-primary">
|
|
177
|
-
{setting.filters?.applyButtonLabel ||
|
|
178
|
-
'Apply Filters'}
|
|
179
|
-
</button>
|
|
180
|
-
<button
|
|
181
|
-
onClick={() => {
|
|
182
|
-
setFilterValues({});
|
|
183
|
-
setErrorMessage('');
|
|
184
|
-
}}
|
|
185
|
-
className="btn btn-secondary"
|
|
186
|
-
>
|
|
187
|
-
{setting.filters?.clearButtonLabel ||
|
|
188
|
-
'Clear Filters'}
|
|
189
|
-
</button>
|
|
9
|
+
<div className="grid">
|
|
10
|
+
<div className="grid__row">
|
|
11
|
+
<div className="grid__three dashtopwidge">
|
|
12
|
+
<div className="dashtopwidge__left">
|
|
13
|
+
<h2>
|
|
14
|
+
Current
|
|
15
|
+
<span>
|
|
16
|
+
<strong>Enquiries</strong>
|
|
17
|
+
</span>
|
|
18
|
+
</h2>
|
|
19
|
+
</div>
|
|
20
|
+
<div className="dashtopwidge__right">
|
|
21
|
+
<span>0</span>
|
|
190
22
|
</div>
|
|
191
23
|
</div>
|
|
192
|
-
|
|
193
|
-
<div className=
|
|
194
|
-
<
|
|
24
|
+
<div className="grid__three dashtopwidge">
|
|
25
|
+
<div className="dashtopwidge__left">
|
|
26
|
+
<h2>
|
|
27
|
+
Current{' '}
|
|
28
|
+
<span>
|
|
29
|
+
<strong>Enquiries</strong>
|
|
30
|
+
</span>
|
|
31
|
+
</h2>
|
|
195
32
|
</div>
|
|
196
|
-
|
|
33
|
+
<div className="dashtopwidge__right">
|
|
34
|
+
<span>0</span>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
197
37
|
</div>
|
|
198
|
-
|
|
199
|
-
{setting.widgets?.map((widget, index) => {
|
|
200
|
-
switch (widget.type) {
|
|
201
|
-
case 'chart':
|
|
202
|
-
return (
|
|
203
|
-
<div key={index} className={styles.grid__row}>
|
|
204
|
-
<div className={styles.grid__dashfull}>
|
|
205
|
-
<div className={styles.widgetTitle}>
|
|
206
|
-
<h2>
|
|
207
|
-
{widget.title || 'Chart Widget'}
|
|
208
|
-
</h2>
|
|
209
|
-
</div>
|
|
210
|
-
<div style={{ height: 600 }}>
|
|
211
|
-
{data.length > 0 ? (
|
|
212
|
-
<ResponsiveBar
|
|
213
|
-
data={data}
|
|
214
|
-
keys={widget.keys || []}
|
|
215
|
-
indexBy={
|
|
216
|
-
widget.indexBy ||
|
|
217
|
-
'supervisor'
|
|
218
|
-
}
|
|
219
|
-
margin={
|
|
220
|
-
widget.margin || {
|
|
221
|
-
top: 20,
|
|
222
|
-
right: 200,
|
|
223
|
-
bottom: 110,
|
|
224
|
-
left: 80,
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
padding={0.2}
|
|
228
|
-
valueScale={{ type: 'linear' }}
|
|
229
|
-
indexScale={{
|
|
230
|
-
type: 'band',
|
|
231
|
-
round: true,
|
|
232
|
-
}}
|
|
233
|
-
colors={{
|
|
234
|
-
scheme:
|
|
235
|
-
widget.colorScheme ||
|
|
236
|
-
'set3',
|
|
237
|
-
}}
|
|
238
|
-
borderColor={{
|
|
239
|
-
from: 'color',
|
|
240
|
-
modifiers: [
|
|
241
|
-
['darker', 1.6],
|
|
242
|
-
],
|
|
243
|
-
}}
|
|
244
|
-
axisBottom={
|
|
245
|
-
widget.axisBottom || {
|
|
246
|
-
tickSize: 5,
|
|
247
|
-
tickPadding: 5,
|
|
248
|
-
tickRotation: 45,
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
axisLeft={
|
|
252
|
-
widget.axisLeft || {
|
|
253
|
-
tickSize: 5,
|
|
254
|
-
tickPadding: 5,
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
legends={widget.legends || []}
|
|
258
|
-
/>
|
|
259
|
-
) : (
|
|
260
|
-
<div>Loading chart...</div>
|
|
261
|
-
)}
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
|
-
);
|
|
266
|
-
case 'table':
|
|
267
|
-
return (
|
|
268
|
-
<div key={index} className={styles.grid__row}>
|
|
269
|
-
<div className={styles.grid__dashfull}>
|
|
270
|
-
<div className={styles.widgetTitle}>
|
|
271
|
-
<h2>
|
|
272
|
-
{widget.title || 'Table Widget'}
|
|
273
|
-
</h2>
|
|
274
|
-
</div>
|
|
275
|
-
<div className={styles.tableContainer}>
|
|
276
|
-
{data.length > 0 ? (
|
|
277
|
-
<table>
|
|
278
|
-
<thead>
|
|
279
|
-
<tr>
|
|
280
|
-
<th>
|
|
281
|
-
{widget.tableHeader ||
|
|
282
|
-
'Data'}
|
|
283
|
-
</th>
|
|
284
|
-
{data.map(
|
|
285
|
-
(row, index) => (
|
|
286
|
-
<th key={index}>
|
|
287
|
-
{
|
|
288
|
-
row.supervisor
|
|
289
|
-
}
|
|
290
|
-
</th>
|
|
291
|
-
)
|
|
292
|
-
)}
|
|
293
|
-
</tr>
|
|
294
|
-
</thead>
|
|
295
|
-
<tbody>
|
|
296
|
-
{widget.keys?.map(
|
|
297
|
-
(key, index) => {
|
|
298
|
-
let total = 0;
|
|
299
|
-
return (
|
|
300
|
-
<tr key={index}>
|
|
301
|
-
<td>
|
|
302
|
-
{key}
|
|
303
|
-
</td>
|
|
304
|
-
{data.map(
|
|
305
|
-
(
|
|
306
|
-
row
|
|
307
|
-
) => {
|
|
308
|
-
const count =
|
|
309
|
-
row[
|
|
310
|
-
key
|
|
311
|
-
] ||
|
|
312
|
-
0;
|
|
313
|
-
total +=
|
|
314
|
-
count;
|
|
315
|
-
return (
|
|
316
|
-
<td
|
|
317
|
-
key={
|
|
318
|
-
row.supervisor
|
|
319
|
-
}
|
|
320
|
-
>
|
|
321
|
-
{
|
|
322
|
-
count
|
|
323
|
-
}
|
|
324
|
-
</td>
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
)}
|
|
328
|
-
<td>
|
|
329
|
-
{total}
|
|
330
|
-
</td>
|
|
331
|
-
</tr>
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
)}
|
|
335
|
-
</tbody>
|
|
336
|
-
</table>
|
|
337
|
-
) : (
|
|
338
|
-
<div>No data available</div>
|
|
339
|
-
)}
|
|
340
|
-
</div>
|
|
341
|
-
</div>
|
|
342
|
-
</div>
|
|
343
|
-
);
|
|
344
|
-
default:
|
|
345
|
-
return null;
|
|
346
|
-
}
|
|
347
|
-
})}
|
|
348
38
|
</div>
|
|
349
39
|
);
|
|
350
|
-
}
|
|
40
|
+
};
|
|
351
41
|
|
|
352
42
|
export default GenericDashboard;
|