@visns-studio/visns-components 5.13.20 → 5.13.21
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
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@nivo/pie": "^0.99.0",
|
|
14
14
|
"@tinymce/miniature": "^6.0.0",
|
|
15
15
|
"@tinymce/tinymce-react": "^6.2.1",
|
|
16
|
-
"@uiw/react-color": "^2.
|
|
16
|
+
"@uiw/react-color": "^2.6.0",
|
|
17
17
|
"@visns-studio/visns-datagrid-community": "1.1.0",
|
|
18
18
|
"@visns-studio/visns-datagrid-enterprise": "1.1.0",
|
|
19
19
|
"@vitejs/plugin-react": "^4.6.0",
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
"dayjs": "^1.11.13",
|
|
25
25
|
"fabric": "^6.7.0",
|
|
26
26
|
"file-saver": "^2.0.5",
|
|
27
|
-
"framer-motion": "^12.23.
|
|
27
|
+
"framer-motion": "^12.23.1",
|
|
28
28
|
"html-react-parser": "^5.2.5",
|
|
29
29
|
"lodash": "^4.17.21",
|
|
30
30
|
"lodash.debounce": "^4.0.8",
|
|
31
31
|
"lucide-react": "^0.525.0",
|
|
32
32
|
"moment": "^2.30.1",
|
|
33
|
-
"motion": "^12.23.
|
|
33
|
+
"motion": "^12.23.1",
|
|
34
34
|
"numeral": "^2.0.6",
|
|
35
35
|
"pluralize": "^8.0.0",
|
|
36
36
|
"qrcode.react": "^4.2.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"react-quill": "^2.0.0",
|
|
48
48
|
"react-reveal": "^1.2.2",
|
|
49
49
|
"react-router-dom": "^6.30.1",
|
|
50
|
-
"react-select": "^5.10.
|
|
50
|
+
"react-select": "^5.10.1",
|
|
51
51
|
"react-signature-pad-wrapper": "^4.1.1",
|
|
52
52
|
"react-slugify": "^4.0.1",
|
|
53
53
|
"react-sortable-hoc": "^2.0.0",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
89
89
|
},
|
|
90
90
|
"name": "@visns-studio/visns-components",
|
|
91
|
-
"version": "5.13.
|
|
91
|
+
"version": "5.13.21",
|
|
92
92
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
93
93
|
"main": "src/index.js",
|
|
94
94
|
"files": [
|
|
@@ -33,15 +33,15 @@ const renderProgressBar = (value, options = {}) => {
|
|
|
33
33
|
const backgroundColor = colorMap[color] || colorMap.primary;
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
|
-
<div style={{
|
|
36
|
+
<div style={{ width: '100%', minWidth: '150px' }}>
|
|
37
37
|
<div
|
|
38
38
|
style={{
|
|
39
|
-
width: '
|
|
40
|
-
height: '
|
|
39
|
+
width: '100%',
|
|
40
|
+
height: '24px',
|
|
41
41
|
backgroundColor: '#e9ecef',
|
|
42
|
-
borderRadius: '
|
|
42
|
+
borderRadius: '12px',
|
|
43
43
|
overflow: 'hidden',
|
|
44
|
-
|
|
44
|
+
position: 'relative'
|
|
45
45
|
}}
|
|
46
46
|
>
|
|
47
47
|
<div
|
|
@@ -49,21 +49,66 @@ const renderProgressBar = (value, options = {}) => {
|
|
|
49
49
|
width: `${Math.min(Math.max(percentage, 0), 100)}%`,
|
|
50
50
|
height: '100%',
|
|
51
51
|
backgroundColor: backgroundColor,
|
|
52
|
-
borderRadius: '
|
|
52
|
+
borderRadius: '12px',
|
|
53
53
|
transition: 'width 0.3s ease'
|
|
54
54
|
}}
|
|
55
55
|
/>
|
|
56
|
+
{showPercentage && (
|
|
57
|
+
<span style={{
|
|
58
|
+
position: 'absolute',
|
|
59
|
+
top: '50%',
|
|
60
|
+
left: '50%',
|
|
61
|
+
transform: 'translate(-50%, -50%)',
|
|
62
|
+
fontSize: '12px',
|
|
63
|
+
fontWeight: '600',
|
|
64
|
+
color: percentage > 50 ? '#fff' : '#333',
|
|
65
|
+
textShadow: percentage > 50 ? '0 1px 2px rgba(0,0,0,0.3)' : '0 1px 2px rgba(255,255,255,0.8)',
|
|
66
|
+
zIndex: 1
|
|
67
|
+
}}>
|
|
68
|
+
{percentage.toFixed(1)}%
|
|
69
|
+
</span>
|
|
70
|
+
)}
|
|
56
71
|
</div>
|
|
57
|
-
{showPercentage && (
|
|
58
|
-
<span style={{ fontSize: '12px', color: '#6c757d', minWidth: '35px' }}>
|
|
59
|
-
{percentage.toFixed(1)}%
|
|
60
|
-
</span>
|
|
61
|
-
)}
|
|
62
72
|
</div>
|
|
63
73
|
);
|
|
64
74
|
};
|
|
65
75
|
|
|
66
|
-
const
|
|
76
|
+
const renderStatusMessage = (status, messages) => {
|
|
77
|
+
const message = messages[status] || messages.default || 'Status not available';
|
|
78
|
+
return (
|
|
79
|
+
<div style={{
|
|
80
|
+
fontSize: '12px',
|
|
81
|
+
color: '#6c757d',
|
|
82
|
+
fontStyle: 'italic',
|
|
83
|
+
padding: '4px 8px',
|
|
84
|
+
backgroundColor: '#f8f9fa',
|
|
85
|
+
borderRadius: '4px',
|
|
86
|
+
border: '1px solid #e9ecef'
|
|
87
|
+
}}>
|
|
88
|
+
{message}
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const checkCondition = (rowData, condition) => {
|
|
94
|
+
if (!condition || !rowData) return false;
|
|
95
|
+
|
|
96
|
+
const { field, value, operator = 'equals' } = condition;
|
|
97
|
+
const fieldValue = rowData[field];
|
|
98
|
+
|
|
99
|
+
switch (operator) {
|
|
100
|
+
case 'equals':
|
|
101
|
+
return fieldValue === value;
|
|
102
|
+
case 'not_equals':
|
|
103
|
+
return fieldValue !== value;
|
|
104
|
+
case 'contains':
|
|
105
|
+
return fieldValue && fieldValue.toString().includes(value);
|
|
106
|
+
default:
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const renderCellContent = (value, column, widget, rowData = {}) => {
|
|
67
112
|
const columnFormatting = widget.columnFormatting || {};
|
|
68
113
|
const formatting = columnFormatting[column];
|
|
69
114
|
|
|
@@ -71,6 +116,17 @@ const renderCellContent = (value, column, widget) => {
|
|
|
71
116
|
return renderProgressBar(value, formatting);
|
|
72
117
|
}
|
|
73
118
|
|
|
119
|
+
if (formatting && formatting.type === 'conditionalProgressBar') {
|
|
120
|
+
const conditionMet = checkCondition(rowData, formatting.condition);
|
|
121
|
+
|
|
122
|
+
if (conditionMet) {
|
|
123
|
+
return renderProgressBar(value, formatting);
|
|
124
|
+
} else if (formatting.fallback && formatting.fallback.type === 'statusMessage') {
|
|
125
|
+
const status = rowData[formatting.condition.field] || 'default';
|
|
126
|
+
return renderStatusMessage(status, formatting.fallback.messages);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
74
130
|
return value;
|
|
75
131
|
};
|
|
76
132
|
|
|
@@ -94,6 +150,9 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
94
150
|
const [widgetAdded, setWidgetAdded] = useState(false);
|
|
95
151
|
// State to track viewport width
|
|
96
152
|
const [viewportWidth, setViewportWidth] = useState(window.innerWidth);
|
|
153
|
+
// Auto-refresh state
|
|
154
|
+
const [autoRefreshEnabled, setAutoRefreshEnabled] = useState(false);
|
|
155
|
+
const autoRefreshIntervalRef = useRef(null);
|
|
97
156
|
|
|
98
157
|
// Compute available widgets from original settings that are not yet added.
|
|
99
158
|
const availableWidgets = setting.widgets.filter(
|
|
@@ -260,6 +319,39 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
260
319
|
};
|
|
261
320
|
}, []);
|
|
262
321
|
|
|
322
|
+
// Auto-refresh functionality
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
const widgets = dashboardSetting.widgets || [];
|
|
325
|
+
const autoRefreshWidget = widgets.find(widget => widget.autoRefresh?.enabled);
|
|
326
|
+
|
|
327
|
+
if (autoRefreshWidget && autoRefreshEnabled) {
|
|
328
|
+
const interval = autoRefreshWidget.autoRefresh.interval || 30000; // Default 30 seconds
|
|
329
|
+
|
|
330
|
+
autoRefreshIntervalRef.current = setInterval(() => {
|
|
331
|
+
if (Object.keys(filters).length > 0) {
|
|
332
|
+
fetchData(filters);
|
|
333
|
+
}
|
|
334
|
+
}, interval);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return () => {
|
|
338
|
+
if (autoRefreshIntervalRef.current) {
|
|
339
|
+
clearInterval(autoRefreshIntervalRef.current);
|
|
340
|
+
autoRefreshIntervalRef.current = null;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}, [autoRefreshEnabled, filters, dashboardSetting]);
|
|
344
|
+
|
|
345
|
+
// Initialize auto-refresh from widget settings
|
|
346
|
+
useEffect(() => {
|
|
347
|
+
const widgets = dashboardSetting.widgets || [];
|
|
348
|
+
const autoRefreshWidget = widgets.find(widget => widget.autoRefresh?.enabled);
|
|
349
|
+
|
|
350
|
+
if (autoRefreshWidget) {
|
|
351
|
+
setAutoRefreshEnabled(true);
|
|
352
|
+
}
|
|
353
|
+
}, [dashboardSetting]);
|
|
354
|
+
|
|
263
355
|
const openModal = (widgetId) => {
|
|
264
356
|
setModalContent(widgetId);
|
|
265
357
|
setModalShow(true);
|
|
@@ -1119,7 +1211,8 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
1119
1211
|
{renderCellContent(
|
|
1120
1212
|
row[column],
|
|
1121
1213
|
column,
|
|
1122
|
-
widget
|
|
1214
|
+
widget,
|
|
1215
|
+
row
|
|
1123
1216
|
)}
|
|
1124
1217
|
</td>
|
|
1125
1218
|
)
|
|
@@ -1333,6 +1426,25 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
|
|
|
1333
1426
|
>
|
|
1334
1427
|
<div className={styles.widgetTitle}>
|
|
1335
1428
|
<h2>{widget.title}</h2>
|
|
1429
|
+
{widget.autoRefresh?.enabled && widget.autoRefresh?.showControls && (
|
|
1430
|
+
<div className={styles.autoRefreshControl}>
|
|
1431
|
+
<label style={{
|
|
1432
|
+
display: 'flex',
|
|
1433
|
+
alignItems: 'center',
|
|
1434
|
+
fontSize: '12px',
|
|
1435
|
+
color: '#6c757d',
|
|
1436
|
+
marginLeft: '10px'
|
|
1437
|
+
}}>
|
|
1438
|
+
<input
|
|
1439
|
+
type="checkbox"
|
|
1440
|
+
checked={autoRefreshEnabled}
|
|
1441
|
+
onChange={(e) => setAutoRefreshEnabled(e.target.checked)}
|
|
1442
|
+
style={{ marginRight: '5px' }}
|
|
1443
|
+
/>
|
|
1444
|
+
Auto-refresh ({Math.round((widget.autoRefresh.interval || 30000) / 1000)}s)
|
|
1445
|
+
</label>
|
|
1446
|
+
</div>
|
|
1447
|
+
)}
|
|
1336
1448
|
</div>
|
|
1337
1449
|
{renderFilters(widget)}
|
|
1338
1450
|
<div>{renderWidget(widget)}</div>
|