@visns-studio/visns-components 5.16.2 → 5.18.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
CHANGED
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
95
95
|
},
|
|
96
96
|
"name": "@visns-studio/visns-components",
|
|
97
|
-
"version": "5.
|
|
97
|
+
"version": "5.18.0",
|
|
98
98
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
99
99
|
"main": "src/index.js",
|
|
100
100
|
"files": [
|
|
@@ -921,6 +921,36 @@ const DataGrid = forwardRef(
|
|
|
921
921
|
[selected, ajaxSetting]
|
|
922
922
|
);
|
|
923
923
|
|
|
924
|
+
const isGroupPartiallySelected = useCallback(
|
|
925
|
+
(groupValue) => {
|
|
926
|
+
if (!dataRef.current || !ajaxSetting?.groupBy) {
|
|
927
|
+
return false;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
const groupField = ajaxSetting.groupBy[0];
|
|
931
|
+
const validRows = dataRef.current.filter(
|
|
932
|
+
(row) =>
|
|
933
|
+
row &&
|
|
934
|
+
row[groupField] === groupValue &&
|
|
935
|
+
row.id !== undefined &&
|
|
936
|
+
row.id !== null
|
|
937
|
+
);
|
|
938
|
+
|
|
939
|
+
if (validRows.length === 0) {
|
|
940
|
+
return false;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
const selectedCount = validRows.filter(
|
|
944
|
+
(row) =>
|
|
945
|
+
selected[row.id] &&
|
|
946
|
+
!selected[row.id].__group
|
|
947
|
+
).length;
|
|
948
|
+
|
|
949
|
+
return selectedCount > 0 && selectedCount < validRows.length;
|
|
950
|
+
},
|
|
951
|
+
[selected, ajaxSetting]
|
|
952
|
+
);
|
|
953
|
+
|
|
924
954
|
const findUpdatedFilter = (filters, currentValues) => {
|
|
925
955
|
for (const filter of filters) {
|
|
926
956
|
const matchingCurrentValue = currentValues.find(
|
|
@@ -1275,6 +1305,11 @@ const DataGrid = forwardRef(
|
|
|
1275
1305
|
case 'update':
|
|
1276
1306
|
modalOpen('update', d.id);
|
|
1277
1307
|
break;
|
|
1308
|
+
case 'navigate':
|
|
1309
|
+
if (s.url && s.key && d[s.key] != null) {
|
|
1310
|
+
navigate(`${s.url}${d[s.key]}`);
|
|
1311
|
+
}
|
|
1312
|
+
break;
|
|
1278
1313
|
default:
|
|
1279
1314
|
confirmDialog({
|
|
1280
1315
|
title: s.title,
|
|
@@ -1393,11 +1428,21 @@ const DataGrid = forwardRef(
|
|
|
1393
1428
|
// Check if all show conditions are met
|
|
1394
1429
|
return iconConfig.show.every((condition) => {
|
|
1395
1430
|
const { id, value } = condition;
|
|
1431
|
+
const hasValueProp = condition.hasOwnProperty('value');
|
|
1396
1432
|
|
|
1397
1433
|
// Check if any row in the group matches the condition
|
|
1398
1434
|
return groupRows.some((row) => {
|
|
1399
1435
|
const rowValue = row[id];
|
|
1400
1436
|
|
|
1437
|
+
// No value prop → field must be truthy (set/non-empty)
|
|
1438
|
+
if (!hasValueProp) {
|
|
1439
|
+
return (
|
|
1440
|
+
rowValue !== null &&
|
|
1441
|
+
rowValue !== undefined &&
|
|
1442
|
+
rowValue !== ''
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1401
1446
|
// Handle null value condition
|
|
1402
1447
|
if (value === null) {
|
|
1403
1448
|
return (
|
|
@@ -2533,6 +2578,8 @@ const DataGrid = forwardRef(
|
|
|
2533
2578
|
return getIconComponent(RotateCcw);
|
|
2534
2579
|
case 'update':
|
|
2535
2580
|
return getIconComponent(Edit);
|
|
2581
|
+
case 'navigate':
|
|
2582
|
+
return getIconComponent(Inbox);
|
|
2536
2583
|
case 'romComplete':
|
|
2537
2584
|
return getIconComponent(CheckCircle);
|
|
2538
2585
|
default:
|
|
@@ -3525,6 +3572,7 @@ const DataGrid = forwardRef(
|
|
|
3525
3572
|
|
|
3526
3573
|
{/* DataGrid container with its own border */}
|
|
3527
3574
|
<div className={styles.dataGridContainer}>
|
|
3575
|
+
|
|
3528
3576
|
{limit && limit > 0 ? (
|
|
3529
3577
|
<ReactDataGrid
|
|
3530
3578
|
key={`datagrid-${ajaxSetting?.url || ''}-${
|
|
@@ -3747,6 +3795,37 @@ const DataGrid = forwardRef(
|
|
|
3747
3795
|
styles.groupActionContainer
|
|
3748
3796
|
}
|
|
3749
3797
|
>
|
|
3798
|
+
{tableSetting?.checkboxColumn && (
|
|
3799
|
+
<input
|
|
3800
|
+
type="checkbox"
|
|
3801
|
+
className={
|
|
3802
|
+
styles.groupHeaderCheckbox
|
|
3803
|
+
}
|
|
3804
|
+
checked={isGroupSelected(
|
|
3805
|
+
groupValue
|
|
3806
|
+
)}
|
|
3807
|
+
ref={(el) => {
|
|
3808
|
+
if (el) {
|
|
3809
|
+
el.indeterminate =
|
|
3810
|
+
isGroupPartiallySelected(
|
|
3811
|
+
groupValue
|
|
3812
|
+
);
|
|
3813
|
+
}
|
|
3814
|
+
}}
|
|
3815
|
+
onClick={(e) =>
|
|
3816
|
+
e.stopPropagation()
|
|
3817
|
+
}
|
|
3818
|
+
onChange={(e) => {
|
|
3819
|
+
e.stopPropagation();
|
|
3820
|
+
handleGroupSelectionChange(
|
|
3821
|
+
groupValue,
|
|
3822
|
+
e.target
|
|
3823
|
+
.checked
|
|
3824
|
+
);
|
|
3825
|
+
}}
|
|
3826
|
+
aria-label="Select all items in this group"
|
|
3827
|
+
/>
|
|
3828
|
+
)}
|
|
3750
3829
|
<button
|
|
3751
3830
|
className={`group-expand-btn ${styles.groupExpandBtn}`}
|
|
3752
3831
|
onClick={(e) => {
|
package/src/components/Form.jsx
CHANGED
|
@@ -2229,6 +2229,30 @@ function Form({
|
|
|
2229
2229
|
}
|
|
2230
2230
|
}, [tableData.dataSource]);
|
|
2231
2231
|
|
|
2232
|
+
// Auto-submit on mount when formSettings.autoSubmit is true.
|
|
2233
|
+
// Used for "report" tabs that should show their results immediately instead of
|
|
2234
|
+
// requiring the user to click "View Report" with an empty filter form.
|
|
2235
|
+
// We trigger an actual click on the rendered Save button so the path is
|
|
2236
|
+
// identical to the user clicking it manually.
|
|
2237
|
+
const autoSubmittedRef = useRef(false);
|
|
2238
|
+
useEffect(() => {
|
|
2239
|
+
if (formSettings?.autoSubmit && !autoSubmittedRef.current) {
|
|
2240
|
+
autoSubmittedRef.current = true;
|
|
2241
|
+
const timer = setTimeout(() => {
|
|
2242
|
+
const saveBtn = document.querySelector('[data-type="save"]');
|
|
2243
|
+
if (saveBtn) {
|
|
2244
|
+
saveBtn.click();
|
|
2245
|
+
} else {
|
|
2246
|
+
handleSubmit({
|
|
2247
|
+
preventDefault: () => {},
|
|
2248
|
+
target: { dataset: { type: 'save' } },
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
}, 150);
|
|
2252
|
+
return () => clearTimeout(timer);
|
|
2253
|
+
}
|
|
2254
|
+
}, [formSettings?.autoSubmit]);
|
|
2255
|
+
|
|
2232
2256
|
useEffect(() => {
|
|
2233
2257
|
formSettings.fields.forEach((field) => {
|
|
2234
2258
|
// showIfEmpty: only show field when its own value is empty/null/undefined/[]
|
|
@@ -241,6 +241,20 @@ function GenericIndex({
|
|
|
241
241
|
const [customActionFormData, setCustomActionFormData] = useState({});
|
|
242
242
|
const [customActionConfig, setCustomActionConfig] = useState(null);
|
|
243
243
|
const { windowHeight, windowWidth } = useWindowDimensions();
|
|
244
|
+
|
|
245
|
+
// Toggle a body-level "tablet-mode" class when this view opts in via
|
|
246
|
+
// setting.tabletMode. Lets consumer projects style the whole UI
|
|
247
|
+
// (including app-level chrome) for tablet use without touching this lib.
|
|
248
|
+
useEffect(() => {
|
|
249
|
+
if (!setting?.tabletMode) {
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
document.body.classList.add('tablet-mode');
|
|
253
|
+
return () => {
|
|
254
|
+
document.body.classList.remove('tablet-mode');
|
|
255
|
+
};
|
|
256
|
+
}, [setting?.tabletMode]);
|
|
257
|
+
|
|
244
258
|
const { config, setConfig, subnav, setSubnav } = useConfig(
|
|
245
259
|
setting,
|
|
246
260
|
setting.tabs,
|
|
@@ -879,6 +879,21 @@
|
|
|
879
879
|
position: relative;
|
|
880
880
|
}
|
|
881
881
|
|
|
882
|
+
.groupHeaderCheckbox {
|
|
883
|
+
width: 22px;
|
|
884
|
+
height: 22px;
|
|
885
|
+
margin-right: 12px;
|
|
886
|
+
cursor: pointer;
|
|
887
|
+
accent-color: var(--primary-color, #3b82f6);
|
|
888
|
+
flex-shrink: 0;
|
|
889
|
+
border-radius: 4px;
|
|
890
|
+
transition: transform 0.15s ease;
|
|
891
|
+
|
|
892
|
+
&:hover {
|
|
893
|
+
transform: scale(1.08);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
882
897
|
.groupExpandBtn {
|
|
883
898
|
background: var(--primary-color, #3b82f6);
|
|
884
899
|
border: none;
|
|
@@ -1200,3 +1215,5 @@
|
|
|
1200
1215
|
transform: scale(1.2);
|
|
1201
1216
|
}
|
|
1202
1217
|
}
|
|
1218
|
+
|
|
1219
|
+
|