@antelopejs/dms 0.3.7 → 0.4.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/CHANGELOG.md +57 -0
- package/dist/implementations/dms/guards.d.ts +1 -1
- package/dist/implementations/dms/page.js +2 -2
- package/dist/implementations/dms/page.js.map +1 -1
- package/dist/implementations/dms-base/table-view.d.ts +1 -1
- package/dist/pages/settings/users/category.d.ts +1 -1
- package/dist/pages/settings/users/members.d.ts +2 -2
- package/dist/pages/settings/users/notifications.d.ts +2 -2
- package/dist/test/antelope.test.js +16 -5
- package/dist/test/antelope.test.js.map +1 -1
- package/dist/test/api-endpoint/index.d.ts +5 -0
- package/dist/test/api-endpoint/index.js +8 -0
- package/dist/test/api-endpoint/index.js.map +1 -0
- package/dist/test/attachment-host/native.d.ts +2 -2
- package/dist/test/helpers/http.d.ts +1 -0
- package/dist/test/helpers/http.js +16 -4
- package/dist/test/helpers/http.js.map +1 -1
- package/dist/test/unit/implementations/dms/notify-menu-changed.test.js +21 -0
- package/dist/test/unit/implementations/dms/notify-menu-changed.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-form-page-urls.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-form-page-urls.test.js +308 -0
- package/dist/test/unit/interfaces/dms-base/table-view-form-page-urls.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.js +241 -0
- package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-route-param-filter-defaults.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-route-param-filter-defaults.test.js +254 -0
- package/dist/test/unit/interfaces/dms-base/table-view-route-param-filter-defaults.test.js.map +1 -0
- package/dist/validation/auth.schema.d.ts +18 -18
- package/dist/validation/onboarding/register-admin.schema.d.ts +3 -3
- package/frontend-vue/layers/dms-layout/app/composables/page/useSiteLayout.ts +49 -20
- package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +6 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +2 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +13 -7
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/registerDefaultFunctions.ts +49 -20
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +43 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +23 -29
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +3 -0
- package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +35 -25
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +5 -1
- package/frontend-vue/pnpm-lock.yaml +4 -4
- package/frontend-vue/tests/form-page-url-fill.test.ts +63 -0
- package/frontend-vue/tests/form-redirect-placeholders.test.ts +69 -0
- package/frontend-vue/tests/route-param-filter-defaults.test.ts +59 -0
- package/frontend-vue/tests/route-param-occurrences.test.ts +109 -0
- package/package.json +8 -19
- package/skills/dms/REFERENCE.md +2 -3
- package/skills/dms/SKILL.md +1 -1
- package/skills/dms-module/REFERENCE.md +4 -5
- package/skills/dms-module/SKILL.md +1 -1
- package/frontend-vue/tests/theming-browser.mjs +0 -130
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
const interface_api_1 = require("@antelopejs/interface-api");
|
|
46
|
+
const interface_core_1 = require("@antelopejs/interface-core");
|
|
47
|
+
const interface_data_api_1 = require("@antelopejs/interface-data-api");
|
|
48
|
+
const metadata_1 = require("@antelopejs/interface-data-api/metadata");
|
|
49
|
+
const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
|
|
50
|
+
const chai_1 = require("chai");
|
|
51
|
+
const pageImpl = __importStar(require("../../../../implementations/dms/page"));
|
|
52
|
+
const permissionsImpl = __importStar(require("../../../../implementations/dms/permissions"));
|
|
53
|
+
const realtimeImpl = __importStar(require("../../../../implementations/dms/realtime"));
|
|
54
|
+
const constants_1 = require("@antelopejs/interface-dms/constants");
|
|
55
|
+
const pageInterface = __importStar(require("@antelopejs/interface-dms/page"));
|
|
56
|
+
const page_1 = require("@antelopejs/interface-dms/page");
|
|
57
|
+
const registry_1 = require("@antelopejs/interface-dms/page/registry");
|
|
58
|
+
const permissionsInterface = __importStar(require("@antelopejs/interface-dms/permissions"));
|
|
59
|
+
const realtimeInterface = __importStar(require("@antelopejs/interface-dms/realtime"));
|
|
60
|
+
const default_types_1 = require("@antelopejs/interface-dms/base/data-types/default-types");
|
|
61
|
+
const table_view_1 = require("@antelopejs/interface-dms/base/table-view");
|
|
62
|
+
const TABLE = "route-param-filter-documents";
|
|
63
|
+
const LOCATION = "/api/route-param-filter-defaults";
|
|
64
|
+
function settle() {
|
|
65
|
+
return new Promise((resolve) => setImmediate(resolve));
|
|
66
|
+
}
|
|
67
|
+
let Document = class Document extends interface_database_decorators_1.Table {
|
|
68
|
+
};
|
|
69
|
+
__decorate([
|
|
70
|
+
(0, interface_database_decorators_1.Field)("string"),
|
|
71
|
+
__metadata("design:type", String)
|
|
72
|
+
], Document.prototype, "name", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, interface_database_decorators_1.Field)("string"),
|
|
75
|
+
__metadata("design:type", String)
|
|
76
|
+
], Document.prototype, "_instance", void 0);
|
|
77
|
+
Document = __decorate([
|
|
78
|
+
(0, interface_database_decorators_1.RegisterTable)(TABLE, constants_1.CORE_SCHEMA_NAME)
|
|
79
|
+
], Document);
|
|
80
|
+
class DocumentModel extends (0, interface_database_decorators_1.BasicDataModel)(Document, TABLE) {
|
|
81
|
+
}
|
|
82
|
+
let DocumentAPI = class DocumentAPI extends (0, interface_data_api_1.DataController)(Document, { new: table_view_1.TableViewRoutes.New, edit: table_view_1.TableViewRoutes.Edit }, (0, interface_api_1.Controller)(LOCATION)) {
|
|
83
|
+
};
|
|
84
|
+
__decorate([
|
|
85
|
+
(0, metadata_1.ModelReference)(),
|
|
86
|
+
(0, interface_database_decorators_1.Model)(DocumentModel),
|
|
87
|
+
__metadata("design:type", DocumentModel)
|
|
88
|
+
], DocumentAPI.prototype, "model", void 0);
|
|
89
|
+
__decorate([
|
|
90
|
+
(0, table_view_1.Column)({ name: "Name", type: new default_types_1.DefaultDataTypes.StringType() }),
|
|
91
|
+
(0, metadata_1.Access)(metadata_1.AccessMode.ReadWrite),
|
|
92
|
+
__metadata("design:type", String)
|
|
93
|
+
], DocumentAPI.prototype, "name", void 0);
|
|
94
|
+
DocumentAPI = __decorate([
|
|
95
|
+
(0, interface_data_api_1.RegisterDataController)()
|
|
96
|
+
], DocumentAPI);
|
|
97
|
+
const ROUTE_FILTER = { id: { field: "_instance" } };
|
|
98
|
+
const QUERY_FILTER = { status: { field: "status" } };
|
|
99
|
+
const detailTable = (0, table_view_1.TableView)(DocumentAPI, {
|
|
100
|
+
formContainer: { type: "page" },
|
|
101
|
+
routeParamFilters: ROUTE_FILTER,
|
|
102
|
+
queryParamFilters: QUERY_FILTER,
|
|
103
|
+
realtime: false,
|
|
104
|
+
});
|
|
105
|
+
const namedParamTable = (0, table_view_1.TableView)(DocumentAPI, {
|
|
106
|
+
formContainer: { type: "page" },
|
|
107
|
+
routeParamFilters: { workspace: { field: "_instance" } },
|
|
108
|
+
realtime: false,
|
|
109
|
+
});
|
|
110
|
+
const deepTable = (0, table_view_1.TableView)(DocumentAPI, {
|
|
111
|
+
formContainer: { type: "page" },
|
|
112
|
+
routeParamFilters: ROUTE_FILTER,
|
|
113
|
+
realtime: false,
|
|
114
|
+
});
|
|
115
|
+
const topLevelTable = (0, table_view_1.TableView)(DocumentAPI, {
|
|
116
|
+
formContainer: { type: "page" },
|
|
117
|
+
routeParamFilters: ROUTE_FILTER,
|
|
118
|
+
realtime: false,
|
|
119
|
+
});
|
|
120
|
+
const unfilteredTable = (0, table_view_1.TableView)(DocumentAPI, {
|
|
121
|
+
formContainer: { type: "page" },
|
|
122
|
+
realtime: false,
|
|
123
|
+
});
|
|
124
|
+
const drawerTable = (0, table_view_1.TableView)(DocumentAPI, {
|
|
125
|
+
formContainer: { type: "drawer" },
|
|
126
|
+
routeParamFilters: ROUTE_FILTER,
|
|
127
|
+
realtime: false,
|
|
128
|
+
});
|
|
129
|
+
let DetailPage = class DetailPage extends (0, page_1.RootPageController)("rpf-detail", {
|
|
130
|
+
displayName: "Detail of a workspace",
|
|
131
|
+
urlSlug: "rpf-detail/:id",
|
|
132
|
+
}) {
|
|
133
|
+
static rows = detailTable;
|
|
134
|
+
};
|
|
135
|
+
DetailPage = __decorate([
|
|
136
|
+
(0, page_1.RegisterPage)()
|
|
137
|
+
], DetailPage);
|
|
138
|
+
let NamedParamPage = class NamedParamPage extends (0, page_1.RootPageController)("rpf-named", {
|
|
139
|
+
displayName: "Detail with a placeholder of its own name",
|
|
140
|
+
urlSlug: "rpf-named/:workspace",
|
|
141
|
+
}) {
|
|
142
|
+
static rows = namedParamTable;
|
|
143
|
+
};
|
|
144
|
+
NamedParamPage = __decorate([
|
|
145
|
+
(0, page_1.RegisterPage)()
|
|
146
|
+
], NamedParamPage);
|
|
147
|
+
let DeepPage = class DeepPage extends (0, page_1.RootPageController)("rpf-deep", {
|
|
148
|
+
displayName: "Page repeating its own placeholder",
|
|
149
|
+
urlSlug: "rpf-deep/:id/sub/:id",
|
|
150
|
+
}) {
|
|
151
|
+
static rows = deepTable;
|
|
152
|
+
};
|
|
153
|
+
DeepPage = __decorate([
|
|
154
|
+
(0, page_1.RegisterPage)()
|
|
155
|
+
], DeepPage);
|
|
156
|
+
let TopLevelPage = class TopLevelPage extends (0, page_1.RootPageController)("rpf-top", {
|
|
157
|
+
displayName: "Page without a route parameter",
|
|
158
|
+
}) {
|
|
159
|
+
static rows = topLevelTable;
|
|
160
|
+
};
|
|
161
|
+
TopLevelPage = __decorate([
|
|
162
|
+
(0, page_1.RegisterPage)()
|
|
163
|
+
], TopLevelPage);
|
|
164
|
+
let UnfilteredPage = class UnfilteredPage extends (0, page_1.RootPageController)("rpf-unfiltered", {
|
|
165
|
+
displayName: "Table view without URL filters",
|
|
166
|
+
}) {
|
|
167
|
+
static rows = unfilteredTable;
|
|
168
|
+
};
|
|
169
|
+
UnfilteredPage = __decorate([
|
|
170
|
+
(0, page_1.RegisterPage)()
|
|
171
|
+
], UnfilteredPage);
|
|
172
|
+
let DrawerPage = class DrawerPage extends (0, page_1.RootPageController)("rpf-drawer", {
|
|
173
|
+
displayName: "Drawer form container",
|
|
174
|
+
urlSlug: "rpf-drawer/:id",
|
|
175
|
+
}) {
|
|
176
|
+
static rows = drawerTable;
|
|
177
|
+
};
|
|
178
|
+
DrawerPage = __decorate([
|
|
179
|
+
(0, page_1.RegisterPage)()
|
|
180
|
+
], DrawerPage);
|
|
181
|
+
const pages = [
|
|
182
|
+
DetailPage,
|
|
183
|
+
NamedParamPage,
|
|
184
|
+
DeepPage,
|
|
185
|
+
TopLevelPage,
|
|
186
|
+
UnfilteredPage,
|
|
187
|
+
DrawerPage,
|
|
188
|
+
];
|
|
189
|
+
async function formPageOptions(formPageFullId) {
|
|
190
|
+
const form = registry_1.pageMetadataByFullId.get(formPageFullId)?.components.form;
|
|
191
|
+
if (!form)
|
|
192
|
+
throw new Error(`No form page registered as ${formPageFullId}`);
|
|
193
|
+
return (await form.serialize()).options;
|
|
194
|
+
}
|
|
195
|
+
async function formComponents(table) {
|
|
196
|
+
return (await table.serialize()).options?.formComponents;
|
|
197
|
+
}
|
|
198
|
+
describe("[unit] interfaces/dms-base — route param filter form defaults", () => {
|
|
199
|
+
before(async () => {
|
|
200
|
+
(0, interface_core_1.ImplementInterface)(permissionsInterface, permissionsImpl);
|
|
201
|
+
(0, interface_core_1.ImplementInterface)(realtimeInterface, realtimeImpl);
|
|
202
|
+
(0, interface_core_1.ImplementInterface)(pageInterface, pageImpl);
|
|
203
|
+
await settle();
|
|
204
|
+
});
|
|
205
|
+
after(() => {
|
|
206
|
+
for (const page of pages) {
|
|
207
|
+
const { pageInfo } = (0, interface_core_1.GetMetadata)(page, page_1.PageMetadata);
|
|
208
|
+
if (pageInfo)
|
|
209
|
+
pageInterface.internal.RegisterPage.unregister(pageInfo);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
it("numbers the page parameter on an edit route repeating its name", async () => {
|
|
213
|
+
const edit = await formPageOptions("rpf-detail.rows.edit");
|
|
214
|
+
(0, chai_1.expect)(edit?.submitDefaults).to.deep.equal({
|
|
215
|
+
status: "{{query.status}}",
|
|
216
|
+
_instance: "{{params.id:1}}",
|
|
217
|
+
});
|
|
218
|
+
(0, chai_1.expect)(edit?.submitUrl).to.equal(`${LOCATION}/edit?id={{params.id}}`);
|
|
219
|
+
});
|
|
220
|
+
it("keeps the bare name on a new route carrying the name once", async () => {
|
|
221
|
+
(0, chai_1.expect)((await formPageOptions("rpf-detail.rows.new"))?.submitDefaults).to.deep.equal({
|
|
222
|
+
status: "{{query.status}}",
|
|
223
|
+
_instance: "{{params.id}}",
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
it("gives the view form no defaults", async () => {
|
|
227
|
+
(0, chai_1.expect)((await formPageOptions("rpf-detail.rows.view"))?.submitDefaults).to.equal(undefined);
|
|
228
|
+
});
|
|
229
|
+
it("keeps the bare name when the page parameter is not named id", async () => {
|
|
230
|
+
(0, chai_1.expect)((await formPageOptions("rpf-named.rows.edit"))?.submitDefaults).to.deep.equal({ _instance: "{{params.workspace}}" });
|
|
231
|
+
});
|
|
232
|
+
it("numbers the last occurrence of a name the page slug repeats", async () => {
|
|
233
|
+
(0, chai_1.expect)((await formPageOptions("rpf-deep.rows.new"))?.submitDefaults).to.deep.equal({ _instance: "{{params.id:2}}" });
|
|
234
|
+
(0, chai_1.expect)((await formPageOptions("rpf-deep.rows.edit"))?.submitDefaults).to.deep.equal({ _instance: "{{params.id:2}}" });
|
|
235
|
+
});
|
|
236
|
+
it("leaves the forms of a page without route parameter as they were", async () => {
|
|
237
|
+
for (const kind of ["new", "edit"]) {
|
|
238
|
+
(0, chai_1.expect)((await formPageOptions(`rpf-top.rows.${kind}`))?.submitDefaults).to.deep.equal({ _instance: "{{params.id}}" });
|
|
239
|
+
}
|
|
240
|
+
const unfiltered = await formPageOptions("rpf-unfiltered.rows.edit");
|
|
241
|
+
(0, chai_1.expect)(unfiltered?.submitDefaults).to.equal(undefined);
|
|
242
|
+
});
|
|
243
|
+
it("keeps the bare name on the forms the table view embeds", async () => {
|
|
244
|
+
const embedded = await formComponents(drawerTable);
|
|
245
|
+
(0, chai_1.expect)(embedded?.edit?.options?.submitDefaults).to.deep.equal({
|
|
246
|
+
_instance: "{{params.id}}",
|
|
247
|
+
});
|
|
248
|
+
(0, chai_1.expect)((await formComponents(detailTable))?.edit?.options?.submitDefaults).to.deep.equal({
|
|
249
|
+
status: "{{query.status}}",
|
|
250
|
+
_instance: "{{params.id}}",
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
//# sourceMappingURL=table-view-route-param-filter-defaults.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-view-route-param-filter-defaults.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/table-view-route-param-filter-defaults.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,29 +7,29 @@ export declare const authSchema: {
|
|
|
7
7
|
lang: z.ZodString;
|
|
8
8
|
token: z.ZodString;
|
|
9
9
|
}, "strip", z.ZodTypeAny, {
|
|
10
|
-
name: string;
|
|
11
|
-
lang: string;
|
|
12
|
-
email: string;
|
|
13
10
|
token: string;
|
|
14
|
-
password: string;
|
|
15
|
-
}, {
|
|
16
11
|
name: string;
|
|
17
|
-
|
|
12
|
+
password: string;
|
|
18
13
|
email: string;
|
|
14
|
+
lang: string;
|
|
15
|
+
}, {
|
|
19
16
|
token: string;
|
|
17
|
+
name: string;
|
|
20
18
|
password: string;
|
|
19
|
+
email: string;
|
|
20
|
+
lang: string;
|
|
21
21
|
}>;
|
|
22
22
|
login: z.ZodObject<{
|
|
23
23
|
email: z.ZodString;
|
|
24
24
|
password: z.ZodString;
|
|
25
25
|
keep_login: z.ZodOptional<z.ZodBoolean>;
|
|
26
26
|
}, "strip", z.ZodTypeAny, {
|
|
27
|
-
email: string;
|
|
28
27
|
password: string;
|
|
28
|
+
email: string;
|
|
29
29
|
keep_login?: boolean | undefined;
|
|
30
30
|
}, {
|
|
31
|
-
email: string;
|
|
32
31
|
password: string;
|
|
32
|
+
email: string;
|
|
33
33
|
keep_login?: boolean | undefined;
|
|
34
34
|
}>;
|
|
35
35
|
oauthCallback: z.ZodObject<{
|
|
@@ -42,14 +42,14 @@ export declare const authSchema: {
|
|
|
42
42
|
code: string;
|
|
43
43
|
state: string;
|
|
44
44
|
state_cookie: string;
|
|
45
|
-
language?: string | undefined;
|
|
46
45
|
invite?: string | undefined;
|
|
46
|
+
language?: string | undefined;
|
|
47
47
|
}, {
|
|
48
48
|
code: string;
|
|
49
49
|
state: string;
|
|
50
50
|
state_cookie: string;
|
|
51
|
-
language?: string | undefined;
|
|
52
51
|
invite?: string | undefined;
|
|
52
|
+
language?: string | undefined;
|
|
53
53
|
}>;
|
|
54
54
|
refresh: z.ZodObject<{
|
|
55
55
|
token: z.ZodString;
|
|
@@ -83,37 +83,37 @@ export declare const authSchema: {
|
|
|
83
83
|
token: z.ZodString;
|
|
84
84
|
email: z.ZodString;
|
|
85
85
|
}, "strip", z.ZodTypeAny, {
|
|
86
|
-
email: string;
|
|
87
86
|
token: string;
|
|
88
|
-
}, {
|
|
89
87
|
email: string;
|
|
88
|
+
}, {
|
|
90
89
|
token: string;
|
|
90
|
+
email: string;
|
|
91
91
|
}>;
|
|
92
92
|
reset: z.ZodObject<{
|
|
93
93
|
token: z.ZodString;
|
|
94
94
|
email: z.ZodString;
|
|
95
95
|
password: z.ZodString;
|
|
96
96
|
}, "strip", z.ZodTypeAny, {
|
|
97
|
-
email: string;
|
|
98
97
|
token: string;
|
|
99
98
|
password: string;
|
|
100
|
-
}, {
|
|
101
99
|
email: string;
|
|
100
|
+
}, {
|
|
102
101
|
token: string;
|
|
103
102
|
password: string;
|
|
103
|
+
email: string;
|
|
104
104
|
}>;
|
|
105
105
|
verify2FA: z.ZodObject<{
|
|
106
106
|
token: z.ZodString;
|
|
107
107
|
code: z.ZodString;
|
|
108
108
|
method: z.ZodEnum<["totp", "email", "backup"]>;
|
|
109
109
|
}, "strip", z.ZodTypeAny, {
|
|
110
|
-
code: string;
|
|
111
110
|
method: "email" | "totp" | "backup";
|
|
112
111
|
token: string;
|
|
113
|
-
}, {
|
|
114
112
|
code: string;
|
|
113
|
+
}, {
|
|
115
114
|
method: "email" | "totp" | "backup";
|
|
116
115
|
token: string;
|
|
116
|
+
code: string;
|
|
117
117
|
}>;
|
|
118
118
|
request2FAEmail: z.ZodObject<{
|
|
119
119
|
token: z.ZodString;
|
|
@@ -133,11 +133,11 @@ export declare const authSchema: {
|
|
|
133
133
|
method: z.ZodEnum<["totp", "email"]>;
|
|
134
134
|
code: z.ZodString;
|
|
135
135
|
}, "strip", z.ZodTypeAny, {
|
|
136
|
-
code: string;
|
|
137
136
|
method: "email" | "totp";
|
|
138
|
-
}, {
|
|
139
137
|
code: string;
|
|
138
|
+
}, {
|
|
140
139
|
method: "email" | "totp";
|
|
140
|
+
code: string;
|
|
141
141
|
}>;
|
|
142
142
|
regenerateBackup: z.ZodObject<{
|
|
143
143
|
code: z.ZodString;
|
|
@@ -5,18 +5,18 @@ export declare const onboardingRegisterAdminSchema: z.ZodEffects<z.ZodObject<{
|
|
|
5
5
|
password: z.ZodString;
|
|
6
6
|
}, "strip", z.ZodTypeAny, {
|
|
7
7
|
name: string;
|
|
8
|
-
email: string;
|
|
9
8
|
password: string;
|
|
9
|
+
email: string;
|
|
10
10
|
}, {
|
|
11
11
|
name: string;
|
|
12
|
-
email: string;
|
|
13
12
|
password: string;
|
|
13
|
+
email: string;
|
|
14
14
|
}>, {
|
|
15
15
|
email: string;
|
|
16
16
|
name: string;
|
|
17
17
|
password: string;
|
|
18
18
|
}, {
|
|
19
19
|
name: string;
|
|
20
|
-
email: string;
|
|
21
20
|
password: string;
|
|
21
|
+
email: string;
|
|
22
22
|
}>;
|
|
@@ -37,36 +37,65 @@ interface MatchRouteResult {
|
|
|
37
37
|
params: Record<string, string>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
// A route pattern can carry the same placeholder name twice: a page-mode form
|
|
41
|
+
// sub-page under a page whose own slug is `:id` resolves to
|
|
42
|
+
// `/workspaces/:id/invoiceTable/:id/edit`. The bare name holds the LAST
|
|
43
|
+
// occurrence, so `params.id` keeps meaning the row id the way it does on every
|
|
44
|
+
// single-placeholder form route, and each occurrence of a repeated name is
|
|
45
|
+
// exposed as well under `<name>:<n>`, numbered from 1 in pattern order, so the
|
|
46
|
+
// id of the carrying page stays reachable as `id:1`. A name that occurs only
|
|
47
|
+
// once gets no indexed key: those bags are exactly what they were.
|
|
48
|
+
const OCCURRENCE_KEY_SEPARATOR = ":";
|
|
49
|
+
|
|
50
|
+
const occurrenceKey = (name: string, occurrence: number): string =>
|
|
51
|
+
`${name}${OCCURRENCE_KEY_SEPARATOR}${occurrence}`;
|
|
52
|
+
|
|
53
|
+
function countByName(names: string[]): Record<string, number> {
|
|
54
|
+
const totals: Record<string, number> = {};
|
|
55
|
+
for (const name of names) {
|
|
56
|
+
totals[name] = (totals[name] ?? 0) + 1;
|
|
57
|
+
}
|
|
58
|
+
return totals;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function buildParamBag(
|
|
62
|
+
names: string[],
|
|
63
|
+
values: string[],
|
|
64
|
+
): Record<string, string> {
|
|
65
|
+
const totals = countByName(names);
|
|
66
|
+
const seen: Record<string, number> = {};
|
|
67
|
+
const params: Record<string, string> = {};
|
|
68
|
+
|
|
69
|
+
names.forEach((name, index) => {
|
|
70
|
+
const value = values[index]!;
|
|
71
|
+
const occurrence = (seen[name] ?? 0) + 1;
|
|
72
|
+
seen[name] = occurrence;
|
|
73
|
+
params[name] = value;
|
|
74
|
+
if (totals[name]! > 1) {
|
|
75
|
+
params[occurrenceKey(name, occurrence)] = value;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return params;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function extractRouteParams(
|
|
41
83
|
pattern: string,
|
|
42
84
|
path: string,
|
|
43
85
|
): Record<string, string> | null {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
.map((segment) =>
|
|
47
|
-
if (segment.startsWith(":")) {
|
|
48
|
-
return "([^/]+)";
|
|
49
|
-
}
|
|
50
|
-
return segment;
|
|
51
|
-
})
|
|
86
|
+
const segments = pattern.split("/");
|
|
87
|
+
const regexPattern = segments
|
|
88
|
+
.map((segment) => (segment.startsWith(":") ? "([^/]+)" : segment))
|
|
52
89
|
.join("/");
|
|
53
90
|
|
|
54
|
-
const
|
|
55
|
-
const match = path.match(regex);
|
|
56
|
-
|
|
91
|
+
const match = path.match(new RegExp(`^${regexPattern}$`));
|
|
57
92
|
if (!match) return null;
|
|
58
93
|
|
|
59
|
-
const paramNames =
|
|
60
|
-
.split("/")
|
|
94
|
+
const paramNames = segments
|
|
61
95
|
.filter((segment) => segment.startsWith(":"))
|
|
62
96
|
.map((segment) => segment.substring(1));
|
|
63
97
|
|
|
64
|
-
|
|
65
|
-
paramNames.forEach((name, index) => {
|
|
66
|
-
params[name] = match[index + 1]!;
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return params;
|
|
98
|
+
return buildParamBag(paramNames, match.slice(1));
|
|
70
99
|
}
|
|
71
100
|
|
|
72
101
|
export const useSiteLayout = () => {
|
|
@@ -26,7 +26,10 @@ import type {
|
|
|
26
26
|
CustomButton,
|
|
27
27
|
TableViewDisplayCapabilities,
|
|
28
28
|
} from "../../../composables/table-view/types";
|
|
29
|
-
import type {
|
|
29
|
+
import type {
|
|
30
|
+
FormContainer,
|
|
31
|
+
FormPageUrls,
|
|
32
|
+
} from "../../composables/table-view/useTableViewConfig";
|
|
30
33
|
import type { CustomRowAction } from "../../../types/row-action";
|
|
31
34
|
import type { RowActionConfig } from "#dms-core/app/types/row-action";
|
|
32
35
|
import type { TableTabItem } from "./Tabs.vue";
|
|
@@ -97,6 +100,8 @@ export interface TableProps<T> {
|
|
|
97
100
|
onCustomRowAction?: (action: CustomRowAction, rowData: T) => void;
|
|
98
101
|
componentId?: string;
|
|
99
102
|
formContainer?: FormContainer;
|
|
103
|
+
formPages?: FormPageUrls;
|
|
104
|
+
routeParams?: Record<string, string>;
|
|
100
105
|
defaultSort?: { field: string; desc?: boolean };
|
|
101
106
|
initialColumnVisibility?: VisibilityState;
|
|
102
107
|
presenceByRow?: TableRowPresenceMap;
|
|
@@ -92,6 +92,8 @@ export const useTable = <T extends Data>(props: UseTableProps<T>) => {
|
|
|
92
92
|
ui: props.ui,
|
|
93
93
|
componentId: props.tableProps.componentId,
|
|
94
94
|
formContainer: props.tableProps.formContainer,
|
|
95
|
+
formPages: props.tableProps.formPages,
|
|
96
|
+
routeParams: props.tableProps.routeParams,
|
|
95
97
|
onCustomRowAction: props.tableProps.onCustomRowAction,
|
|
96
98
|
});
|
|
97
99
|
|
|
@@ -28,7 +28,11 @@ import {
|
|
|
28
28
|
FormContainerType,
|
|
29
29
|
DEFAULT_FORM_CONTAINER_TYPE,
|
|
30
30
|
} from "../table-view/types";
|
|
31
|
-
import
|
|
31
|
+
import {
|
|
32
|
+
fillFormPageUrl,
|
|
33
|
+
type FormContainer,
|
|
34
|
+
type FormPageUrls,
|
|
35
|
+
} from "../table-view/useTableViewConfig";
|
|
32
36
|
import type { DmsAppConfig } from "#dms-core/shared/types/app-config";
|
|
33
37
|
|
|
34
38
|
const SORT_DIRECTION_ICON: Record<SortDirection, string> = {
|
|
@@ -84,6 +88,8 @@ interface ColumnConfig<T> {
|
|
|
84
88
|
ui: ComputedRef<TableStyleSlots>;
|
|
85
89
|
componentId?: string;
|
|
86
90
|
formContainer?: FormContainer;
|
|
91
|
+
formPages?: FormPageUrls;
|
|
92
|
+
routeParams?: Record<string, string>;
|
|
87
93
|
onCustomRowAction?: (action: CustomRowAction, rowData: T) => void;
|
|
88
94
|
}
|
|
89
95
|
|
|
@@ -353,13 +359,13 @@ export const useTableColumns = <T extends Data>(config: ColumnConfig<T>) => {
|
|
|
353
359
|
|
|
354
360
|
const containerType =
|
|
355
361
|
config.formContainer?.type ?? DEFAULT_FORM_CONTAINER_TYPE;
|
|
356
|
-
|
|
362
|
+
const viewPageUrl =
|
|
363
|
+
containerType === FormContainerType.page
|
|
364
|
+
? config.formPages?.view
|
|
365
|
+
: undefined;
|
|
366
|
+
if (viewPageUrl) {
|
|
357
367
|
const itemId = get(rowData, config.rowIdKey);
|
|
358
|
-
|
|
359
|
-
config.formContainer?.pages?.view?.urlSlug ||
|
|
360
|
-
`${currentRoute.path}/${itemId}/view`;
|
|
361
|
-
const viewUrl = viewSlug.replace(":id", itemId);
|
|
362
|
-
itemUrl = `${window.location.origin}${viewUrl}`;
|
|
368
|
+
itemUrl = `${window.location.origin}${fillFormPageUrl(viewPageUrl, config.routeParams, itemId)}`;
|
|
363
369
|
} else {
|
|
364
370
|
const updatedQuery = {
|
|
365
371
|
...currentRoute.query,
|
package/frontend-vue/layers/dms-ui/app/build/composables/table-view/registerDefaultFunctions.ts
CHANGED
|
@@ -1,32 +1,61 @@
|
|
|
1
1
|
import type { LocationQueryValue } from "#dms/frontend-module";
|
|
2
|
+
import { replaceUrlVariables } from "../../../composables/form/useForm";
|
|
3
|
+
|
|
4
|
+
type RouteQuery = Record<string, LocationQueryValue | LocationQueryValue[]>;
|
|
5
|
+
|
|
6
|
+
export interface FormSuccessParams {
|
|
7
|
+
url: string;
|
|
8
|
+
preserveQuery?: string[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface FormSuccessRoute {
|
|
12
|
+
query: RouteQuery;
|
|
13
|
+
params?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Where a page-mode form sends the user on submit: the page carrying the table
|
|
18
|
+
* view. Its URL holds a `{{params.X}}` token per placeholder of that page's
|
|
19
|
+
* slug, resolved against the parameters of the form route being left, the way
|
|
20
|
+
* `redirectOnSuccess` is.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveFormSuccessTarget(
|
|
23
|
+
{ url, preserveQuery }: FormSuccessParams,
|
|
24
|
+
route: FormSuccessRoute,
|
|
25
|
+
): { path: string; query?: RouteQuery } {
|
|
26
|
+
const path = replaceUrlVariables(url, {
|
|
27
|
+
routeParams: route.params,
|
|
28
|
+
routeQuery: route.query,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Restore the filtered table view: carry back the query params the form
|
|
32
|
+
// was opened with (those declared in `queryParamFilters`).
|
|
33
|
+
const query: RouteQuery = {};
|
|
34
|
+
for (const key of preserveQuery ?? []) {
|
|
35
|
+
if (route.query[key] !== undefined) {
|
|
36
|
+
query[key] = route.query[key];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return { path, ...(Object.keys(query).length > 0 ? { query } : {}) };
|
|
41
|
+
}
|
|
2
42
|
|
|
3
43
|
export function registerDefaultFunctions() {
|
|
4
44
|
const { registerFunction } = useDefinedFunctions();
|
|
5
45
|
const route = useDmsRoute();
|
|
46
|
+
const { findMatchingRoute } = useSiteLayout();
|
|
6
47
|
|
|
7
48
|
registerFunction(
|
|
8
49
|
TableViewFunctions.CUSTOM_PAGE_FORM_SUCCESS,
|
|
9
50
|
(event: CustomEvent) => {
|
|
10
|
-
const {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const query: Record<string, LocationQueryValue | LocationQueryValue[]> =
|
|
19
|
-
{};
|
|
20
|
-
for (const key of preserveQuery ?? []) {
|
|
21
|
-
if (route.query[key] !== undefined) {
|
|
22
|
-
query[key] = route.query[key];
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
navigateDms({
|
|
27
|
-
path: url,
|
|
28
|
-
...(Object.keys(query).length > 0 ? { query } : {}),
|
|
29
|
-
});
|
|
51
|
+
const { params } = event as CustomEvent & { params: FormSuccessParams };
|
|
52
|
+
|
|
53
|
+
navigateDms(
|
|
54
|
+
resolveFormSuccessTarget(params, {
|
|
55
|
+
query: route.query,
|
|
56
|
+
params: findMatchingRoute(route.path)?.params,
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
30
59
|
},
|
|
31
60
|
);
|
|
32
61
|
}
|