@mshuja288/aksuicore 0.4.1 → 0.4.3
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/CHANGELOG.md +7 -0
- package/dist/aksui.css +75 -1
- package/dist/index.cjs +226 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.js +226 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
- package/src/patterns/RecordWorkspace.tsx +272 -10
- package/src/patterns/index.ts +3 -0
- package/src/theme/patterns.css +75 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ Versioning follows [VERSIONING.md](./VERSIONING.md).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.3] — 2026-10-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `RecordWorkspace` persists preview on/off and side-rail expand/collapse globally (`aksui.workspace.chrome`) across all tables
|
|
15
|
+
- Filter values persist per screen at `${columnPrefsKey}.filters` when `columnPrefsKey` is set
|
|
16
|
+
|
|
10
17
|
## [0.4.1] — 2026-10-12
|
|
11
18
|
|
|
12
19
|
### Fixed
|
package/dist/aksui.css
CHANGED
|
@@ -1222,7 +1222,8 @@ button.side-rail-add:hover {
|
|
|
1222
1222
|
}
|
|
1223
1223
|
|
|
1224
1224
|
.side-rail-columns,
|
|
1225
|
-
.side-rail-download
|
|
1225
|
+
.side-rail-download,
|
|
1226
|
+
.side-rail-bulk {
|
|
1226
1227
|
display: grid;
|
|
1227
1228
|
gap: 8px;
|
|
1228
1229
|
}
|
|
@@ -1350,6 +1351,79 @@ button.side-rail-download-format:disabled {
|
|
|
1350
1351
|
cursor: default;
|
|
1351
1352
|
}
|
|
1352
1353
|
|
|
1354
|
+
button.side-rail-bulk-toggle {
|
|
1355
|
+
display: inline-flex;
|
|
1356
|
+
align-items: center;
|
|
1357
|
+
justify-content: center;
|
|
1358
|
+
gap: 8px;
|
|
1359
|
+
width: 100%;
|
|
1360
|
+
padding: 10px 12px;
|
|
1361
|
+
border: 1px solid var(--aks-border, #d7dde5);
|
|
1362
|
+
border-radius: var(--aks-radius);
|
|
1363
|
+
background: #fff;
|
|
1364
|
+
color: var(--aks-brand);
|
|
1365
|
+
box-shadow: none;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
button.side-rail-bulk-toggle svg {
|
|
1369
|
+
width: 18px;
|
|
1370
|
+
height: 18px;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
button.side-rail-bulk-toggle:hover:not(:disabled) {
|
|
1374
|
+
background: #f5f7fa;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
button.side-rail-bulk-toggle:disabled {
|
|
1378
|
+
opacity: 0.55;
|
|
1379
|
+
cursor: default;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
.side-rail-bulk-panel {
|
|
1383
|
+
display: grid;
|
|
1384
|
+
gap: 10px;
|
|
1385
|
+
padding: 8px;
|
|
1386
|
+
border: 1px solid var(--aks-line);
|
|
1387
|
+
border-radius: var(--aks-radius);
|
|
1388
|
+
background: #faf9f7;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
label.side-rail-bulk-mode,
|
|
1392
|
+
label.side-rail-bulk-file {
|
|
1393
|
+
display: grid;
|
|
1394
|
+
gap: 6px;
|
|
1395
|
+
margin: 0;
|
|
1396
|
+
font-size: 13px;
|
|
1397
|
+
font-weight: 600;
|
|
1398
|
+
color: var(--aks-brand);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
button.side-rail-bulk-submit {
|
|
1402
|
+
width: 100%;
|
|
1403
|
+
padding: 10px 12px;
|
|
1404
|
+
border: none;
|
|
1405
|
+
border-radius: var(--aks-radius);
|
|
1406
|
+
background: var(--aks-accent, #c45c26);
|
|
1407
|
+
color: #fff;
|
|
1408
|
+
font-weight: 600;
|
|
1409
|
+
box-shadow: none;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
button.side-rail-bulk-submit:disabled {
|
|
1413
|
+
opacity: 0.5;
|
|
1414
|
+
cursor: default;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
.side-rail-bulk-report {
|
|
1418
|
+
font-size: 12px;
|
|
1419
|
+
color: var(--aks-brand);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
.side-rail-bulk-errors {
|
|
1423
|
+
margin: 6px 0 0;
|
|
1424
|
+
padding-left: 18px;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1353
1427
|
.side-rail-filters {
|
|
1354
1428
|
display: grid;
|
|
1355
1429
|
gap: 12px;
|
package/dist/index.cjs
CHANGED
|
@@ -869,9 +869,45 @@ var EXPORT_FORMAT_OPTIONS = [
|
|
|
869
869
|
{ format: "xlsx", label: "Excel" },
|
|
870
870
|
{ format: "json", label: "JSON" }
|
|
871
871
|
];
|
|
872
|
+
var BULK_IMPORT_MODE_OPTIONS = [
|
|
873
|
+
{ mode: "insert", label: "Insert" },
|
|
874
|
+
{ mode: "update", label: "Update" },
|
|
875
|
+
{ mode: "upsert", label: "Upsert" }
|
|
876
|
+
];
|
|
872
877
|
function defaultVisibleKeys(columns) {
|
|
873
878
|
return columns.filter((column) => column.defaultVisible !== false).map((column) => column.key);
|
|
874
879
|
}
|
|
880
|
+
var WORKSPACE_CHROME_KEY = "aksui.workspace.chrome";
|
|
881
|
+
function readWorkspaceChrome() {
|
|
882
|
+
if (typeof window === "undefined") {
|
|
883
|
+
return { previewEnabled: false, sideOpen: false };
|
|
884
|
+
}
|
|
885
|
+
try {
|
|
886
|
+
const raw = window.localStorage.getItem(WORKSPACE_CHROME_KEY);
|
|
887
|
+
if (!raw) {
|
|
888
|
+
return { previewEnabled: false, sideOpen: false };
|
|
889
|
+
}
|
|
890
|
+
const parsed = JSON.parse(raw);
|
|
891
|
+
return {
|
|
892
|
+
previewEnabled: Boolean(parsed.previewEnabled),
|
|
893
|
+
sideOpen: Boolean(parsed.sideOpen)
|
|
894
|
+
};
|
|
895
|
+
} catch {
|
|
896
|
+
return { previewEnabled: false, sideOpen: false };
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function writeWorkspaceChrome(chrome) {
|
|
900
|
+
if (typeof window === "undefined") {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
try {
|
|
904
|
+
window.localStorage.setItem(WORKSPACE_CHROME_KEY, JSON.stringify(chrome));
|
|
905
|
+
} catch {
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
function filtersPrefsKey(columnPrefsKey) {
|
|
909
|
+
return columnPrefsKey ? `${columnPrefsKey}.filters` : void 0;
|
|
910
|
+
}
|
|
875
911
|
function readStoredColumnKeys(prefsKey, fallback, allowed) {
|
|
876
912
|
if (!prefsKey || typeof window === "undefined") {
|
|
877
913
|
return fallback;
|
|
@@ -900,6 +936,45 @@ function writeStoredColumnKeys(prefsKey, keys) {
|
|
|
900
936
|
} catch {
|
|
901
937
|
}
|
|
902
938
|
}
|
|
939
|
+
function readStoredFilters(prefsKey, allowed) {
|
|
940
|
+
if (!prefsKey || typeof window === "undefined") {
|
|
941
|
+
return {};
|
|
942
|
+
}
|
|
943
|
+
try {
|
|
944
|
+
const raw = window.localStorage.getItem(prefsKey);
|
|
945
|
+
if (!raw) {
|
|
946
|
+
return {};
|
|
947
|
+
}
|
|
948
|
+
const parsed = JSON.parse(raw);
|
|
949
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
950
|
+
return {};
|
|
951
|
+
}
|
|
952
|
+
const next = {};
|
|
953
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
954
|
+
if (allowed.has(key) && typeof value === "string" && value.trim()) {
|
|
955
|
+
next[key] = value;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return next;
|
|
959
|
+
} catch {
|
|
960
|
+
return {};
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
function writeStoredFilters(prefsKey, filters) {
|
|
964
|
+
if (!prefsKey || typeof window === "undefined") {
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
try {
|
|
968
|
+
const trimmed = {};
|
|
969
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
970
|
+
if (value.trim()) {
|
|
971
|
+
trimmed[key] = value;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
window.localStorage.setItem(prefsKey, JSON.stringify(trimmed));
|
|
975
|
+
} catch {
|
|
976
|
+
}
|
|
977
|
+
}
|
|
903
978
|
function compareColumnValues(column, left, right) {
|
|
904
979
|
const leftRaw = column.display ? column.display(left) : column.value(left);
|
|
905
980
|
const rightRaw = column.display ? column.display(right) : column.value(right);
|
|
@@ -945,6 +1020,13 @@ function PreviewIcon() {
|
|
|
945
1020
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "2.4", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
|
|
946
1021
|
] });
|
|
947
1022
|
}
|
|
1023
|
+
function UploadIcon() {
|
|
1024
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
|
|
1025
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 16.5V7.3", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
1026
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.5 10.8 10 7.2l3.5 3.6", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
1027
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4.5h12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
1028
|
+
] });
|
|
1029
|
+
}
|
|
948
1030
|
function DownloadIcon() {
|
|
949
1031
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
|
|
950
1032
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3.5v8.2", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
@@ -994,7 +1076,11 @@ function RecordWorkspace({
|
|
|
994
1076
|
canDelete,
|
|
995
1077
|
onDownload,
|
|
996
1078
|
canDownload = true,
|
|
1079
|
+
canExport,
|
|
997
1080
|
downloadBusy = false,
|
|
1081
|
+
onBulkImport,
|
|
1082
|
+
canImport = true,
|
|
1083
|
+
importBusy = false,
|
|
998
1084
|
showColumnPicker = true,
|
|
999
1085
|
columnPrefsKey,
|
|
1000
1086
|
visibleColumnKeys,
|
|
@@ -1012,13 +1098,21 @@ function RecordWorkspace({
|
|
|
1012
1098
|
const [internalVisibleKeys, setInternalVisibleKeys] = react.useState(
|
|
1013
1099
|
() => readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys)
|
|
1014
1100
|
);
|
|
1015
|
-
const
|
|
1101
|
+
const filterStorageKey = filtersPrefsKey(columnPrefsKey);
|
|
1102
|
+
const [filters, setFilters] = react.useState(
|
|
1103
|
+
() => readStoredFilters(filterStorageKey, allowedKeys)
|
|
1104
|
+
);
|
|
1016
1105
|
const [sort, setSort] = react.useState(null);
|
|
1017
|
-
const [sideOpen, setSideOpen] = react.useState(
|
|
1106
|
+
const [sideOpen, setSideOpen] = react.useState(() => readWorkspaceChrome().sideOpen);
|
|
1018
1107
|
const [toolsDrawerOpen, setToolsDrawerOpen] = react.useState(false);
|
|
1019
1108
|
const [downloadOpen, setDownloadOpen] = react.useState(false);
|
|
1109
|
+
const [bulkOpen, setBulkOpen] = react.useState(false);
|
|
1110
|
+
const [bulkMode, setBulkMode] = react.useState("upsert");
|
|
1111
|
+
const [bulkFile, setBulkFile] = react.useState(null);
|
|
1112
|
+
const [bulkReport, setBulkReport] = react.useState(null);
|
|
1113
|
+
const bulkFileInputRef = react.useRef(null);
|
|
1020
1114
|
const [columnsOpen, setColumnsOpen] = react.useState(false);
|
|
1021
|
-
const [previewEnabled, setPreviewEnabled] = react.useState(
|
|
1115
|
+
const [previewEnabled, setPreviewEnabled] = react.useState(() => readWorkspaceChrome().previewEnabled);
|
|
1022
1116
|
const [previewKey, setPreviewKey] = react.useState(null);
|
|
1023
1117
|
const [tooltip, setTooltip] = react.useState(null);
|
|
1024
1118
|
const [pageSize, setPageSize] = react.useState("15");
|
|
@@ -1033,6 +1127,9 @@ function RecordWorkspace({
|
|
|
1033
1127
|
}
|
|
1034
1128
|
setInternalVisibleKeys(readStoredColumnKeys(columnPrefsKey, fallbackKeys, allowedKeys));
|
|
1035
1129
|
}, [allowedKeys, columnPrefsKey, fallbackKeys, isControlled]);
|
|
1130
|
+
react.useEffect(() => {
|
|
1131
|
+
setFilters(readStoredFilters(filtersPrefsKey(columnPrefsKey), allowedKeys));
|
|
1132
|
+
}, [allowedKeys, columnPrefsKey]);
|
|
1036
1133
|
const resolvedVisibleKeys = react.useMemo(() => {
|
|
1037
1134
|
const source = isControlled ? visibleColumnKeys : internalVisibleKeys;
|
|
1038
1135
|
const filtered2 = source.filter((key) => allowedKeys.has(key));
|
|
@@ -1111,7 +1208,9 @@ function RecordWorkspace({
|
|
|
1111
1208
|
const start = showAll ? 0 : (currentPage - 1) * numericPageSize;
|
|
1112
1209
|
const pageItems = showAll ? sorted : sorted.slice(start, start + numericPageSize);
|
|
1113
1210
|
const showAdd = canAdd && Boolean(onAdd);
|
|
1114
|
-
const
|
|
1211
|
+
const exportAllowed = (canExport ?? true) && canDownload;
|
|
1212
|
+
const showDownload = Boolean(onDownload) && exportAllowed;
|
|
1213
|
+
const showBulkImport = Boolean(onBulkImport) && canImport;
|
|
1115
1214
|
const showFilters = filterableColumns.length > 0;
|
|
1116
1215
|
const showColumns = showColumnPicker && columns.length > 0;
|
|
1117
1216
|
const previewItem = previewKey === null ? null : sorted.find((item) => rowKey(item) === previewKey) ?? null;
|
|
@@ -1156,6 +1255,29 @@ function RecordWorkspace({
|
|
|
1156
1255
|
onDownload(format, exportColumns);
|
|
1157
1256
|
setDownloadOpen(false);
|
|
1158
1257
|
}
|
|
1258
|
+
async function submitBulkImport() {
|
|
1259
|
+
if (!onBulkImport || importBusy || !bulkFile) {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
setBulkReport(null);
|
|
1263
|
+
try {
|
|
1264
|
+
const report = await onBulkImport(bulkMode, bulkFile);
|
|
1265
|
+
setBulkReport(report);
|
|
1266
|
+
if (report.applied) {
|
|
1267
|
+
setBulkFile(null);
|
|
1268
|
+
if (bulkFileInputRef.current) {
|
|
1269
|
+
bulkFileInputRef.current.value = "";
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
} catch {
|
|
1273
|
+
setBulkReport({
|
|
1274
|
+
totalRows: 0,
|
|
1275
|
+
failed: 1,
|
|
1276
|
+
applied: false,
|
|
1277
|
+
errors: [{ row: 0, code: "ImportFailed", message: "Import request failed." }]
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1159
1281
|
function cellText(column, item) {
|
|
1160
1282
|
const raw = column.display ? column.display(item) : column.value(item);
|
|
1161
1283
|
return raw === null || raw === void 0 || raw === "" ? "\u2014" : String(raw);
|
|
@@ -1168,13 +1290,22 @@ function RecordWorkspace({
|
|
|
1168
1290
|
}
|
|
1169
1291
|
const previewTitle = previewItem && visibleColumns[0] ? cellText(visibleColumns[0], previewItem) : null;
|
|
1170
1292
|
function changeFilter(key, value) {
|
|
1171
|
-
setFilters((current) =>
|
|
1293
|
+
setFilters((current) => {
|
|
1294
|
+
const next = { ...current, [key]: value };
|
|
1295
|
+
writeStoredFilters(filterStorageKey, next);
|
|
1296
|
+
return next;
|
|
1297
|
+
});
|
|
1172
1298
|
setPage(1);
|
|
1173
1299
|
}
|
|
1174
1300
|
function clearFilters() {
|
|
1175
1301
|
setFilters({});
|
|
1302
|
+
writeStoredFilters(filterStorageKey, {});
|
|
1176
1303
|
setPage(1);
|
|
1177
1304
|
}
|
|
1305
|
+
function setSideOpenValue(open) {
|
|
1306
|
+
setSideOpen(open);
|
|
1307
|
+
writeWorkspaceChrome({ previewEnabled, sideOpen: open });
|
|
1308
|
+
}
|
|
1178
1309
|
function toggleSort(column) {
|
|
1179
1310
|
if (column.sortable === false) {
|
|
1180
1311
|
return;
|
|
@@ -1192,6 +1323,7 @@ function RecordWorkspace({
|
|
|
1192
1323
|
}
|
|
1193
1324
|
function setPreviewEnabledValue(enabled) {
|
|
1194
1325
|
setPreviewEnabled(enabled);
|
|
1326
|
+
writeWorkspaceChrome({ previewEnabled: enabled, sideOpen });
|
|
1195
1327
|
setTooltip(null);
|
|
1196
1328
|
if (!enabled) {
|
|
1197
1329
|
setPreviewKey(null);
|
|
@@ -1252,7 +1384,7 @@ function RecordWorkspace({
|
|
|
1252
1384
|
title: "Columns",
|
|
1253
1385
|
"aria-label": "Columns",
|
|
1254
1386
|
onClick: () => {
|
|
1255
|
-
|
|
1387
|
+
setSideOpenValue(true);
|
|
1256
1388
|
setColumnsOpen(true);
|
|
1257
1389
|
},
|
|
1258
1390
|
children: [
|
|
@@ -1270,12 +1402,27 @@ function RecordWorkspace({
|
|
|
1270
1402
|
"aria-label": "Download",
|
|
1271
1403
|
disabled: downloadBusy,
|
|
1272
1404
|
onClick: () => {
|
|
1273
|
-
|
|
1405
|
+
setSideOpenValue(true);
|
|
1274
1406
|
setDownloadOpen(true);
|
|
1275
1407
|
},
|
|
1276
1408
|
children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
|
|
1277
1409
|
}
|
|
1278
1410
|
) : null,
|
|
1411
|
+
showBulkImport ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1412
|
+
"button",
|
|
1413
|
+
{
|
|
1414
|
+
type: "button",
|
|
1415
|
+
className: "ghost side-rail-icon",
|
|
1416
|
+
title: "Bulk entry",
|
|
1417
|
+
"aria-label": "Bulk entry",
|
|
1418
|
+
disabled: importBusy,
|
|
1419
|
+
onClick: () => {
|
|
1420
|
+
setSideOpenValue(true);
|
|
1421
|
+
setBulkOpen(true);
|
|
1422
|
+
},
|
|
1423
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(UploadIcon, {})
|
|
1424
|
+
}
|
|
1425
|
+
) : null,
|
|
1279
1426
|
showFilters ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1280
1427
|
"button",
|
|
1281
1428
|
{
|
|
@@ -1400,6 +1547,77 @@ function RecordWorkspace({
|
|
|
1400
1547
|
option.format
|
|
1401
1548
|
)) }) : null
|
|
1402
1549
|
] }) : null,
|
|
1550
|
+
showBulkImport ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-bulk", children: [
|
|
1551
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1552
|
+
"button",
|
|
1553
|
+
{
|
|
1554
|
+
type: "button",
|
|
1555
|
+
className: "ghost side-rail-bulk-toggle",
|
|
1556
|
+
"aria-expanded": bulkOpen,
|
|
1557
|
+
disabled: importBusy,
|
|
1558
|
+
onClick: () => setBulkOpen((open) => !open),
|
|
1559
|
+
children: [
|
|
1560
|
+
/* @__PURE__ */ jsxRuntime.jsx(UploadIcon, {}),
|
|
1561
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: importBusy ? "Importing\u2026" : "Bulk entry" })
|
|
1562
|
+
]
|
|
1563
|
+
}
|
|
1564
|
+
),
|
|
1565
|
+
bulkOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-bulk-panel", role: "group", "aria-label": "Bulk entry", children: [
|
|
1566
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-bulk-mode", children: [
|
|
1567
|
+
"Mode",
|
|
1568
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1569
|
+
Select,
|
|
1570
|
+
{
|
|
1571
|
+
value: bulkMode,
|
|
1572
|
+
options: BULK_IMPORT_MODE_OPTIONS.map((option) => ({ value: option.mode, label: option.label })),
|
|
1573
|
+
onChange: (value) => setBulkMode(value)
|
|
1574
|
+
}
|
|
1575
|
+
)
|
|
1576
|
+
] }),
|
|
1577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-bulk-file", children: [
|
|
1578
|
+
"File",
|
|
1579
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1580
|
+
"input",
|
|
1581
|
+
{
|
|
1582
|
+
ref: bulkFileInputRef,
|
|
1583
|
+
type: "file",
|
|
1584
|
+
accept: ".csv,.xlsx,.json",
|
|
1585
|
+
disabled: importBusy,
|
|
1586
|
+
onChange: (event) => {
|
|
1587
|
+
setBulkFile(event.target.files?.[0] ?? null);
|
|
1588
|
+
setBulkReport(null);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
)
|
|
1592
|
+
] }),
|
|
1593
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1594
|
+
"button",
|
|
1595
|
+
{
|
|
1596
|
+
type: "button",
|
|
1597
|
+
className: "side-rail-bulk-submit",
|
|
1598
|
+
disabled: importBusy || !bulkFile,
|
|
1599
|
+
onClick: () => void submitBulkImport(),
|
|
1600
|
+
children: importBusy ? "Importing\u2026" : "Import"
|
|
1601
|
+
}
|
|
1602
|
+
),
|
|
1603
|
+
bulkReport ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-bulk-report", role: "status", children: [
|
|
1604
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: bulkReport.applied ? `Applied ${bulkReport.totalRows} row(s).` : `${bulkReport.failed} error(s) in ${bulkReport.totalRows} row(s).` }),
|
|
1605
|
+
bulkReport.errors.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "side-rail-bulk-errors", children: [
|
|
1606
|
+
bulkReport.errors.slice(0, 8).map((error, index) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
1607
|
+
"Row ",
|
|
1608
|
+
error.row,
|
|
1609
|
+
": ",
|
|
1610
|
+
error.message
|
|
1611
|
+
] }, `${error.row}-${error.code}-${index}`)),
|
|
1612
|
+
bulkReport.errors.length > 8 ? /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
1613
|
+
"\u2026and ",
|
|
1614
|
+
bulkReport.errors.length - 8,
|
|
1615
|
+
" more"
|
|
1616
|
+
] }) : null
|
|
1617
|
+
] }) : null
|
|
1618
|
+
] }) : null
|
|
1619
|
+
] }) : null
|
|
1620
|
+
] }) : null,
|
|
1403
1621
|
showFilters ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-filters", children: [
|
|
1404
1622
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "filter-panel-head", children: [
|
|
1405
1623
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Filters" }),
|
|
@@ -1601,7 +1819,7 @@ function RecordWorkspace({
|
|
|
1601
1819
|
className: "ghost side-rail-toggle",
|
|
1602
1820
|
"aria-expanded": sideOpen,
|
|
1603
1821
|
title: sideOpen ? "Collapse" : "Expand",
|
|
1604
|
-
onClick: () =>
|
|
1822
|
+
onClick: () => setSideOpenValue(!sideOpen),
|
|
1605
1823
|
children: [
|
|
1606
1824
|
/* @__PURE__ */ jsxRuntime.jsx(ChevronIcon, { open: sideOpen }),
|
|
1607
1825
|
sideOpen ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Collapse" }) : null
|