@visns-studio/visns-components 5.0.13 → 5.0.14
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
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
76
76
|
},
|
|
77
77
|
"name": "@visns-studio/visns-components",
|
|
78
|
-
"version": "5.0.
|
|
78
|
+
"version": "5.0.14",
|
|
79
79
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
80
80
|
"main": "src/index.js",
|
|
81
81
|
"files": [
|
|
@@ -1328,9 +1328,8 @@ function GenericDetail({
|
|
|
1328
1328
|
schedulingConfig={activeTabConfig}
|
|
1329
1329
|
data={data}
|
|
1330
1330
|
dataId={routeParams[urlParam]}
|
|
1331
|
-
|
|
1331
|
+
modalOpen={modalOpen}
|
|
1332
1332
|
preloadedOptions={preloadedOptions}
|
|
1333
|
-
userProfile={userProfile}
|
|
1334
1333
|
/>
|
|
1335
1334
|
);
|
|
1336
1335
|
default:
|
|
@@ -16,9 +16,8 @@ const GenericEditableTable = ({
|
|
|
16
16
|
schedulingConfig,
|
|
17
17
|
data,
|
|
18
18
|
dataId,
|
|
19
|
-
|
|
19
|
+
modalOpen,
|
|
20
20
|
preloadedOptions,
|
|
21
|
-
userProfile,
|
|
22
21
|
}) => {
|
|
23
22
|
const { columns, rows, form } = schedulingConfig;
|
|
24
23
|
|
|
@@ -56,29 +55,37 @@ const GenericEditableTable = ({
|
|
|
56
55
|
|
|
57
56
|
const groupCategoriesByType = (data) => {
|
|
58
57
|
const grouped = {};
|
|
59
|
-
|
|
58
|
+
|
|
59
|
+
data.forEach((category, categoryKey) => {
|
|
60
60
|
const categoryType =
|
|
61
|
-
category[rows.categoryKey.id]?.[rows.categoryKey.label] ||
|
|
62
|
-
|
|
61
|
+
category[rows.categoryKey.id]?.[rows.categoryKey.label] || null;
|
|
62
|
+
|
|
63
|
+
const categoryId = category[rows.categoryKey.id]?.id || null;
|
|
63
64
|
|
|
64
|
-
const categoryId
|
|
65
|
-
category[rows.categoryKey.id]?.id || Number.MAX_SAFE_INTEGER;
|
|
65
|
+
const groupKey = categoryId || 'no_category';
|
|
66
66
|
|
|
67
|
-
if (!grouped[
|
|
68
|
-
grouped[
|
|
69
|
-
id: categoryId,
|
|
70
|
-
category: categoryType,
|
|
67
|
+
if (!grouped[groupKey]) {
|
|
68
|
+
grouped[groupKey] = {
|
|
69
|
+
id: categoryId || 'no_category',
|
|
70
|
+
category: categoryType || '',
|
|
71
71
|
entries: [],
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
-
grouped[
|
|
74
|
+
grouped[groupKey].entries.push({
|
|
75
|
+
...category,
|
|
76
|
+
keyCounter: categoryKey,
|
|
77
|
+
});
|
|
75
78
|
});
|
|
76
79
|
|
|
77
80
|
Object.values(grouped).forEach((group) => {
|
|
78
81
|
group.entries.sort((a, b) => a.sort_order - b.sort_order);
|
|
79
82
|
});
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
// Ensure 'no_category' group is at the top
|
|
85
|
+
const groupedArray = Object.values(grouped);
|
|
86
|
+
return groupedArray.sort((a, b) =>
|
|
87
|
+
a.id === 'no_category' ? -1 : b.id === 'no_category' ? 1 : 0
|
|
88
|
+
);
|
|
82
89
|
};
|
|
83
90
|
|
|
84
91
|
const handleFieldChange = (value, fieldId, keyCounter) => {
|
|
@@ -89,7 +96,7 @@ const GenericEditableTable = ({
|
|
|
89
96
|
[fieldId]: value,
|
|
90
97
|
};
|
|
91
98
|
|
|
92
|
-
debouncedUpdate({
|
|
99
|
+
debouncedUpdate({ [rows.key]: updatedDetail });
|
|
93
100
|
|
|
94
101
|
return updatedDetail;
|
|
95
102
|
});
|
|
@@ -130,7 +137,7 @@ const GenericEditableTable = ({
|
|
|
130
137
|
: item;
|
|
131
138
|
});
|
|
132
139
|
|
|
133
|
-
debouncedUpdate({
|
|
140
|
+
debouncedUpdate({ [rows.key]: reordered });
|
|
134
141
|
return reordered;
|
|
135
142
|
}
|
|
136
143
|
}
|
|
@@ -139,6 +146,30 @@ const GenericEditableTable = ({
|
|
|
139
146
|
});
|
|
140
147
|
};
|
|
141
148
|
|
|
149
|
+
const handleDeleteRow = (entry) => {
|
|
150
|
+
confirmAlert({
|
|
151
|
+
title: 'Confirm to Delete',
|
|
152
|
+
message: 'Are you sure you want to delete this entry?',
|
|
153
|
+
buttons: [
|
|
154
|
+
{
|
|
155
|
+
label: 'Yes',
|
|
156
|
+
onClick: async () => {
|
|
157
|
+
setLocalData((prev) => {
|
|
158
|
+
const updatedDetail = prev.filter(
|
|
159
|
+
(item) => item.id !== entry.id
|
|
160
|
+
);
|
|
161
|
+
debouncedUpdate({ [rows.key]: updatedDetail });
|
|
162
|
+
return updatedDetail;
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
label: 'No',
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
142
173
|
const renderScheduledTableField = (entry, column, keyCounter) => {
|
|
143
174
|
if (!entry || !column) return null;
|
|
144
175
|
|
|
@@ -159,6 +190,21 @@ const GenericEditableTable = ({
|
|
|
159
190
|
style={{ textAlign: 'right' }}
|
|
160
191
|
/>
|
|
161
192
|
);
|
|
193
|
+
case 'date':
|
|
194
|
+
return (
|
|
195
|
+
<input
|
|
196
|
+
type="date"
|
|
197
|
+
value={entry[column.id] || ''}
|
|
198
|
+
onChange={(e) =>
|
|
199
|
+
handleFieldChange(
|
|
200
|
+
e.target.value,
|
|
201
|
+
column.id,
|
|
202
|
+
keyCounter
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
style={{ textAlign: 'right' }}
|
|
206
|
+
/>
|
|
207
|
+
);
|
|
162
208
|
case 'dropdown':
|
|
163
209
|
return (
|
|
164
210
|
<select
|
|
@@ -287,43 +333,49 @@ const GenericEditableTable = ({
|
|
|
287
333
|
</td>
|
|
288
334
|
))}
|
|
289
335
|
<td>
|
|
290
|
-
{
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
<
|
|
336
|
+
<div className={styles.tdactions}>
|
|
337
|
+
{idx > 0 && (
|
|
338
|
+
<ArrowUp
|
|
339
|
+
size={18}
|
|
340
|
+
onClick={() =>
|
|
341
|
+
handleSortChange(
|
|
342
|
+
group.id,
|
|
343
|
+
entry.id,
|
|
344
|
+
'up'
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
style={{
|
|
348
|
+
cursor: 'pointer',
|
|
349
|
+
}}
|
|
350
|
+
/>
|
|
351
|
+
)}
|
|
352
|
+
{idx <
|
|
353
|
+
group.entries.length -
|
|
354
|
+
1 && (
|
|
355
|
+
<ArrowDown
|
|
356
|
+
size={18}
|
|
357
|
+
onClick={() =>
|
|
358
|
+
handleSortChange(
|
|
359
|
+
group.id,
|
|
360
|
+
entry.id,
|
|
361
|
+
'down'
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
style={{
|
|
365
|
+
cursor: 'pointer',
|
|
366
|
+
}}
|
|
367
|
+
/>
|
|
368
|
+
)}
|
|
369
|
+
<TrashCan
|
|
307
370
|
size={18}
|
|
308
371
|
onClick={() =>
|
|
309
|
-
|
|
310
|
-
group.id,
|
|
311
|
-
entry.id,
|
|
312
|
-
'down'
|
|
313
|
-
)
|
|
372
|
+
handleDeleteRow(entry)
|
|
314
373
|
}
|
|
315
374
|
style={{
|
|
316
375
|
cursor: 'pointer',
|
|
317
376
|
}}
|
|
318
377
|
/>
|
|
319
|
-
|
|
320
|
-
<TrashCan
|
|
321
|
-
size={18}
|
|
322
|
-
onClick={() =>
|
|
323
|
-
handleDeleteRow(entry)
|
|
324
|
-
}
|
|
325
|
-
style={{ cursor: 'pointer' }}
|
|
326
|
-
/>
|
|
378
|
+
</div>
|
|
327
379
|
</td>
|
|
328
380
|
</tr>
|
|
329
381
|
))}
|
|
@@ -332,8 +384,22 @@ const GenericEditableTable = ({
|
|
|
332
384
|
</tbody>
|
|
333
385
|
</table>
|
|
334
386
|
) : (
|
|
335
|
-
<div
|
|
387
|
+
<div className={styles.noDataMessage}>
|
|
388
|
+
No data available. Please check your filters or try
|
|
389
|
+
reloading the data.
|
|
390
|
+
</div>
|
|
336
391
|
)}
|
|
392
|
+
|
|
393
|
+
<div className={styles.polActions}>
|
|
394
|
+
<button
|
|
395
|
+
className={styles.btn}
|
|
396
|
+
onClick={() => {
|
|
397
|
+
modalOpen('create', 0);
|
|
398
|
+
}}
|
|
399
|
+
>
|
|
400
|
+
Add
|
|
401
|
+
</button>
|
|
402
|
+
</div>
|
|
337
403
|
</div>
|
|
338
404
|
);
|
|
339
405
|
};
|
|
@@ -134,3 +134,45 @@
|
|
|
134
134
|
background: var(--highlight-color);
|
|
135
135
|
border: 1px solid rgba(var(--highlight-rgb), 1.05);
|
|
136
136
|
}
|
|
137
|
+
|
|
138
|
+
.tdactions {
|
|
139
|
+
width: 100%;
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-wrap: nowrap;
|
|
142
|
+
justify-content: flex-start;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 0.1rem;
|
|
145
|
+
|
|
146
|
+
span {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
position: relative;
|
|
150
|
+
width: 18px;
|
|
151
|
+
height: 18px;
|
|
152
|
+
|
|
153
|
+
svg {
|
|
154
|
+
width: 18px;
|
|
155
|
+
height: 18px;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.noDataMessage {
|
|
161
|
+
text-align: center;
|
|
162
|
+
color: var(--primary-color);
|
|
163
|
+
font-size: 1rem;
|
|
164
|
+
padding: 2rem;
|
|
165
|
+
margin: 2rem auto;
|
|
166
|
+
background-color: var(--secondary-bg-color, #f8f8f8);
|
|
167
|
+
border: 1px solid rgba(var(--primary-rgb), 0.15);
|
|
168
|
+
border-radius: 6px;
|
|
169
|
+
max-width: 80%;
|
|
170
|
+
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
|
|
171
|
+
font-weight: 500;
|
|
172
|
+
font-family: var(--font-family, Arial, sans-serif);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.noDataMessage:hover {
|
|
176
|
+
background-color: rgba(var(--primary-rgb), 0.05);
|
|
177
|
+
border-color: rgba(var(--primary-rgb), 0.2);
|
|
178
|
+
}
|