@visns-studio/visns-components 5.16.3 → 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(
|
|
@@ -1398,11 +1428,21 @@ const DataGrid = forwardRef(
|
|
|
1398
1428
|
// Check if all show conditions are met
|
|
1399
1429
|
return iconConfig.show.every((condition) => {
|
|
1400
1430
|
const { id, value } = condition;
|
|
1431
|
+
const hasValueProp = condition.hasOwnProperty('value');
|
|
1401
1432
|
|
|
1402
1433
|
// Check if any row in the group matches the condition
|
|
1403
1434
|
return groupRows.some((row) => {
|
|
1404
1435
|
const rowValue = row[id];
|
|
1405
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
|
+
|
|
1406
1446
|
// Handle null value condition
|
|
1407
1447
|
if (value === null) {
|
|
1408
1448
|
return (
|
|
@@ -3532,6 +3572,7 @@ const DataGrid = forwardRef(
|
|
|
3532
3572
|
|
|
3533
3573
|
{/* DataGrid container with its own border */}
|
|
3534
3574
|
<div className={styles.dataGridContainer}>
|
|
3575
|
+
|
|
3535
3576
|
{limit && limit > 0 ? (
|
|
3536
3577
|
<ReactDataGrid
|
|
3537
3578
|
key={`datagrid-${ajaxSetting?.url || ''}-${
|
|
@@ -3754,6 +3795,37 @@ const DataGrid = forwardRef(
|
|
|
3754
3795
|
styles.groupActionContainer
|
|
3755
3796
|
}
|
|
3756
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
|
+
)}
|
|
3757
3829
|
<button
|
|
3758
3830
|
className={`group-expand-btn ${styles.groupExpandBtn}`}
|
|
3759
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
|
+
|