@antelopejs/dms 0.7.20 → 0.7.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/CHANGELOG.md +23 -0
- package/dist/test/unit/interfaces/dms-base/table-view-row-menu-label.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-row-menu-label.test.js +27 -0
- package/dist/test/unit/interfaces/dms-base/table-view-row-menu-label.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js +11 -0
- package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js.map +1 -1
- package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +13 -3
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +1 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +14 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +63 -7
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableUrlTab.ts +42 -12
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +3 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +10 -11
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +29 -0
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +14 -6
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +2 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +6 -0
- package/frontend-vue/tests/row-side-panel.test.ts +93 -2
- package/frontend-vue/tests/table-view-bulk-drawer.test.ts +114 -0
- package/frontend-vue/tests/table-view-cards-reread.test.ts +77 -0
- package/frontend-vue/tests/table-view-url-tab.test.ts +84 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.7.21
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/AntelopeJS/dms/compare/v0.7.20...v0.7.21)
|
|
6
|
+
|
|
7
|
+
### 🚀 Enhancements
|
|
8
|
+
|
|
9
|
+
- **table-view:** Let a row's panel, drawer or modal show another row in place ([#252](https://github.com/AntelopeJS/dms/pull/252))
|
|
10
|
+
- **table-view:** Let a table view drop the built-in table display ([#255](https://github.com/AntelopeJS/dms/pull/255))
|
|
11
|
+
|
|
12
|
+
### 🩹 Fixes
|
|
13
|
+
|
|
14
|
+
- **table-view:** Keep an empty list on screen while it is read again ([#250](https://github.com/AntelopeJS/dms/pull/250))
|
|
15
|
+
- **table-view:** Serve the row menu label to the browser ([#253](https://github.com/AntelopeJS/dms/pull/253))
|
|
16
|
+
- **table-view:** Keep the tab the user opens in the URL ([#254](https://github.com/AntelopeJS/dms/pull/254))
|
|
17
|
+
|
|
18
|
+
### 🏡 Chore
|
|
19
|
+
|
|
20
|
+
- **release:** @antelopejs/interface-dms v0.5.13 ([6b58111b](https://github.com/AntelopeJS/dms/commit/6b58111b))
|
|
21
|
+
|
|
22
|
+
### ❤️ Contributors
|
|
23
|
+
|
|
24
|
+
- Antony Rizzitelli <rizzitelli.antony@pm.me>
|
|
25
|
+
|
|
3
26
|
## v0.7.20
|
|
4
27
|
|
|
5
28
|
[compare changes](https://github.com/AntelopeJS/dms/compare/v0.7.19...v0.7.20)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const request_filter_1 = require("@antelopejs/interface-dms/base/table-view/internal/request-filter");
|
|
5
|
+
const ALL_GRANTED = {
|
|
6
|
+
add: true,
|
|
7
|
+
edit: true,
|
|
8
|
+
delete: true,
|
|
9
|
+
view: true,
|
|
10
|
+
archive: true,
|
|
11
|
+
restore: true,
|
|
12
|
+
viewArchived: true,
|
|
13
|
+
export: true,
|
|
14
|
+
};
|
|
15
|
+
describe("[unit] interfaces/dms-base/table-view row menu label", () => {
|
|
16
|
+
it("serves the table's menuLabel to the browser", () => {
|
|
17
|
+
const served = (0, request_filter_1.adaptRowActions)({
|
|
18
|
+
rowActions: { menuLabel: "$features.row_menu" },
|
|
19
|
+
archiveMode: false,
|
|
20
|
+
grants: ALL_GRANTED,
|
|
21
|
+
custom: undefined,
|
|
22
|
+
controllerRules: undefined,
|
|
23
|
+
});
|
|
24
|
+
(0, chai_1.expect)(served.menuLabel).to.equal("$features.row_menu");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=table-view-row-menu-label.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-view-row-menu-label.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/table-view-row-menu-label.test.ts"],"names":[],"mappings":";;AAAA,+BAA8B;AAC9B,sGAG2E;AAE3E,MAAM,WAAW,GAAoB;IACnC,GAAG,EAAE,IAAI;IACT,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,YAAY,EAAE,IAAI;IAClB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,IAAA,gCAAe,EAAC;YAC7B,UAAU,EAAE,EAAE,SAAS,EAAE,oBAAoB,EAAE;YAC/C,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE,SAAS;YACjB,eAAe,EAAE,SAAS;SAC3B,CAAC,CAAC;QAEH,IAAA,aAAM,EAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -171,6 +171,17 @@ describe("[unit] interfaces/dms-base — table view sources and reorder", () =>
|
|
|
171
171
|
(0, chai_1.expect)(() => sourceOf({ pageSize: 0 })).to.throw(/pageSize/);
|
|
172
172
|
(0, chai_1.expect)(() => sourceOf({ displays: [{ id: "plan-cards" }] })).to.throw(/named "<module>:<id>"/);
|
|
173
173
|
(0, chai_1.expect)(() => sourceOf({ defaultDisplay: "cards" })).to.throw(/not declared in displays/);
|
|
174
|
+
(0, chai_1.expect)(() => sourceOf({ tableDisplay: false, displays: [{ id: "cards" }] })).to.throw(/drops the table display without a defaultDisplay/);
|
|
175
|
+
(0, chai_1.expect)(() => sourceOf({
|
|
176
|
+
tableDisplay: false,
|
|
177
|
+
displays: [{ id: "cards" }],
|
|
178
|
+
defaultDisplay: "table",
|
|
179
|
+
})).to.throw(/not declared in displays/);
|
|
180
|
+
(0, chai_1.expect)(sourceOf({
|
|
181
|
+
tableDisplay: false,
|
|
182
|
+
displays: [{ id: "cards" }],
|
|
183
|
+
defaultDisplay: "cards",
|
|
184
|
+
}).tableDisplay).to.equal(false);
|
|
174
185
|
(0, chai_1.expect)(() => sourceOf({ card: { fields: ["status"] } })).to.throw(/unknown column "status"/);
|
|
175
186
|
const both = [
|
|
176
187
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-view-source-reorder.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/table-view-source-reorder.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table-view-source-reorder.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/table-view-source-reorder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -256,6 +256,12 @@ export interface TableProps<T> {
|
|
|
256
256
|
data?: T[] | null;
|
|
257
257
|
columns?: TableColumn<T>[];
|
|
258
258
|
loading?: boolean;
|
|
259
|
+
/**
|
|
260
|
+
* No answer has arrived yet. Without it, a load with no row listed counts
|
|
261
|
+
* as the first one, which also draws the skeleton over a re-read of an
|
|
262
|
+
* empty list.
|
|
263
|
+
*/
|
|
264
|
+
firstPageLoading?: boolean;
|
|
259
265
|
/**
|
|
260
266
|
* Message (i18n key) of a failed data fetch; switches the empty-table panel
|
|
261
267
|
* to its error state so a refused query never reads as "no data".
|
|
@@ -713,7 +719,11 @@ const DEFAULT_CAPABILITIES = resolveDisplayCapabilities({
|
|
|
713
719
|
columnManagement: true,
|
|
714
720
|
});
|
|
715
721
|
|
|
716
|
-
|
|
722
|
+
// Undefined, not the `false` an absent boolean prop casts to: the table then
|
|
723
|
+
// judges the first load by itself.
|
|
724
|
+
const props = withDefaults(defineProps<TableProps<T>>(), {
|
|
725
|
+
firstPageLoading: undefined,
|
|
726
|
+
});
|
|
717
727
|
const emits = defineEmits<TableEmits<T>>();
|
|
718
728
|
|
|
719
729
|
const appConfig = useDmsAppConfig() as DmsAppConfig & {
|
|
@@ -827,7 +837,7 @@ const paginationState = defineModel<PaginationState>("pagination", {
|
|
|
827
837
|
// The first page is on its way: skeleton rows (and placeholders for the
|
|
828
838
|
// counts) hold the list's place instead of its empty state.
|
|
829
839
|
const isFirstPageLoading = computed(
|
|
830
|
-
() => !!props.loading && !props.data?.length,
|
|
840
|
+
() => props.firstPageLoading ?? (!!props.loading && !props.data?.length),
|
|
831
841
|
);
|
|
832
842
|
const skeletonRowCount = computed(() =>
|
|
833
843
|
Math.min(
|
|
@@ -1654,7 +1664,7 @@ defineShortcuts({
|
|
|
1654
1664
|
</template>
|
|
1655
1665
|
<!-- First load: skeleton rows keep the column rhythm instead of
|
|
1656
1666
|
flashing the empty state. -->
|
|
1657
|
-
<template v-else-if="
|
|
1667
|
+
<template v-else-if="isFirstPageLoading">
|
|
1658
1668
|
<tr
|
|
1659
1669
|
v-for="rowIndex in skeletonRowCount"
|
|
1660
1670
|
:key="`skeleton-${rowIndex}`"
|
|
@@ -113,7 +113,7 @@ const cardReorder = (index: number): TableViewCardReorder | undefined =>
|
|
|
113
113
|
<!-- v2 cards display: an auto-fill grid inside the table card, sharing
|
|
114
114
|
its selection and its pagination footer. -->
|
|
115
115
|
<CardGridSkeleton
|
|
116
|
-
v-if="props.context.
|
|
116
|
+
v-if="props.context.firstPageLoading"
|
|
117
117
|
:count="props.context.pagination.pageSize"
|
|
118
118
|
:fields="fieldColumns.length"
|
|
119
119
|
/>
|
|
@@ -18,8 +18,22 @@ export interface RowNavigation {
|
|
|
18
18
|
export interface RowNavigationSource {
|
|
19
19
|
rows: () => Data[];
|
|
20
20
|
rowIdKey: string;
|
|
21
|
+
/**
|
|
22
|
+
* Reads one row by id (the table's `get` route or `fetchRowUrl`): what a
|
|
23
|
+
* container's `showRow` falls back to for a row the table does not list.
|
|
24
|
+
*/
|
|
25
|
+
getRow?: (id: string) => Promise<Data | undefined>;
|
|
21
26
|
}
|
|
22
27
|
|
|
28
|
+
/**
|
|
29
|
+
* What a drawer, modal or side panel opened on a row receives to show
|
|
30
|
+
* another row of the same table in its place (`showRow` prop): the row
|
|
31
|
+
* itself, or its id, read from the rows shown or else from the table's route.
|
|
32
|
+
* The table then treats it as the open row: its highlight, its position, its
|
|
33
|
+
* `?record=`. It rejects when the row could not be read.
|
|
34
|
+
*/
|
|
35
|
+
export type ShowRow = (row: Data | string) => Promise<void>;
|
|
36
|
+
|
|
23
37
|
const rowIdOf = (row: Data, rowIdKey: string): string =>
|
|
24
38
|
String(get(row, rowIdKey));
|
|
25
39
|
|
|
@@ -25,10 +25,12 @@ import {
|
|
|
25
25
|
type RowNavigation,
|
|
26
26
|
type RowNavigationSource,
|
|
27
27
|
rowNavigation,
|
|
28
|
+
type ShowRow,
|
|
28
29
|
} from "./rowNavigation";
|
|
29
30
|
import {
|
|
30
31
|
clearWrittenRecord,
|
|
31
32
|
isDeepLinkAction,
|
|
33
|
+
resolveDeepLinkedRow,
|
|
32
34
|
writeRecordId,
|
|
33
35
|
type WrittenRecord,
|
|
34
36
|
} from "../table-view/utils/recordLink";
|
|
@@ -37,6 +39,7 @@ import {
|
|
|
37
39
|
closeRowSidePanelOf,
|
|
38
40
|
openRowSidePanel,
|
|
39
41
|
rowSidePanelOwnerKey,
|
|
42
|
+
useRowSidePanelContent,
|
|
40
43
|
} from "#dms-layout/app/build/composables/layout/rowSidePanel";
|
|
41
44
|
import type { TableUrlScope } from "../table-view/utils/views";
|
|
42
45
|
import { useActionConfirm } from "../confirm/useActionConfirm";
|
|
@@ -145,6 +148,18 @@ interface SidePanelTargetRun extends TargetRunExtras {
|
|
|
145
148
|
missingId?: string;
|
|
146
149
|
}
|
|
147
150
|
|
|
151
|
+
/**
|
|
152
|
+
* `show`, run only while the row side panel still shows `session`: a row read
|
|
153
|
+
* after the panel closed, or moved to another run, leaves it alone.
|
|
154
|
+
*/
|
|
155
|
+
function whileShown<V>(session: symbol, show: (value: V) => void) {
|
|
156
|
+
return (value: V): void => {
|
|
157
|
+
if (useRowSidePanelContent().value?.session === session) show(value);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const NO_ROW_ROUTE = async (): Promise<undefined> => undefined;
|
|
162
|
+
|
|
148
163
|
const NOT_FOUND_TITLE_KEY = "side_panel.not_found.title";
|
|
149
164
|
const NOT_FOUND_DESCRIPTION_KEY = "side_panel.not_found.description";
|
|
150
165
|
|
|
@@ -339,6 +354,31 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
339
354
|
config.onRecordShown?.(id);
|
|
340
355
|
};
|
|
341
356
|
};
|
|
357
|
+
// `showRow` given an id: the listed row, else the one the table's route
|
|
358
|
+
// reads. A row its route answered 404 for goes to `showMissing` when the
|
|
359
|
+
// container has a state for it; any other row not found rejects. Only the
|
|
360
|
+
// latest call applies: a read that resolves after a later call is dropped.
|
|
361
|
+
const rowShower = (
|
|
362
|
+
show: (row: Data) => void,
|
|
363
|
+
showMissing?: (id: string) => void,
|
|
364
|
+
): ShowRow => {
|
|
365
|
+
let latest = 0;
|
|
366
|
+
return async (rowOrId) => {
|
|
367
|
+
const call = ++latest;
|
|
368
|
+
if (typeof rowOrId !== "string") return show(rowOrId);
|
|
369
|
+
const source = config.rowNavigation;
|
|
370
|
+
const found = await resolveDeepLinkedRow(rowOrId, {
|
|
371
|
+
listed: source?.rows(),
|
|
372
|
+
idOf: rowIdOf,
|
|
373
|
+
getRow: source?.getRow ?? NO_ROW_ROUTE,
|
|
374
|
+
});
|
|
375
|
+
if (call !== latest) return;
|
|
376
|
+
if (found.row) return show(found.row);
|
|
377
|
+
if (found.isMissing && showMissing) return showMissing(rowOrId);
|
|
378
|
+
throw new Error(`The row "${rowOrId}" could not be read`);
|
|
379
|
+
};
|
|
380
|
+
};
|
|
381
|
+
|
|
342
382
|
const rowRecorder = (deepLink?: boolean) => {
|
|
343
383
|
const recordId = recordRecorder(deepLink);
|
|
344
384
|
return (row?: Data): void => recordId(rowIdOf(row));
|
|
@@ -382,6 +422,10 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
382
422
|
componentId: config.componentId,
|
|
383
423
|
containerId: run.containerId,
|
|
384
424
|
selection: run.selection,
|
|
425
|
+
showRow: rowShower(
|
|
426
|
+
whileShown(session, showRow),
|
|
427
|
+
whileShown(session, showMissing),
|
|
428
|
+
),
|
|
385
429
|
onSuccessCallback: () => {
|
|
386
430
|
closeRowSidePanel(session);
|
|
387
431
|
config.refreshCallback?.();
|
|
@@ -389,7 +433,7 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
389
433
|
},
|
|
390
434
|
onClose: () => recordId(undefined),
|
|
391
435
|
};
|
|
392
|
-
|
|
436
|
+
function showRow(row?: Data) {
|
|
393
437
|
openRowSidePanel({
|
|
394
438
|
...panel,
|
|
395
439
|
rowTitle: rowTitleOf(run.target, row),
|
|
@@ -399,10 +443,13 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
399
443
|
showRow,
|
|
400
444
|
});
|
|
401
445
|
recordId(rowIdOf(row));
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
446
|
+
}
|
|
447
|
+
function showMissing(id: string) {
|
|
448
|
+
openRowSidePanel({ ...panel, notFound: notFoundOf(run.target), showRow });
|
|
449
|
+
recordId(id);
|
|
450
|
+
}
|
|
451
|
+
if (run.missingId) return showMissing(run.missingId);
|
|
452
|
+
showRow(run.rowData);
|
|
406
453
|
};
|
|
407
454
|
|
|
408
455
|
// A container opened on a listed row steps through the rows shown (its
|
|
@@ -415,6 +462,12 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
415
462
|
const source = config.rowNavigation;
|
|
416
463
|
let instance: ContainerInstance | undefined;
|
|
417
464
|
let navigation: RowNavigation | undefined;
|
|
465
|
+
// Set once the container closes: a row read that resolves later neither
|
|
466
|
+
// writes `?record=` back nor patches the closed container.
|
|
467
|
+
let closed = false;
|
|
468
|
+
const showRowById = rowShower((row) => {
|
|
469
|
+
if (!closed) showRow(row);
|
|
470
|
+
});
|
|
418
471
|
const optionsFor = (row?: Data) => {
|
|
419
472
|
navigation =
|
|
420
473
|
row && source ? rowNavigation(source, row, showRow) : undefined;
|
|
@@ -425,6 +478,7 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
425
478
|
containerId: run.containerId,
|
|
426
479
|
rowData: row,
|
|
427
480
|
navigation,
|
|
481
|
+
showRow: showRowById,
|
|
428
482
|
selection: run.selection,
|
|
429
483
|
onSuccessCallback: () => {
|
|
430
484
|
instance?.close();
|
|
@@ -436,14 +490,16 @@ export function useActionTargets(config: ActionTargetsConfig) {
|
|
|
436
490
|
function showRow(row: Data) {
|
|
437
491
|
instance?.patch({
|
|
438
492
|
componentOptions: optionsFor(row),
|
|
439
|
-
componentKey:
|
|
493
|
+
componentKey: rowIdOf(row),
|
|
440
494
|
});
|
|
441
495
|
recordRow(row);
|
|
442
496
|
}
|
|
443
497
|
instance = openContainer(run, component, optionsFor(run.rowData));
|
|
444
498
|
recordRow(run.rowData);
|
|
445
|
-
|
|
499
|
+
// `showRow` may move an unlisted row's container onto a listed one.
|
|
500
|
+
const stopSteps = source ? listenRowSteps(() => navigation) : undefined;
|
|
446
501
|
const settle = () => {
|
|
502
|
+
closed = true;
|
|
447
503
|
stopSteps?.();
|
|
448
504
|
recordRow(undefined);
|
|
449
505
|
};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { router as inertiaRouter } from "@inertiajs/vue3";
|
|
2
|
+
import { onBeforeUnmount, onMounted, watch, type Ref } from "vue";
|
|
3
|
+
import { queryOfUrl } from "./utils/urlFilters";
|
|
4
|
+
import {
|
|
5
|
+
readTableUrlKey,
|
|
6
|
+
type TableUrlScope,
|
|
7
|
+
writeTableUrlKey,
|
|
8
|
+
} from "./utils/views";
|
|
3
9
|
|
|
4
10
|
const TAB_URL_KEY = "tab";
|
|
5
11
|
|
|
@@ -30,18 +36,42 @@ export function readTableUrlTab(
|
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
39
|
+
* Keeps the open tab and the URL in step after arrival. A tab the user opens
|
|
40
|
+
* is written to the URL in place (no visit, no history entry), under the key
|
|
41
|
+
* it is read from, so a reload or a shared link opens it again. A link or a
|
|
42
|
+
* `router.replace` naming another tab of the same page switches to it without
|
|
43
|
+
* remounting the page. A URL dropping the key, or naming a tab the table
|
|
44
|
+
* cannot open in place (an unknown id, a link tab), leaves the open tab alone.
|
|
37
45
|
*/
|
|
38
46
|
export function useTableUrlTab(options: TableUrlTabOptions): void {
|
|
47
|
+
const { activeTabId, urlScope } = options;
|
|
48
|
+
|
|
49
|
+
const follow = (query: Record<string, unknown>) => {
|
|
50
|
+
const tabId = readTableUrlTab(query, urlScope);
|
|
51
|
+
if (!tabId || tabId === activeTabId.value) return;
|
|
52
|
+
if (!options.isOpenable(tabId)) return;
|
|
53
|
+
activeTabId.value = tabId;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// The tab is written in place, so the route keeps the value of the last
|
|
57
|
+
// visit: a link back to that tab leaves it unchanged, and only the visit
|
|
58
|
+
// tells it was followed. A `router.replace`, which Inertia does not
|
|
59
|
+
// announce, still moves the route.
|
|
39
60
|
watch(
|
|
40
|
-
() => readTableUrlTab(options.route.query,
|
|
41
|
-
(
|
|
42
|
-
if (!tabId || tabId === options.activeTabId.value) return;
|
|
43
|
-
if (!options.isOpenable(tabId)) return;
|
|
44
|
-
options.activeTabId.value = tabId;
|
|
45
|
-
},
|
|
61
|
+
() => readTableUrlTab(options.route.query, urlScope),
|
|
62
|
+
() => follow(options.route.query),
|
|
46
63
|
);
|
|
64
|
+
let stopFollowingVisits: (() => void) | undefined;
|
|
65
|
+
onMounted(() => {
|
|
66
|
+
stopFollowingVisits = inertiaRouter.on("navigate", (event) =>
|
|
67
|
+
follow(queryOfUrl(event.detail.page.url)),
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
onBeforeUnmount(() => stopFollowingVisits?.());
|
|
71
|
+
|
|
72
|
+
watch(activeTabId, (tabId) => {
|
|
73
|
+
if (options.isOpenable(tabId)) {
|
|
74
|
+
writeTableUrlKey(urlScope, TAB_URL_KEY, tabId);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
47
77
|
}
|
|
@@ -103,10 +103,11 @@ export const useTableViewConfig = <T extends Data>(
|
|
|
103
103
|
);
|
|
104
104
|
|
|
105
105
|
// Config-derived (SSR-safe; the registry is client-only): the implicit `table`
|
|
106
|
-
// display plus explicit `displays`. Built-in defaults
|
|
106
|
+
// display (unless `tableDisplay` is false) plus explicit `displays`. Built-in defaults
|
|
107
107
|
// (selfManagedData/capabilities) are merged per id.
|
|
108
108
|
const resolvedDisplays: TableViewDisplayConfig[] = (() => {
|
|
109
|
-
const list: TableViewDisplayConfig[] =
|
|
109
|
+
const list: TableViewDisplayConfig[] =
|
|
110
|
+
config.tableDisplay === false ? [] : [{ id: TABLE_DISPLAY_ID }];
|
|
110
111
|
for (const display of config.displays ?? []) {
|
|
111
112
|
if (display.id === TABLE_DISPLAY_ID) continue;
|
|
112
113
|
list.push(display);
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { CustomRowAction } from "../../../../types/row-action";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
readTableUrlKey,
|
|
4
|
+
tableUrlKey,
|
|
5
|
+
type TableUrlScope,
|
|
6
|
+
writeTableUrlKey,
|
|
7
|
+
} from "./views";
|
|
3
8
|
import { readFetchNotFound } from "../../../utils/fetchNotFound";
|
|
4
9
|
|
|
5
10
|
/** Query key of the row a `deepLink` action has open. */
|
|
@@ -7,9 +12,7 @@ export const RECORD_URL_KEY = "record";
|
|
|
7
12
|
|
|
8
13
|
/** The key this table writes the open row under: short on a sole table. */
|
|
9
14
|
export function recordUrlKey(scope: TableUrlScope): string {
|
|
10
|
-
return scope
|
|
11
|
-
? RECORD_URL_KEY
|
|
12
|
-
: `${scope.tableId}.${RECORD_URL_KEY}`;
|
|
15
|
+
return tableUrlKey(scope, RECORD_URL_KEY);
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
/** The row the URL names for this table, if any. */
|
|
@@ -29,13 +32,9 @@ export function writeRecordId(
|
|
|
29
32
|
scope: TableUrlScope,
|
|
30
33
|
id?: string,
|
|
31
34
|
): WrittenRecord | undefined {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (id) url.searchParams.set(key, id);
|
|
36
|
-
else url.searchParams.delete(key);
|
|
37
|
-
window.history.replaceState(window.history.state, "", url);
|
|
38
|
-
return id ? { pathname: url.pathname, key, id } : undefined;
|
|
35
|
+
const url = writeTableUrlKey(scope, RECORD_URL_KEY, id);
|
|
36
|
+
if (!url || !id) return undefined;
|
|
37
|
+
return { pathname: url.pathname, key: recordUrlKey(scope), id };
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
/**
|
|
@@ -183,6 +183,35 @@ export interface UrlKeyReading {
|
|
|
183
183
|
ignoredShortKey?: boolean;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
/**
|
|
187
|
+
* The key this table writes `key` (`tab`, `record`) under: the short one on
|
|
188
|
+
* its page's only table, else prefixed with its id (`content.tab`).
|
|
189
|
+
*/
|
|
190
|
+
export function tableUrlKey(scope: TableUrlScope, key: string): string {
|
|
191
|
+
return scope.isSoleTableView || !scope.tableId
|
|
192
|
+
? key
|
|
193
|
+
: `${scope.tableId}.${key}`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Writes (or, without a value, removes) `key` for this table in the browser's
|
|
198
|
+
* URL in place: no visit, no history entry. Returns the URL written, or
|
|
199
|
+
* `undefined` on a server render.
|
|
200
|
+
*/
|
|
201
|
+
export function writeTableUrlKey(
|
|
202
|
+
scope: TableUrlScope,
|
|
203
|
+
key: string,
|
|
204
|
+
value?: string,
|
|
205
|
+
): URL | undefined {
|
|
206
|
+
if (typeof window === "undefined") return undefined;
|
|
207
|
+
const url = new URL(window.location.href);
|
|
208
|
+
const scopedKey = tableUrlKey(scope, key);
|
|
209
|
+
if (value) url.searchParams.set(scopedKey, value);
|
|
210
|
+
else url.searchParams.delete(scopedKey);
|
|
211
|
+
window.history.replaceState(window.history.state, "", url);
|
|
212
|
+
return url;
|
|
213
|
+
}
|
|
214
|
+
|
|
186
215
|
/**
|
|
187
216
|
* The value the URL gives `key` (`view`, `tab`) for this table: under its
|
|
188
217
|
* prefixed key (`content.view`) or, when it is its page's only table, the
|
|
@@ -267,6 +267,11 @@ const kanbanGroupByOptions = kanbanEligibleColumns.map((column) => ({
|
|
|
267
267
|
const { displays: registeredDisplays, getById } = useTableViewDisplays();
|
|
268
268
|
|
|
269
269
|
const offeredDisplayIds = new Set(resolvedDisplays.map((d) => d.id));
|
|
270
|
+
// Where a stale or unavailable choice lands: the grid, unless the table view
|
|
271
|
+
// drops it, then its default display.
|
|
272
|
+
const fallbackDisplayId = offeredDisplayIds.has(TABLE_DISPLAY_ID)
|
|
273
|
+
? TABLE_DISPLAY_ID
|
|
274
|
+
: defaultDisplay;
|
|
270
275
|
const resolvedDisplay = (id: string): TableViewDisplayConfig | undefined =>
|
|
271
276
|
resolvedDisplays.find((d) => d.id === id);
|
|
272
277
|
const optionsForDisplay = (id: string): Record<string, unknown> | undefined =>
|
|
@@ -293,7 +298,7 @@ const activeDisplayId = ref<string>(
|
|
|
293
298
|
? defaultDisplay
|
|
294
299
|
: offeredDisplayIds.has(persistedDisplay)
|
|
295
300
|
? persistedDisplay
|
|
296
|
-
:
|
|
301
|
+
: fallbackDisplayId,
|
|
297
302
|
);
|
|
298
303
|
|
|
299
304
|
/** A display the backend config renders by itself, with no client plugin. */
|
|
@@ -587,7 +592,7 @@ const {
|
|
|
587
592
|
),
|
|
588
593
|
display: offeredDisplayIds.has(defaultDisplay)
|
|
589
594
|
? defaultDisplay
|
|
590
|
-
:
|
|
595
|
+
: fallbackDisplayId,
|
|
591
596
|
density: props.density ?? DEFAULT_DENSITY,
|
|
592
597
|
displays: offeredDisplayIds,
|
|
593
598
|
},
|
|
@@ -1296,6 +1301,7 @@ const {
|
|
|
1296
1301
|
rowNavigation: {
|
|
1297
1302
|
rows: () => (shownResults.value ?? []) as Data[],
|
|
1298
1303
|
rowIdKey: props.rowIdKey ?? ROW_ID_DEFAULT_KEY,
|
|
1304
|
+
getRow: (id) => tableRows.getRow(id) as Promise<Data | undefined>,
|
|
1299
1305
|
},
|
|
1300
1306
|
recordScope: urlScope,
|
|
1301
1307
|
onRecordShown: (id) => recordLink?.shown(id),
|
|
@@ -1854,6 +1860,7 @@ const displayContext = computed(
|
|
|
1854
1860
|
items: shownResults.value ?? EMPTY_ITEMS,
|
|
1855
1861
|
columns: props.columns,
|
|
1856
1862
|
loading: isListLoading.value,
|
|
1863
|
+
firstPageLoading: isFirstPageLoading.value,
|
|
1857
1864
|
selection: { ids: selectedIds.value, ...displaySelection },
|
|
1858
1865
|
pagination: {
|
|
1859
1866
|
pageIndex: paginationState.value.pageIndex,
|
|
@@ -2070,14 +2077,14 @@ onMounted(() => {
|
|
|
2070
2077
|
checkUrlParameter();
|
|
2071
2078
|
void loadRelationQuickFilters();
|
|
2072
2079
|
void refreshLinkTabCounts();
|
|
2073
|
-
// The registry is client-only; once hydrated, degrade to the
|
|
2074
|
-
// the active id is no longer available (e.g. kanban with no eligible column).
|
|
2080
|
+
// The registry is client-only; once hydrated, degrade to the fallback display
|
|
2081
|
+
// if the active id is no longer available (e.g. kanban with no eligible column).
|
|
2075
2082
|
if (
|
|
2076
|
-
activeDisplayId.value !==
|
|
2083
|
+
activeDisplayId.value !== fallbackDisplayId &&
|
|
2077
2084
|
!isConfigRenderedDisplay(activeDisplayId.value) &&
|
|
2078
2085
|
!availableDisplays.value.some((d) => d.id === activeDisplayId.value)
|
|
2079
2086
|
) {
|
|
2080
|
-
activeDisplayId.value =
|
|
2087
|
+
activeDisplayId.value = fallbackDisplayId;
|
|
2081
2088
|
}
|
|
2082
2089
|
});
|
|
2083
2090
|
</script>
|
|
@@ -2123,6 +2130,7 @@ onMounted(() => {
|
|
|
2123
2130
|
:tabs="tabsWithCount"
|
|
2124
2131
|
:initial-column-visibility="initialVisibility"
|
|
2125
2132
|
:loading="isListLoading"
|
|
2133
|
+
:first-page-loading="isFirstPageLoading"
|
|
2126
2134
|
:load-error="listLoadError"
|
|
2127
2135
|
:data="shownResults || []"
|
|
2128
2136
|
:pagination-options="{ manualPagination: true, rowCount: data?.total }"
|
|
@@ -296,6 +296,8 @@ export interface TableViewConfig<T extends Data>
|
|
|
296
296
|
tabs?: TableViewTab[];
|
|
297
297
|
/** Displays this table view offers, beyond the implicit built-in `table`. */
|
|
298
298
|
displays?: TableViewDisplayConfig[];
|
|
299
|
+
/** Whether the built-in `table` display is offered. Defaults to `true`. */
|
|
300
|
+
tableDisplay?: boolean;
|
|
299
301
|
/** Display shown by default when the user has no saved preference. Defaults to "table". */
|
|
300
302
|
defaultDisplay?: string;
|
|
301
303
|
/** Expandable rows: caret column + detail band. */
|
|
@@ -214,7 +214,13 @@ export interface TableViewDisplayContext<T = Record<string, unknown>> {
|
|
|
214
214
|
items: T[];
|
|
215
215
|
/** Full column metadata (types, labels, accessor keys) — for field rendering. */
|
|
216
216
|
columns: TableViewColumn[];
|
|
217
|
+
/** The shared query is in flight: a first read or any re-read. */
|
|
217
218
|
loading: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* No answer has arrived yet: draw a skeleton. A re-read keeps the rows,
|
|
221
|
+
* or the empty state, on screen; swapping either for a skeleton flashes.
|
|
222
|
+
*/
|
|
223
|
+
firstPageLoading: boolean;
|
|
218
224
|
|
|
219
225
|
selection: TableViewDisplaySelection;
|
|
220
226
|
pagination: TableViewDisplayPagination;
|
|
@@ -188,7 +188,12 @@ interface Mounted {
|
|
|
188
188
|
showTable: Ref<boolean>;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
type ReadRow = (id: string) => Promise<Row | undefined>;
|
|
192
|
+
|
|
193
|
+
function mountPanel(
|
|
194
|
+
shownRows: Ref<Row[]> = ref(rows),
|
|
195
|
+
getRow?: ReadRow,
|
|
196
|
+
): Mounted {
|
|
192
197
|
let targets: ReturnType<typeof useActionTargets> | undefined;
|
|
193
198
|
const showTable = ref(true);
|
|
194
199
|
const Table = defineComponent({
|
|
@@ -201,7 +206,11 @@ function mountPanel(shownRows: Ref<Row[]> = ref(rows)): Mounted {
|
|
|
201
206
|
refreshCallback: () => {
|
|
202
207
|
refreshes += 1;
|
|
203
208
|
},
|
|
204
|
-
rowNavigation: {
|
|
209
|
+
rowNavigation: {
|
|
210
|
+
rows: () => shownRows.value,
|
|
211
|
+
rowIdKey: "_id",
|
|
212
|
+
getRow,
|
|
213
|
+
},
|
|
205
214
|
recordScope: { tableId: "requests", isSoleTableView: true },
|
|
206
215
|
});
|
|
207
216
|
return () => h("table");
|
|
@@ -480,6 +489,88 @@ describe("deep link to a row the table does not list", () => {
|
|
|
480
489
|
});
|
|
481
490
|
});
|
|
482
491
|
|
|
492
|
+
describe("showing another row from the panel", () => {
|
|
493
|
+
const older: Row = { _id: "r9", name: "Older" };
|
|
494
|
+
const notFoundError = () =>
|
|
495
|
+
Object.assign(new Error("Not Found"), { statusCode: 404 });
|
|
496
|
+
const showRow = (rowOrId: Row | string) =>
|
|
497
|
+
(
|
|
498
|
+
useRowSidePanelContent().value?.componentOptions.showRow as (
|
|
499
|
+
rowOrId: Row | string,
|
|
500
|
+
) => Promise<void>
|
|
501
|
+
)(rowOrId);
|
|
502
|
+
|
|
503
|
+
it("moves the highlight, the position and ?record= onto a listed row", async () => {
|
|
504
|
+
const { host, targets } = mountPanel();
|
|
505
|
+
targets.handleCustomRowAction(panelAction(), rows[0]);
|
|
506
|
+
await settle();
|
|
507
|
+
await showRow("r3");
|
|
508
|
+
await settle();
|
|
509
|
+
expect(shownName(host)).toBe("Third");
|
|
510
|
+
expect(position(host)).toBe("side_panel.position(3/3)");
|
|
511
|
+
expect(useRowSidePanelContent().value?.rowKey).toBe("r3");
|
|
512
|
+
expect(window.location.search).toBe("?record=r3");
|
|
513
|
+
await showRow(rows[1]!);
|
|
514
|
+
await settle();
|
|
515
|
+
expect(position(host)).toBe("side_panel.position(2/3)");
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it("reads an unlisted row by id, shown without a position", async () => {
|
|
519
|
+
const getRow = vi.fn(async () => older);
|
|
520
|
+
const { host, targets } = mountPanel(ref(rows), getRow);
|
|
521
|
+
targets.handleCustomRowAction(panelAction(), rows[0]);
|
|
522
|
+
await settle();
|
|
523
|
+
await showRow("r9");
|
|
524
|
+
await settle();
|
|
525
|
+
expect(getRow).toHaveBeenCalledWith("r9");
|
|
526
|
+
expect(shownName(host)).toBe("Older");
|
|
527
|
+
expect(position(host)).toBeUndefined();
|
|
528
|
+
expect(useRowSidePanelContent().value?.rowKey).toBe("r9");
|
|
529
|
+
expect(window.location.search).toBe("?record=r9");
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
it("says a row its route answers 404 for is gone", async () => {
|
|
533
|
+
const { host, targets } = mountPanel(ref(rows), async () => {
|
|
534
|
+
throw notFoundError();
|
|
535
|
+
});
|
|
536
|
+
targets.handleCustomRowAction(panelAction(), rows[0]);
|
|
537
|
+
await settle();
|
|
538
|
+
await showRow("gone");
|
|
539
|
+
await settle();
|
|
540
|
+
expect(query(host, "[data-dms-row-side-panel-not-found]")).not.toBeNull();
|
|
541
|
+
expect(useRowSidePanelContent().value?.rowKey).toBeUndefined();
|
|
542
|
+
expect(window.location.search).toBe("?record=gone");
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
it("rejects a row it cannot read, keeping the row it shows", async () => {
|
|
546
|
+
const { host, targets } = mountPanel();
|
|
547
|
+
targets.handleCustomRowAction(panelAction(), rows[0]);
|
|
548
|
+
await settle();
|
|
549
|
+
await expect(showRow("r9")).rejects.toThrow("r9");
|
|
550
|
+
await settle();
|
|
551
|
+
expect(shownName(host)).toBe("First");
|
|
552
|
+
expect(window.location.search).toBe("?record=r1");
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it("leaves the panel shut when it closed while the row was read", async () => {
|
|
556
|
+
let answer!: (row: Row) => void;
|
|
557
|
+
const { host, targets } = mountPanel(
|
|
558
|
+
ref(rows),
|
|
559
|
+
() => new Promise((resolve) => (answer = resolve)),
|
|
560
|
+
);
|
|
561
|
+
targets.handleCustomRowAction(panelAction(), rows[0]);
|
|
562
|
+
await settle();
|
|
563
|
+
const shown = showRow("r9");
|
|
564
|
+
closeRowSidePanel();
|
|
565
|
+
answer(older);
|
|
566
|
+
await shown;
|
|
567
|
+
await settle();
|
|
568
|
+
expect(useRowSidePanelContent().value).toBeNull();
|
|
569
|
+
expect(query(host, "[data-dms-side-panel]")).toBeNull();
|
|
570
|
+
expect(window.location.search).toBe("");
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
|
|
483
574
|
describe("side panel on a missing row", () => {
|
|
484
575
|
const notFound = (host: ParentNode) =>
|
|
485
576
|
query(host, "[data-dms-row-side-panel-not-found]");
|
|
@@ -313,6 +313,120 @@ describe("action targets on a selection and on a listed row", () => {
|
|
|
313
313
|
expect(drawer!.patches).toHaveLength(1);
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
+
it("shows another row in a row's drawer by id, read when unlisted", async () => {
|
|
317
|
+
window.history.replaceState(null, "", "/runs");
|
|
318
|
+
const rows = [{ _id: "r1" }, { _id: "r2" }];
|
|
319
|
+
const older = { _id: "r9" };
|
|
320
|
+
const getRow = vi.fn(async (id: string) =>
|
|
321
|
+
id === "r9" ? older : undefined,
|
|
322
|
+
);
|
|
323
|
+
const targets = mountTargets({
|
|
324
|
+
rowNavigation: { rows: () => rows, rowIdKey: "_id", getRow },
|
|
325
|
+
recordScope: { tableId: "runs", isSoleTableView: true },
|
|
326
|
+
});
|
|
327
|
+
targets.handleCustomRowAction(
|
|
328
|
+
{
|
|
329
|
+
label: "Details",
|
|
330
|
+
deepLink: true,
|
|
331
|
+
target: { type: "drawer", component: { componentName: "RunDrawer" } },
|
|
332
|
+
},
|
|
333
|
+
rows[0],
|
|
334
|
+
);
|
|
335
|
+
await vi.waitFor(() => expect(drawers).toHaveLength(1));
|
|
336
|
+
const [drawer] = drawers;
|
|
337
|
+
const options = drawer!.options.componentOptions as Record<string, unknown>;
|
|
338
|
+
const showRow = options.showRow as (row: object | string) => Promise<void>;
|
|
339
|
+
|
|
340
|
+
await showRow("r9");
|
|
341
|
+
expect(drawer!.patches[0]).toMatchObject({ componentKey: "r9" });
|
|
342
|
+
const patched = drawer!.patches[0]!.componentOptions as Record<
|
|
343
|
+
string,
|
|
344
|
+
unknown
|
|
345
|
+
>;
|
|
346
|
+
expect(patched.rowData).toBe(older);
|
|
347
|
+
expect(patched.navigation).toBeUndefined();
|
|
348
|
+
expect(window.location.search).toBe("?record=r9");
|
|
349
|
+
|
|
350
|
+
await showRow("r2");
|
|
351
|
+
expect(getRow).toHaveBeenCalledTimes(1);
|
|
352
|
+
expect(drawer!.patches[1]).toMatchObject({ componentKey: "r2" });
|
|
353
|
+
expect(window.location.search).toBe("?record=r2");
|
|
354
|
+
|
|
355
|
+
await expect(showRow("r404")).rejects.toThrow("r404");
|
|
356
|
+
expect(drawer!.patches).toHaveLength(2);
|
|
357
|
+
drawer!.settle();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
const deferredRows = () => {
|
|
361
|
+
const pending = new Map<string, (row: object) => void>();
|
|
362
|
+
const getRow = vi.fn(
|
|
363
|
+
(id: string) =>
|
|
364
|
+
new Promise<object | undefined>((resolve) => pending.set(id, resolve)),
|
|
365
|
+
);
|
|
366
|
+
return { getRow, resolve: (id: string) => pending.get(id)!({ _id: id }) };
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const openDeepLinkedDrawer = (getRow: (id: string) => Promise<unknown>) => {
|
|
370
|
+
window.history.replaceState(null, "", "/runs");
|
|
371
|
+
const rows = [{ _id: "r1" }];
|
|
372
|
+
const targets = mountTargets({
|
|
373
|
+
rowNavigation: { rows: () => rows, rowIdKey: "_id", getRow },
|
|
374
|
+
recordScope: { tableId: "runs", isSoleTableView: true },
|
|
375
|
+
onRecordShown: vi.fn(),
|
|
376
|
+
});
|
|
377
|
+
targets.handleCustomRowAction(
|
|
378
|
+
{
|
|
379
|
+
label: "Details",
|
|
380
|
+
deepLink: true,
|
|
381
|
+
target: { type: "drawer", component: { componentName: "RunDrawer" } },
|
|
382
|
+
},
|
|
383
|
+
rows[0],
|
|
384
|
+
);
|
|
385
|
+
return targets;
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const showRowOf = (drawer: (typeof drawers)[number]) =>
|
|
389
|
+
(drawer.options.componentOptions as Record<string, unknown>).showRow as (
|
|
390
|
+
row: object | string,
|
|
391
|
+
) => Promise<void>;
|
|
392
|
+
|
|
393
|
+
it("drops a row read that resolves after its drawer closed", async () => {
|
|
394
|
+
const rows = deferredRows();
|
|
395
|
+
openDeepLinkedDrawer(rows.getRow);
|
|
396
|
+
await vi.waitFor(() => expect(drawers).toHaveLength(1));
|
|
397
|
+
const [drawer] = drawers;
|
|
398
|
+
const shown = showRowOf(drawer!)("r9");
|
|
399
|
+
|
|
400
|
+
drawer!.settle();
|
|
401
|
+
await vi.waitFor(() => expect(window.location.search).toBe(""));
|
|
402
|
+
rows.resolve("r9");
|
|
403
|
+
await shown;
|
|
404
|
+
|
|
405
|
+
expect(window.location.search).toBe("");
|
|
406
|
+
expect(drawer!.patches).toHaveLength(0);
|
|
407
|
+
expect(drawers).toHaveLength(1);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it("applies only the latest of two rows read at once", async () => {
|
|
411
|
+
const rows = deferredRows();
|
|
412
|
+
openDeepLinkedDrawer(rows.getRow);
|
|
413
|
+
await vi.waitFor(() => expect(drawers).toHaveLength(1));
|
|
414
|
+
const [drawer] = drawers;
|
|
415
|
+
const showRow = showRowOf(drawer!);
|
|
416
|
+
const first = showRow("r8");
|
|
417
|
+
const second = showRow("r9");
|
|
418
|
+
|
|
419
|
+
rows.resolve("r9");
|
|
420
|
+
await second;
|
|
421
|
+
rows.resolve("r8");
|
|
422
|
+
await first;
|
|
423
|
+
|
|
424
|
+
expect(drawer!.patches).toHaveLength(1);
|
|
425
|
+
expect(drawer!.patches[0]).toMatchObject({ componentKey: "r9" });
|
|
426
|
+
expect(window.location.search).toBe("?record=r9");
|
|
427
|
+
drawer!.settle();
|
|
428
|
+
});
|
|
429
|
+
|
|
316
430
|
it("hands a bulk drawer the selection instead of a row", async () => {
|
|
317
431
|
const targets = mountTargets();
|
|
318
432
|
targets.handleBulkCustomAction(
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { computed, createApp, h, reactive, ref, type App } from "vue";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import CardsDisplay from "../layers/dms-ui/app/build/components/table-view/CardsDisplay.vue";
|
|
5
|
+
import type { TableViewDisplayContext } from "../layers/dms-ui/app/composables/table-view/types/display";
|
|
6
|
+
|
|
7
|
+
vi.mock("../layers/dms-ui/app/build/components/table/Pagination.vue", () => ({
|
|
8
|
+
default: { render: () => null },
|
|
9
|
+
}));
|
|
10
|
+
vi.mock("../layers/dms-ui/app/build/components/table/Empty.vue", () => ({
|
|
11
|
+
default: { render: () => h("p", { "data-test": "empty" }) },
|
|
12
|
+
}));
|
|
13
|
+
vi.mock(
|
|
14
|
+
"../layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue",
|
|
15
|
+
() => ({ default: { render: () => h("p", { "data-test": "skeleton" }) } }),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
interface ReadState {
|
|
19
|
+
loading: boolean;
|
|
20
|
+
firstPageLoading: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createContext(state: ReadState) {
|
|
24
|
+
return reactive({
|
|
25
|
+
items: [],
|
|
26
|
+
columns: [],
|
|
27
|
+
...state,
|
|
28
|
+
rowIdKey: "_id",
|
|
29
|
+
labelKey: "name",
|
|
30
|
+
options: {},
|
|
31
|
+
pagination: { pageIndex: 0, pageSize: 10, total: 0 },
|
|
32
|
+
selection: { isSelected: () => false, toggle: () => {} },
|
|
33
|
+
actions: { canAdd: false, open: () => {} },
|
|
34
|
+
}) as unknown as TableViewDisplayContext;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("the cards display of an empty list", () => {
|
|
38
|
+
let app: App | undefined;
|
|
39
|
+
let container: HTMLElement;
|
|
40
|
+
|
|
41
|
+
const mount = (context: TableViewDisplayContext) => {
|
|
42
|
+
app = createApp({ render: () => h(CardsDisplay, { context }) });
|
|
43
|
+
container = document.createElement("div");
|
|
44
|
+
document.body.append(container);
|
|
45
|
+
app.mount(container);
|
|
46
|
+
};
|
|
47
|
+
const shown = (test: string) =>
|
|
48
|
+
container.querySelector(`[data-test="${test}"]`) !== null;
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
vi.stubGlobal("computed", computed);
|
|
52
|
+
vi.stubGlobal("h", h);
|
|
53
|
+
vi.stubGlobal("useI18n", () => ({ locale: ref("en"), t: (t: string) => t }));
|
|
54
|
+
vi.stubGlobal("useTranslation", () => ({ processI18n: (t: string) => t }));
|
|
55
|
+
vi.stubGlobal("useDataTypes", () => ({ getDataType: () => undefined }));
|
|
56
|
+
vi.stubGlobal("resolveDmsComponent", () => undefined);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
app?.unmount();
|
|
61
|
+
app = undefined;
|
|
62
|
+
container.remove();
|
|
63
|
+
vi.unstubAllGlobals();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("draws the skeleton until the first answer arrives", () => {
|
|
67
|
+
mount(createContext({ loading: true, firstPageLoading: true }));
|
|
68
|
+
expect(shown("skeleton")).toBe(true);
|
|
69
|
+
expect(shown("empty")).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("keeps the empty state on screen while the list is read again", () => {
|
|
73
|
+
mount(createContext({ loading: true, firstPageLoading: false }));
|
|
74
|
+
expect(shown("empty")).toBe(true);
|
|
75
|
+
expect(shown("skeleton")).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -3,18 +3,32 @@
|
|
|
3
3
|
* A table view opens the tab its URL names (`?<tableId>.tab=`, or `?tab=` on
|
|
4
4
|
* a page with a single table view), on arrival and afterwards: a link or a
|
|
5
5
|
* `router.replace` naming another tab switches to it in place, without
|
|
6
|
-
* remounting the page.
|
|
6
|
+
* remounting the page. A tab the user opens is written back to the URL in
|
|
7
|
+
* place, under the same key.
|
|
7
8
|
*/
|
|
8
9
|
import { readFileSync } from "node:fs";
|
|
9
10
|
import { resolve } from "node:path";
|
|
10
11
|
import { createApp, defineComponent, h, nextTick, reactive, ref } from "vue";
|
|
11
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
12
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
12
13
|
import {
|
|
13
14
|
readTableUrlTab,
|
|
14
15
|
useTableUrlTab,
|
|
15
16
|
} from "../layers/dms-ui/app/build/composables/table-view/useTableUrlTab";
|
|
16
17
|
import type { TableUrlScope } from "../layers/dms-ui/app/build/composables/table-view/utils/views";
|
|
17
18
|
|
|
19
|
+
type NavigateListener = (event: { detail: { page: { url: string } } }) => void;
|
|
20
|
+
const navigateListeners = new Set<NavigateListener>();
|
|
21
|
+
|
|
22
|
+
vi.mock("@inertiajs/vue3", () => ({
|
|
23
|
+
router: {
|
|
24
|
+
on: (type: string, listener: NavigateListener) => {
|
|
25
|
+
if (type !== "navigate") return () => {};
|
|
26
|
+
navigateListeners.add(listener);
|
|
27
|
+
return () => navigateListeners.delete(listener);
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}));
|
|
31
|
+
|
|
18
32
|
const OPENABLE_TABS = new Set(["all", "active", "archived"]);
|
|
19
33
|
const mounted: Array<{ unmount: () => void }> = [];
|
|
20
34
|
|
|
@@ -39,10 +53,23 @@ function mountTable(scope: TableUrlScope, query: Record<string, string>) {
|
|
|
39
53
|
return { route, activeTabId };
|
|
40
54
|
}
|
|
41
55
|
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
window.history.replaceState(null, "", "/runs");
|
|
58
|
+
});
|
|
59
|
+
|
|
42
60
|
afterEach(() => {
|
|
43
61
|
mounted.splice(0).forEach((app) => app.unmount());
|
|
44
62
|
});
|
|
45
63
|
|
|
64
|
+
/** A visit of the page already shown: Inertia announces its URL. */
|
|
65
|
+
async function visit(url: string) {
|
|
66
|
+
window.history.pushState(null, "", url);
|
|
67
|
+
navigateListeners.forEach((listener) =>
|
|
68
|
+
listener({ detail: { page: { url } } }),
|
|
69
|
+
);
|
|
70
|
+
await nextTick();
|
|
71
|
+
}
|
|
72
|
+
|
|
46
73
|
describe("the tab a URL names", () => {
|
|
47
74
|
it("opens on arrival", () => {
|
|
48
75
|
const { activeTabId } = mountTable(
|
|
@@ -102,6 +129,61 @@ describe("the tab a URL names", () => {
|
|
|
102
129
|
});
|
|
103
130
|
});
|
|
104
131
|
|
|
132
|
+
describe("the tab the user opens", () => {
|
|
133
|
+
it("is written to the short key in place on a single table view", async () => {
|
|
134
|
+
window.history.replaceState(null, "", "/runs?page=2");
|
|
135
|
+
const { activeTabId } = mountTable(
|
|
136
|
+
{ tableId: "runs", isSoleTableView: true },
|
|
137
|
+
{},
|
|
138
|
+
);
|
|
139
|
+
const entries = window.history.length;
|
|
140
|
+
activeTabId.value = "archived";
|
|
141
|
+
await nextTick();
|
|
142
|
+
expect(window.location.search).toBe("?page=2&tab=archived");
|
|
143
|
+
expect(window.history.length).toBe(entries);
|
|
144
|
+
activeTabId.value = "all";
|
|
145
|
+
await nextTick();
|
|
146
|
+
expect(window.location.search).toBe("?page=2&tab=all");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("is written to the table's own key on a page with several tables", async () => {
|
|
150
|
+
window.history.replaceState(null, "", "/runs?jobs.tab=late");
|
|
151
|
+
const { activeTabId } = mountTable({ tableId: "runs" }, {});
|
|
152
|
+
activeTabId.value = "active";
|
|
153
|
+
await nextTick();
|
|
154
|
+
expect(window.location.search).toBe("?jobs.tab=late&runs.tab=active");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("leaves the URL alone for a tab it cannot open in place", async () => {
|
|
158
|
+
const { activeTabId } = mountTable({ tableId: "runs" }, {});
|
|
159
|
+
activeTabId.value = "docs";
|
|
160
|
+
await nextTick();
|
|
161
|
+
expect(window.location.search).toBe("");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("gives way to a link back to the tab the page was opened on", async () => {
|
|
165
|
+
window.history.replaceState(null, "", "/runs?runs.tab=active");
|
|
166
|
+
const { route, activeTabId } = mountTable(
|
|
167
|
+
{ tableId: "runs" },
|
|
168
|
+
{ "runs.tab": "active" },
|
|
169
|
+
);
|
|
170
|
+
activeTabId.value = "archived";
|
|
171
|
+
await nextTick();
|
|
172
|
+
expect(window.location.search).toBe("?runs.tab=archived");
|
|
173
|
+
// The route still holds the arrival's tab: only the visit tells.
|
|
174
|
+
await visit("/runs?runs.tab=active");
|
|
175
|
+
expect(route.query["runs.tab"]).toBe("active");
|
|
176
|
+
expect(activeTabId.value).toBe("active");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("stops following visits once the table is gone", async () => {
|
|
180
|
+
const { activeTabId } = mountTable({ tableId: "runs" }, {});
|
|
181
|
+
mounted.splice(0).forEach((app) => app.unmount());
|
|
182
|
+
await visit("/runs?runs.tab=archived");
|
|
183
|
+
expect(activeTabId.value).toBe("all");
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
105
187
|
it("wires the URL tab into the table view", () => {
|
|
106
188
|
const source = readFileSync(
|
|
107
189
|
resolve(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/dms",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.21",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/AntelopeJS/dms.git"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@antelopejs/interface-data-api": ">=0.2.0 <1.0.0",
|
|
38
38
|
"@antelopejs/interface-database": ">=0.1.8 <1.0.0",
|
|
39
39
|
"@antelopejs/interface-database-decorators": ">=0.1.7 <1.0.0",
|
|
40
|
-
"@antelopejs/interface-dms": ">=0.5.
|
|
40
|
+
"@antelopejs/interface-dms": ">=0.5.13 <0.6.0",
|
|
41
41
|
"@antelopejs/interface-email": ">=0.0.5 <1.0.0",
|
|
42
42
|
"@antelopejs/interface-file-storage": ">=0.1.3 <1.0.0",
|
|
43
43
|
"archiver": "^7.0.1",
|