@mattisvensson/strapi-plugin-webatlas 0.9.6 → 0.10.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/README.md +24 -36
- package/dist/_chunks/{SettingTitle-77mvMRg_.mjs → SettingTitle-CdR3SVn_.mjs} +1 -1
- package/dist/_chunks/{SettingTitle-DLj_Wwqy.js → SettingTitle-RU1azFIM.js} +1 -1
- package/dist/_chunks/{de-C-uxto84.mjs → de-B5pRvs13.mjs} +13 -7
- package/dist/_chunks/{de-CGXL_3o_.js → de-CqU1FU8C.js} +13 -7
- package/dist/_chunks/{en-B1CHnIH7.mjs → en-BE-zzIv8.mjs} +13 -7
- package/dist/_chunks/{en-DWEd5BXK.js → en-C7I90FwV.js} +13 -7
- package/dist/_chunks/{index-DwaKIwAz.mjs → index-B07UVUOa.mjs} +387 -229
- package/dist/_chunks/{index-3pYLMhui.mjs → index-BmyxSosC.mjs} +3 -3
- package/dist/_chunks/{index-Dt-AXdaw.js → index-BucL4va6.js} +38 -82
- package/dist/_chunks/{index-BRKi-K-v.mjs → index-BvcX9hcc.mjs} +61 -24
- package/dist/_chunks/{index-COfk3YSm.js → index-BxpDM360.js} +386 -228
- package/dist/_chunks/{index-5OG4i6qO.mjs → index-CIM-JzLK.mjs} +38 -82
- package/dist/_chunks/{index-BWzalvVi.mjs → index-CNKWb8pn.mjs} +614 -320
- package/dist/_chunks/{index-VXuAEnpX.js → index-D-vJE_K8.js} +3 -3
- package/dist/_chunks/{index-BOtvXSPU.js → index-IRSCe8PX.js} +609 -315
- package/dist/_chunks/{index-DTsHvlTa.js → index-d09V61nm.js} +61 -24
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/CMEditViewAside/NewPathInfo.d.ts +2 -0
- package/dist/admin/src/components/CMEditViewAside/OverrideCheckbox.d.ts +7 -0
- package/dist/admin/src/components/CMEditViewAside/Panel.d.ts +5 -0
- package/dist/admin/src/components/CMEditViewAside/PathInput.d.ts +11 -0
- package/dist/admin/src/components/CMEditViewAside/RouteStructure.d.ts +3 -0
- package/dist/admin/src/components/CMEditViewAside/UidPathDisplay.d.ts +4 -0
- package/dist/admin/src/components/PathInfo.d.ts +2 -3
- package/dist/admin/src/components/modals/externalItem/index.d.ts +1 -1
- package/dist/admin/src/components/modals/internalItem/ItemDetails.d.ts +13 -0
- package/dist/admin/src/components/modals/internalItem/internalItemCreate.d.ts +1 -1
- package/dist/admin/src/components/modals/internalItem/internalItemEdit.d.ts +1 -1
- package/dist/admin/src/components/modals/useModalSharedLogic.d.ts +1 -1
- package/dist/admin/src/components/modals/wrapperItem/index.d.ts +1 -1
- package/dist/admin/src/hooks/useApi.d.ts +4 -3
- package/dist/admin/src/pages/Navigation/RouteItem.d.ts +1 -15
- package/dist/admin/src/pages/Navigation/RouteItemBadge.d.ts +4 -0
- package/dist/admin/src/pages/Navigation/RouteItemIcon.d.ts +5 -0
- package/dist/admin/src/pages/Navigation/RouteItemMenu.d.ts +10 -0
- package/dist/admin/src/pages/Navigation/RouteItemStatus.d.ts +5 -0
- package/dist/admin/src/pages/Navigation/SortableRouteItem.d.ts +1 -1
- package/dist/admin/src/types/index.d.ts +3 -0
- package/dist/admin/src/types/modal.d.ts +56 -0
- package/dist/admin/src/types/navigation.d.ts +18 -0
- package/dist/admin/src/types/panel.d.ts +41 -0
- package/dist/admin/src/types/route.d.ts +1 -1
- package/dist/admin/src/utils/buildBreadcrumbString.d.ts +16 -0
- package/dist/admin/src/utils/createTempNavItemObject.d.ts +6 -8
- package/dist/admin/src/utils/duplicateCheck.d.ts +10 -4
- package/dist/admin/src/utils/findParentNavItem.d.ts +13 -0
- package/dist/admin/src/utils/index.d.ts +3 -2
- package/dist/server/index.js +630 -200
- package/dist/server/index.mjs +630 -200
- package/dist/server/src/content-types/index.d.ts +18 -0
- package/dist/server/src/content-types/route/index.d.ts +18 -0
- package/dist/server/src/content-types/route/schema.d.ts +18 -0
- package/dist/server/src/controllers/admin.d.ts +3 -2
- package/dist/server/src/controllers/index.d.ts +3 -2
- package/dist/server/src/index.d.ts +24 -4
- package/dist/server/src/migrations/001-canonical-path.d.ts +7 -0
- package/dist/server/src/migrations/index.d.ts +3 -0
- package/dist/server/src/services/admin.d.ts +3 -2
- package/dist/server/src/services/index.d.ts +3 -2
- package/dist/server/src/utils/buildCanonicalPath.d.ts +1 -0
- package/dist/server/src/utils/buildNavigationPath.d.ts +5 -0
- package/dist/server/src/utils/cascadeCanonicalPathUpdates.d.ts +1 -0
- package/dist/server/src/utils/getNonInternalRouteIds.d.ts +1 -0
- package/dist/server/src/utils/getRouteAncestors.d.ts +1 -0
- package/dist/server/src/utils/getRouteDescendants.d.ts +1 -0
- package/dist/server/src/utils/index.d.ts +10 -2
- package/dist/server/src/utils/navigationItemStructure.d.ts +27 -0
- package/dist/server/src/utils/routeHandler.d.ts +4 -2
- package/dist/server/src/utils/validateRouteDependencies.d.ts +4 -0
- package/dist/types/index.d.ts +0 -1
- package/dist/types/navigation.d.ts +13 -12
- package/dist/types/route.d.ts +7 -2
- package/dist/types/strapi.d.ts +1 -2
- package/dist/utils/index.d.ts +1 -2
- package/package.json +1 -1
- package/dist/admin/src/components/CMEditViewAside/Path.d.ts +0 -5
- package/dist/admin/src/utils/countChildren.d.ts +0 -2
- package/dist/types/modal.d.ts +0 -36
- package/dist/utils/getPath.d.ts +0 -1
package/dist/server/index.js
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
function getPath(parentPath, slug) {
|
|
3
|
-
if (!slug) return null;
|
|
4
|
-
if (!parentPath) return slug;
|
|
5
|
-
const newPath = parentPath.endsWith("/") ? parentPath : `${parentPath}/`;
|
|
6
|
-
return `${newPath}${slug}`;
|
|
7
|
-
}
|
|
8
2
|
function transformToUrl(input) {
|
|
9
3
|
const specialCharMap = {
|
|
10
4
|
"ü": "ue",
|
|
@@ -16,6 +10,7 @@ function transformToUrl(input) {
|
|
|
16
10
|
input = input.replace(/\/+/g, "/");
|
|
17
11
|
input = input.startsWith("/") ? input.slice(1) : input;
|
|
18
12
|
input = input.endsWith("/") ? input.slice(0, -1) : input;
|
|
13
|
+
input = input.replace(/\//g, "-");
|
|
19
14
|
for (const char in specialCharMap) {
|
|
20
15
|
const regex = new RegExp(char, "g");
|
|
21
16
|
input = input.replace(regex, specialCharMap[char]);
|
|
@@ -26,7 +21,7 @@ function transformToUrl(input) {
|
|
|
26
21
|
input = input.replace(/-+/g, "-");
|
|
27
22
|
return input;
|
|
28
23
|
}
|
|
29
|
-
const version = "0.9.
|
|
24
|
+
const version = "0.9.6";
|
|
30
25
|
const keywords = [];
|
|
31
26
|
const type = "commonjs";
|
|
32
27
|
const exports$1 = {
|
|
@@ -151,15 +146,10 @@ async function checkPathExists(path, targetRoutePath) {
|
|
|
151
146
|
const entities = await strapi.documents(waRoute).findMany({
|
|
152
147
|
filters: {
|
|
153
148
|
$or: [
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
slug: path
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
uidPath: path
|
|
162
|
-
}
|
|
149
|
+
{ path },
|
|
150
|
+
{ slug: path },
|
|
151
|
+
{ uidPath: path },
|
|
152
|
+
{ canonicalPath: path }
|
|
163
153
|
]
|
|
164
154
|
}
|
|
165
155
|
});
|
|
@@ -186,27 +176,12 @@ async function duplicateCheck(initialPath, targetRouteDocumentId) {
|
|
|
186
176
|
}
|
|
187
177
|
return uniquePath;
|
|
188
178
|
} catch (e) {
|
|
189
|
-
|
|
179
|
+
strapi.log.error(e);
|
|
190
180
|
}
|
|
191
181
|
}
|
|
192
182
|
async function createNavItem(data) {
|
|
193
183
|
try {
|
|
194
184
|
if (!data.route || !data.navigation) return null;
|
|
195
|
-
const parent = data.parent ? await strapi.documents(waNavItem).findOne({
|
|
196
|
-
documentId: data.parent,
|
|
197
|
-
populate: ["route"]
|
|
198
|
-
}) : null;
|
|
199
|
-
const route2 = data.route ? await strapi.documents(waRoute).findOne({
|
|
200
|
-
documentId: data.route
|
|
201
|
-
}) : null;
|
|
202
|
-
let path = route2.slug;
|
|
203
|
-
if (route2.type === "internal" && !route2.isOverride && parent?.route.type === "internal") path = getPath(parent?.route?.path, route2.slug);
|
|
204
|
-
await strapi.documents(waRoute).update({
|
|
205
|
-
documentId: data.route,
|
|
206
|
-
data: {
|
|
207
|
-
path
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
185
|
const entity = await strapi.documents(waNavItem).create({
|
|
211
186
|
data: {
|
|
212
187
|
navigation: data.navigation,
|
|
@@ -217,7 +192,7 @@ async function createNavItem(data) {
|
|
|
217
192
|
});
|
|
218
193
|
return entity;
|
|
219
194
|
} catch (e) {
|
|
220
|
-
|
|
195
|
+
strapi.log.error(e);
|
|
221
196
|
}
|
|
222
197
|
}
|
|
223
198
|
async function updateNavItem(documentId, data) {
|
|
@@ -230,7 +205,7 @@ async function updateNavItem(documentId, data) {
|
|
|
230
205
|
data: updateData
|
|
231
206
|
});
|
|
232
207
|
} catch (e) {
|
|
233
|
-
|
|
208
|
+
strapi.log.error(e);
|
|
234
209
|
}
|
|
235
210
|
}
|
|
236
211
|
async function deleteNavItem(documentId) {
|
|
@@ -240,7 +215,7 @@ async function deleteNavItem(documentId) {
|
|
|
240
215
|
});
|
|
241
216
|
return true;
|
|
242
217
|
} catch (e) {
|
|
243
|
-
|
|
218
|
+
strapi.log.error(e);
|
|
244
219
|
}
|
|
245
220
|
}
|
|
246
221
|
function getAdminService() {
|
|
@@ -282,7 +257,31 @@ async function createExternalRoute(data) {
|
|
|
282
257
|
}
|
|
283
258
|
});
|
|
284
259
|
} catch (e) {
|
|
285
|
-
|
|
260
|
+
strapi.log.error(e);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async function updateRoute(documentId, data) {
|
|
264
|
+
try {
|
|
265
|
+
const entity = await strapi.documents(waRoute).update({
|
|
266
|
+
documentId,
|
|
267
|
+
data: {
|
|
268
|
+
...data
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return entity;
|
|
272
|
+
} catch (e) {
|
|
273
|
+
strapi.log.error(e);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async function deleteRoute(documentId) {
|
|
277
|
+
try {
|
|
278
|
+
await strapi.documents(waRoute).delete({
|
|
279
|
+
documentId
|
|
280
|
+
});
|
|
281
|
+
return true;
|
|
282
|
+
} catch (e) {
|
|
283
|
+
strapi.log.error(e);
|
|
284
|
+
return false;
|
|
286
285
|
}
|
|
287
286
|
}
|
|
288
287
|
function buildStructuredNavigation(navigation2, variant = "nested") {
|
|
@@ -336,7 +335,7 @@ function buildStructuredNavigation(navigation2, variant = "nested") {
|
|
|
336
335
|
return { ...navigation2, items: flattenedItems };
|
|
337
336
|
}
|
|
338
337
|
} catch (error) {
|
|
339
|
-
|
|
338
|
+
strapi.log.error(error);
|
|
340
339
|
throw error;
|
|
341
340
|
}
|
|
342
341
|
}
|
|
@@ -377,8 +376,6 @@ function extractRouteAndItems(items) {
|
|
|
377
376
|
delete route2.createdAt;
|
|
378
377
|
delete route2.updatedAt;
|
|
379
378
|
delete route2.isOverride;
|
|
380
|
-
delete route2.internal;
|
|
381
|
-
delete route2.wrapper;
|
|
382
379
|
return {
|
|
383
380
|
__component: route2.type === "wrapper" ? `${PLUGIN_ID}.wrapper` : `${PLUGIN_ID}.route`,
|
|
384
381
|
type: route2.type,
|
|
@@ -4399,10 +4396,406 @@ function cleanRootKeys(obj) {
|
|
|
4399
4396
|
function removeWaFields(obj) {
|
|
4400
4397
|
delete obj["webatlas_path"];
|
|
4401
4398
|
delete obj["webatlas_override"];
|
|
4399
|
+
delete obj["webatlas_parent"];
|
|
4402
4400
|
return obj;
|
|
4403
4401
|
}
|
|
4402
|
+
async function buildCanonicalPath(slug, parentDocumentId) {
|
|
4403
|
+
try {
|
|
4404
|
+
const parentRoute = await strapi.documents(waRoute).findOne({
|
|
4405
|
+
documentId: parentDocumentId
|
|
4406
|
+
});
|
|
4407
|
+
const parentCanonicalPath = parentRoute?.canonicalPath || "";
|
|
4408
|
+
const canonicalPath = `${parentCanonicalPath ? parentCanonicalPath + "/" : ""}${slug}`;
|
|
4409
|
+
return canonicalPath;
|
|
4410
|
+
} catch (err) {
|
|
4411
|
+
strapi.log.error("Error building canonical path:", err);
|
|
4412
|
+
return slug;
|
|
4413
|
+
}
|
|
4414
|
+
}
|
|
4415
|
+
async function cascadeCanonicalPathUpdates(parentRouteId, newParentCanonicalPath) {
|
|
4416
|
+
const children = await strapi.db.query(waRoute).findMany({
|
|
4417
|
+
where: {
|
|
4418
|
+
parent: {
|
|
4419
|
+
documentId: parentRouteId
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4422
|
+
});
|
|
4423
|
+
for (const child of children) {
|
|
4424
|
+
const newCanonicalPath = `${newParentCanonicalPath}/${child.slug}`;
|
|
4425
|
+
const updateData = {
|
|
4426
|
+
canonicalPath: newCanonicalPath,
|
|
4427
|
+
// Only update path if not manually overridden
|
|
4428
|
+
...child.isOverride ? {} : { path: newCanonicalPath }
|
|
4429
|
+
};
|
|
4430
|
+
await strapi.documents(waRoute).update({
|
|
4431
|
+
documentId: child.documentId,
|
|
4432
|
+
data: updateData
|
|
4433
|
+
});
|
|
4434
|
+
await cascadeCanonicalPathUpdates(child.documentId, newCanonicalPath);
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
async function getRouteDescendants(routeId) {
|
|
4438
|
+
const descendants = [];
|
|
4439
|
+
const stack = [routeId];
|
|
4440
|
+
while (stack.length > 0) {
|
|
4441
|
+
const currentId = stack.pop();
|
|
4442
|
+
if (!currentId) continue;
|
|
4443
|
+
const children = await strapi.documents(waRoute).findMany({
|
|
4444
|
+
filters: {
|
|
4445
|
+
parent: {
|
|
4446
|
+
documentId: currentId
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4449
|
+
});
|
|
4450
|
+
for (const child of children) {
|
|
4451
|
+
descendants.push(child.documentId);
|
|
4452
|
+
stack.push(child.documentId);
|
|
4453
|
+
}
|
|
4454
|
+
}
|
|
4455
|
+
return descendants;
|
|
4456
|
+
}
|
|
4457
|
+
async function getNonInternalRouteIds() {
|
|
4458
|
+
const routes2 = await strapi.documents(waRoute).findMany({
|
|
4459
|
+
filters: {
|
|
4460
|
+
type: {
|
|
4461
|
+
$ne: "internal"
|
|
4462
|
+
}
|
|
4463
|
+
}
|
|
4464
|
+
});
|
|
4465
|
+
const routeIds = routes2.map((route2) => route2.documentId);
|
|
4466
|
+
return routeIds;
|
|
4467
|
+
}
|
|
4468
|
+
async function validateRouteDependencies({
|
|
4469
|
+
routeId,
|
|
4470
|
+
newParentId
|
|
4471
|
+
}) {
|
|
4472
|
+
if (!newParentId) return true;
|
|
4473
|
+
const normalizedRouteId = routeId ?? void 0;
|
|
4474
|
+
const parentRoute = await strapi.documents(waRoute).findOne({
|
|
4475
|
+
documentId: newParentId
|
|
4476
|
+
});
|
|
4477
|
+
if (!parentRoute) {
|
|
4478
|
+
throw new Error(`Parent route not found: ${newParentId}`);
|
|
4479
|
+
}
|
|
4480
|
+
if (parentRoute?.type === "external") {
|
|
4481
|
+
throw new Error("External routes cannot have children");
|
|
4482
|
+
}
|
|
4483
|
+
if (!normalizedRouteId) return true;
|
|
4484
|
+
const descendants = await getRouteDescendants(normalizedRouteId);
|
|
4485
|
+
const nonInternalRouteIds = await getNonInternalRouteIds();
|
|
4486
|
+
if (normalizedRouteId === newParentId || descendants.includes(newParentId) || nonInternalRouteIds.includes(newParentId)) {
|
|
4487
|
+
throw new Error(`Circular dependency detected: Cannot set route ${newParentId} as parent of ${normalizedRouteId}`);
|
|
4488
|
+
}
|
|
4489
|
+
return true;
|
|
4490
|
+
}
|
|
4491
|
+
async function buildNavigationPath({
|
|
4492
|
+
slug,
|
|
4493
|
+
routeDocumentId,
|
|
4494
|
+
calculatedParent
|
|
4495
|
+
}) {
|
|
4496
|
+
let parentDocumentId = calculatedParent;
|
|
4497
|
+
let parent = null;
|
|
4498
|
+
if (parentDocumentId) {
|
|
4499
|
+
do {
|
|
4500
|
+
const navItem = await strapi.documents(waNavItem).findOne({
|
|
4501
|
+
documentId: parentDocumentId,
|
|
4502
|
+
populate: ["route", "parent"]
|
|
4503
|
+
});
|
|
4504
|
+
parent = navItem;
|
|
4505
|
+
parentDocumentId = navItem?.parent?.documentId || null;
|
|
4506
|
+
if (parent?.route?.type === "internal") break;
|
|
4507
|
+
} while (parentDocumentId);
|
|
4508
|
+
}
|
|
4509
|
+
if (parent?.route?.type !== "internal")
|
|
4510
|
+
parent = null;
|
|
4511
|
+
if (slug.startsWith("/")) slug = slug.substring(1);
|
|
4512
|
+
const newPath = parent?.route ? `${parent.route.path}/${slug}` : `${slug}`;
|
|
4513
|
+
const validatedPath = await duplicateCheck(newPath, routeDocumentId);
|
|
4514
|
+
return validatedPath;
|
|
4515
|
+
}
|
|
4516
|
+
async function handleItemDeletion(navigationItems) {
|
|
4517
|
+
const errors = [];
|
|
4518
|
+
let items = [...navigationItems];
|
|
4519
|
+
for (let i = 0; i < items.length; i++) {
|
|
4520
|
+
const item = items[i];
|
|
4521
|
+
if (item.clientModifications?.type === "delete") {
|
|
4522
|
+
try {
|
|
4523
|
+
if (item.documentId) {
|
|
4524
|
+
await deleteNavItem(item.documentId);
|
|
4525
|
+
}
|
|
4526
|
+
if (item.route.type !== "internal") {
|
|
4527
|
+
await deleteRoute(item.route.documentId);
|
|
4528
|
+
}
|
|
4529
|
+
const newItems = reduceDepthOfOrphanedItems(items, item.documentId);
|
|
4530
|
+
if (!newItems) {
|
|
4531
|
+
throw new Error("Failed to reduce depth of orphaned items");
|
|
4532
|
+
}
|
|
4533
|
+
items = newItems;
|
|
4534
|
+
i--;
|
|
4535
|
+
} catch (err) {
|
|
4536
|
+
const errorMsg = `Error deleting navigation item: ${err instanceof Error ? err.message : String(err)}`;
|
|
4537
|
+
errors.push(errorMsg);
|
|
4538
|
+
strapi.log.error(errorMsg, err);
|
|
4539
|
+
}
|
|
4540
|
+
continue;
|
|
4541
|
+
}
|
|
4542
|
+
if (!item.route && item.documentId) {
|
|
4543
|
+
try {
|
|
4544
|
+
strapi.log.warn("Navigation item without route found. Deleting it.", item);
|
|
4545
|
+
await deleteNavItem(item.documentId);
|
|
4546
|
+
items.splice(i, 1);
|
|
4547
|
+
i--;
|
|
4548
|
+
} catch (err) {
|
|
4549
|
+
const errorMsg = `Error deleting navigation item without route: ${err instanceof Error ? err.message : String(err)}`;
|
|
4550
|
+
errors.push(errorMsg);
|
|
4551
|
+
strapi.log.error(errorMsg, err);
|
|
4552
|
+
}
|
|
4553
|
+
continue;
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
return {
|
|
4557
|
+
success: errors.length === 0,
|
|
4558
|
+
items,
|
|
4559
|
+
errors
|
|
4560
|
+
};
|
|
4561
|
+
}
|
|
4562
|
+
async function handleItemUpdate({
|
|
4563
|
+
item,
|
|
4564
|
+
calculatedParent,
|
|
4565
|
+
calculatedOrder,
|
|
4566
|
+
navigationId,
|
|
4567
|
+
newNavItemsMap
|
|
4568
|
+
}) {
|
|
4569
|
+
const errors = [];
|
|
4570
|
+
const isCreate = item.clientModifications?.type === "create";
|
|
4571
|
+
const isUpdate = item.clientModifications?.type === "update";
|
|
4572
|
+
const isInternal = item.route.type === "internal";
|
|
4573
|
+
if (isCreate && !item.clientModifications.route) {
|
|
4574
|
+
try {
|
|
4575
|
+
const newRoute = await createExternalRoute({
|
|
4576
|
+
title: item.route.title,
|
|
4577
|
+
slug: item.route.slug,
|
|
4578
|
+
path: item.route.path,
|
|
4579
|
+
type: item.route.type
|
|
4580
|
+
});
|
|
4581
|
+
const newNavItem = await createNavItem({
|
|
4582
|
+
route: newRoute.documentId,
|
|
4583
|
+
navigation: navigationId,
|
|
4584
|
+
parent: calculatedParent,
|
|
4585
|
+
order: calculatedOrder
|
|
4586
|
+
});
|
|
4587
|
+
if (newNavItem) newNavItemsMap.set(item.documentId, newNavItem);
|
|
4588
|
+
} catch (err) {
|
|
4589
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
4590
|
+
strapi.log.error(`Error creating navigation item '${item.route.title}': `, err);
|
|
4591
|
+
}
|
|
4592
|
+
return { success: errors.length === 0, errors };
|
|
4593
|
+
}
|
|
4594
|
+
if (isCreate && item.clientModifications.route) {
|
|
4595
|
+
try {
|
|
4596
|
+
const route2 = await strapi.documents(waRoute).findOne({
|
|
4597
|
+
documentId: item.clientModifications.route
|
|
4598
|
+
});
|
|
4599
|
+
if (!route2) throw new Error(`Related route not found for new navigation item '${item.route.title}'`);
|
|
4600
|
+
const path = await buildNavigationPath({
|
|
4601
|
+
slug: item.route.slug,
|
|
4602
|
+
routeDocumentId: route2.documentId,
|
|
4603
|
+
calculatedParent
|
|
4604
|
+
});
|
|
4605
|
+
await updateRoute(route2.documentId, {
|
|
4606
|
+
title: item.route.title,
|
|
4607
|
+
slug: item.route.slug,
|
|
4608
|
+
path,
|
|
4609
|
+
isOverride: path !== route2.canonicalPath
|
|
4610
|
+
});
|
|
4611
|
+
const newNavItem = await createNavItem({
|
|
4612
|
+
route: item.clientModifications.route,
|
|
4613
|
+
navigation: item.clientModifications.navigation,
|
|
4614
|
+
parent: calculatedParent,
|
|
4615
|
+
order: calculatedOrder
|
|
4616
|
+
});
|
|
4617
|
+
if (newNavItem) newNavItemsMap.set(item.documentId, newNavItem);
|
|
4618
|
+
} catch (err) {
|
|
4619
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
4620
|
+
strapi.log.error(`Error creating navigation item with existing route '${item.route.title}': `, err);
|
|
4621
|
+
}
|
|
4622
|
+
return { success: errors.length === 0, errors };
|
|
4623
|
+
}
|
|
4624
|
+
const needsRouteUpdate = isUpdate || isInternal;
|
|
4625
|
+
if (needsRouteUpdate || isInternal) {
|
|
4626
|
+
try {
|
|
4627
|
+
const route2 = await strapi.documents(waRoute).findOne({
|
|
4628
|
+
documentId: item.route.documentId
|
|
4629
|
+
});
|
|
4630
|
+
if (!route2) throw new Error(`Related route not found for navigation item '${item.route.title}'`);
|
|
4631
|
+
const slug = item.clientModifications?.slug || item.route.slug;
|
|
4632
|
+
const path = isInternal ? await buildNavigationPath({ slug, routeDocumentId: route2.documentId, calculatedParent }) : slug;
|
|
4633
|
+
if (needsRouteUpdate) {
|
|
4634
|
+
await updateRoute(route2.documentId, {
|
|
4635
|
+
title: item.clientModifications?.title || item.route.title,
|
|
4636
|
+
slug,
|
|
4637
|
+
path,
|
|
4638
|
+
isOverride: path !== route2.canonicalPath
|
|
4639
|
+
});
|
|
4640
|
+
}
|
|
4641
|
+
if (isInternal) {
|
|
4642
|
+
await strapi.entityService.update(item.route.relatedContentType, item.route.relatedDocumentId, {
|
|
4643
|
+
data: {
|
|
4644
|
+
webatlas_path: path,
|
|
4645
|
+
webatlas_override: path !== route2.canonicalPath
|
|
4646
|
+
}
|
|
4647
|
+
});
|
|
4648
|
+
}
|
|
4649
|
+
} catch (err) {
|
|
4650
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
4651
|
+
strapi.log.error(`Error processing route for navigation item '${item.route.title}': `, err);
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4654
|
+
await updateNavItem(item.documentId, {
|
|
4655
|
+
parent: calculatedParent,
|
|
4656
|
+
order: calculatedOrder
|
|
4657
|
+
});
|
|
4658
|
+
return {
|
|
4659
|
+
success: errors.length === 0,
|
|
4660
|
+
errors
|
|
4661
|
+
};
|
|
4662
|
+
}
|
|
4663
|
+
function calculateParentAndOrder({
|
|
4664
|
+
navigationItems,
|
|
4665
|
+
item,
|
|
4666
|
+
index: index2,
|
|
4667
|
+
parentIds,
|
|
4668
|
+
groupIndices,
|
|
4669
|
+
newNavItemsMap
|
|
4670
|
+
}) {
|
|
4671
|
+
if (item.depth === 0) {
|
|
4672
|
+
if (groupIndices[0] !== void 0) {
|
|
4673
|
+
groupIndices[0] = groupIndices[0] + 1;
|
|
4674
|
+
} else {
|
|
4675
|
+
groupIndices[0] = 0;
|
|
4676
|
+
}
|
|
4677
|
+
parentIds.length = 0;
|
|
4678
|
+
} else {
|
|
4679
|
+
const previousItem = navigationItems[index2 - 1];
|
|
4680
|
+
if (previousItem && typeof previousItem.depth === "number") {
|
|
4681
|
+
if (item.depth === previousItem.depth + 1) {
|
|
4682
|
+
parentIds.push(previousItem.documentId.startsWith("temp-") ? newNavItemsMap.get(previousItem.documentId)?.documentId || previousItem.documentId : previousItem.documentId);
|
|
4683
|
+
groupIndices[item.depth] = 0;
|
|
4684
|
+
} else if (item.depth <= previousItem.depth) {
|
|
4685
|
+
const diff = previousItem.depth - item.depth;
|
|
4686
|
+
for (let i = 0; i < diff; i++) {
|
|
4687
|
+
parentIds.pop();
|
|
4688
|
+
groupIndices.pop();
|
|
4689
|
+
}
|
|
4690
|
+
groupIndices[item.depth] = (groupIndices[item.depth] || 0) + 1;
|
|
4691
|
+
} else {
|
|
4692
|
+
groupIndices[item.depth] = (groupIndices[item.depth] || 0) + 1;
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
const calculatedParent = parentIds.at(-1) || null;
|
|
4697
|
+
const calculatedOrder = groupIndices[item.depth] || 0;
|
|
4698
|
+
return {
|
|
4699
|
+
calculatedParent,
|
|
4700
|
+
calculatedOrder
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4703
|
+
const migration_001_canonical_path = {
|
|
4704
|
+
version: "001",
|
|
4705
|
+
description: "Migrate title field to canonicalPath using transformToUrl",
|
|
4706
|
+
async up(strapi2) {
|
|
4707
|
+
strapi2.log.info("[webatlas] Starting canonical path migration...");
|
|
4708
|
+
try {
|
|
4709
|
+
const routes2 = await strapi2.db?.query(waRoute).findMany({
|
|
4710
|
+
where: {
|
|
4711
|
+
title: {
|
|
4712
|
+
$notNull: true,
|
|
4713
|
+
$ne: ""
|
|
4714
|
+
},
|
|
4715
|
+
$or: [
|
|
4716
|
+
{ canonicalPath: { $null: true } },
|
|
4717
|
+
{ canonicalPath: "" }
|
|
4718
|
+
]
|
|
4719
|
+
},
|
|
4720
|
+
populate: ["parent"]
|
|
4721
|
+
});
|
|
4722
|
+
if (!routes2 || routes2.length === 0) {
|
|
4723
|
+
strapi2.log.info("[webatlas] No routes found that need canonical path migration");
|
|
4724
|
+
return;
|
|
4725
|
+
}
|
|
4726
|
+
strapi2.log.info(`[webatlas] Found ${routes2.length} routes to migrate`);
|
|
4727
|
+
let migratedCount = 0;
|
|
4728
|
+
let errorCount = 0;
|
|
4729
|
+
const chunkSize = 50;
|
|
4730
|
+
for (let i = 0; i < routes2.length; i += chunkSize) {
|
|
4731
|
+
const chunk = routes2.slice(i, i + chunkSize);
|
|
4732
|
+
await Promise.all(chunk.map(async (route2) => {
|
|
4733
|
+
try {
|
|
4734
|
+
const transformedTitle = transformToUrl(route2.title);
|
|
4735
|
+
const parentId = route2.parent?.id || null;
|
|
4736
|
+
const canonicalPath = await buildCanonicalPath(transformedTitle, parentId);
|
|
4737
|
+
await strapi2.db?.query(waRoute).update({
|
|
4738
|
+
where: { id: route2.id },
|
|
4739
|
+
data: { canonicalPath }
|
|
4740
|
+
});
|
|
4741
|
+
migratedCount++;
|
|
4742
|
+
if (migratedCount % 25 === 0) {
|
|
4743
|
+
strapi2.log.info(`[webatlas] Migrated ${migratedCount}/${routes2.length} routes`);
|
|
4744
|
+
}
|
|
4745
|
+
} catch (error) {
|
|
4746
|
+
strapi2.log.error(`[webatlas] Failed to migrate route ${route2.id}:`, error);
|
|
4747
|
+
errorCount++;
|
|
4748
|
+
}
|
|
4749
|
+
}));
|
|
4750
|
+
}
|
|
4751
|
+
strapi2.log.info(`[webatlas] Canonical path migration completed. Migrated: ${migratedCount}, Errors: ${errorCount}`);
|
|
4752
|
+
if (errorCount > 0) {
|
|
4753
|
+
strapi2.log.warn(`[webatlas] ${errorCount} routes failed to migrate. Check logs for details.`);
|
|
4754
|
+
}
|
|
4755
|
+
} catch (error) {
|
|
4756
|
+
strapi2.log.error("[webatlas] Canonical path migration failed:", error);
|
|
4757
|
+
throw error;
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4760
|
+
};
|
|
4761
|
+
const migrations = [
|
|
4762
|
+
migration_001_canonical_path
|
|
4763
|
+
];
|
|
4764
|
+
const runMigrations = async (strapi2) => {
|
|
4765
|
+
const pluginStore = strapi2.store({ type: "plugin", name: PLUGIN_ID });
|
|
4766
|
+
let config2 = await pluginStore.get({ key: "config" });
|
|
4767
|
+
if (!config2) {
|
|
4768
|
+
config2 = { migrationVersion: "0" };
|
|
4769
|
+
}
|
|
4770
|
+
const currentVersion = config2.migrationVersion || "0";
|
|
4771
|
+
const pendingMigrations = migrations.filter((migration) => migration.version > currentVersion);
|
|
4772
|
+
if (pendingMigrations.length === 0) {
|
|
4773
|
+
strapi2.log.info("[webatlas] All migrations up to date");
|
|
4774
|
+
return;
|
|
4775
|
+
}
|
|
4776
|
+
strapi2.log.info(`[webatlas] Running ${pendingMigrations.length} migration(s)...`);
|
|
4777
|
+
for (const migration of pendingMigrations) {
|
|
4778
|
+
try {
|
|
4779
|
+
strapi2.log.info(`[webatlas] Running migration ${migration.version}: ${migration.description}`);
|
|
4780
|
+
await migration.up(strapi2);
|
|
4781
|
+
await pluginStore.set({
|
|
4782
|
+
key: "config",
|
|
4783
|
+
value: {
|
|
4784
|
+
...config2,
|
|
4785
|
+
migrationVersion: migration.version
|
|
4786
|
+
}
|
|
4787
|
+
});
|
|
4788
|
+
strapi2.log.info(`[webatlas] Migration ${migration.version} completed successfully`);
|
|
4789
|
+
} catch (error) {
|
|
4790
|
+
strapi2.log.error(`[webatlas] Migration ${migration.version} failed:`, error);
|
|
4791
|
+
throw error;
|
|
4792
|
+
}
|
|
4793
|
+
}
|
|
4794
|
+
strapi2.log.info("[webatlas] All migrations completed successfully");
|
|
4795
|
+
};
|
|
4404
4796
|
const bootstrap = async ({ strapi: strapi2 }) => {
|
|
4405
4797
|
try {
|
|
4798
|
+
await runMigrations(strapi2);
|
|
4406
4799
|
const actions = [
|
|
4407
4800
|
{
|
|
4408
4801
|
section: "plugins",
|
|
@@ -4458,15 +4851,15 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4458
4851
|
navigation: {
|
|
4459
4852
|
maxDepth: config2?.navigation?.maxDepth || 1,
|
|
4460
4853
|
...config2?.navigation
|
|
4461
|
-
}
|
|
4854
|
+
},
|
|
4855
|
+
migrationVersion: config2?.migrationVersion || "0"
|
|
4462
4856
|
};
|
|
4463
4857
|
enabledContentTypes.forEach((type2) => {
|
|
4464
4858
|
const existingConfig = config2?.selectedContentTypes?.find((ct) => ct.uid === type2.uid);
|
|
4465
4859
|
newConfig.selectedContentTypes.push({
|
|
4466
4860
|
uid: type2.uid,
|
|
4467
4861
|
label: type2.info.displayName,
|
|
4468
|
-
default: existingConfig?.default || null
|
|
4469
|
-
pattern: existingConfig?.pattern || null
|
|
4862
|
+
default: existingConfig?.default || null
|
|
4470
4863
|
});
|
|
4471
4864
|
});
|
|
4472
4865
|
if (JSON.stringify(newConfig) !== JSON.stringify(config2)) {
|
|
@@ -4489,7 +4882,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4489
4882
|
if (!navItem || !navItem.route) return;
|
|
4490
4883
|
event.state = navItem.route.id && navItem.route.type === "external" ? { id: navItem.route.id } : null;
|
|
4491
4884
|
} catch (err) {
|
|
4492
|
-
|
|
4885
|
+
strapi2.log.error(err);
|
|
4493
4886
|
}
|
|
4494
4887
|
},
|
|
4495
4888
|
async afterDelete(event) {
|
|
@@ -4502,15 +4895,13 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4502
4895
|
}
|
|
4503
4896
|
});
|
|
4504
4897
|
} catch (err) {
|
|
4505
|
-
|
|
4898
|
+
strapi2.log.error(err);
|
|
4506
4899
|
}
|
|
4507
4900
|
}
|
|
4508
4901
|
});
|
|
4509
4902
|
strapi2.db?.lifecycles.subscribe({
|
|
4510
4903
|
models: enabledContentTypes.map((type2) => type2.uid),
|
|
4511
4904
|
async beforeCreate(event) {
|
|
4512
|
-
const validContentTypes = config2.selectedContentTypes.filter((type2) => strapi2.contentTypes[type2.uid]);
|
|
4513
|
-
await pluginStore.set({ key: "config", value: { selectedContentTypes: validContentTypes } });
|
|
4514
4905
|
if (!event.params.data.webatlas_path) return;
|
|
4515
4906
|
event.params.data.webatlas_path = transformToUrl(event.params.data.webatlas_path);
|
|
4516
4907
|
},
|
|
@@ -4518,7 +4909,8 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4518
4909
|
const ctSettings = config2.selectedContentTypes.find((type2) => type2.uid === event.model.uid);
|
|
4519
4910
|
const {
|
|
4520
4911
|
webatlas_path,
|
|
4521
|
-
webatlas_override
|
|
4912
|
+
webatlas_override,
|
|
4913
|
+
webatlas_parent
|
|
4522
4914
|
} = event.params.data;
|
|
4523
4915
|
if (!webatlas_path) return;
|
|
4524
4916
|
const relatedRoute = await strapi2.db?.query(waRoute).findOne({
|
|
@@ -4527,8 +4919,20 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4527
4919
|
}
|
|
4528
4920
|
});
|
|
4529
4921
|
if (relatedRoute) return;
|
|
4530
|
-
|
|
4922
|
+
let parent = null;
|
|
4923
|
+
if (webatlas_parent) {
|
|
4924
|
+
try {
|
|
4925
|
+
const isValid = await validateRouteDependencies({
|
|
4926
|
+
newParentId: webatlas_parent
|
|
4927
|
+
});
|
|
4928
|
+
if (isValid) parent = webatlas_parent;
|
|
4929
|
+
} catch (err) {
|
|
4930
|
+
strapi2.log.error(`Route dependency validation failed: ${err.message}`);
|
|
4931
|
+
}
|
|
4932
|
+
}
|
|
4531
4933
|
const path = await duplicateCheck(transformToUrl(webatlas_path));
|
|
4934
|
+
const canonicalPath = await buildCanonicalPath(path, parent);
|
|
4935
|
+
const title = event.params.data[ctSettings?.default]?.trim() || path;
|
|
4532
4936
|
await strapi2.documents(waRoute).create({
|
|
4533
4937
|
data: {
|
|
4534
4938
|
relatedContentType: event.model.uid,
|
|
@@ -4538,7 +4942,9 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4538
4942
|
path,
|
|
4539
4943
|
uidPath: `${event.model.singularName}/${event.result.id}`,
|
|
4540
4944
|
isOverride: webatlas_override || false,
|
|
4541
|
-
title
|
|
4945
|
+
title,
|
|
4946
|
+
parent,
|
|
4947
|
+
canonicalPath
|
|
4542
4948
|
}
|
|
4543
4949
|
});
|
|
4544
4950
|
},
|
|
@@ -4547,46 +4953,74 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
4547
4953
|
const {
|
|
4548
4954
|
webatlas_path,
|
|
4549
4955
|
webatlas_override,
|
|
4956
|
+
webatlas_parent,
|
|
4550
4957
|
documentId
|
|
4551
4958
|
} = event.params.data;
|
|
4552
4959
|
if (!webatlas_path) return;
|
|
4553
|
-
const relatedRoute = await strapi2.
|
|
4554
|
-
|
|
4960
|
+
const relatedRoute = await strapi2.documents(waRoute).findFirst({
|
|
4961
|
+
filters: {
|
|
4555
4962
|
relatedDocumentId: documentId
|
|
4556
4963
|
}
|
|
4557
4964
|
});
|
|
4558
|
-
|
|
4559
|
-
|
|
4965
|
+
let parent = null;
|
|
4966
|
+
if (webatlas_parent) {
|
|
4967
|
+
try {
|
|
4968
|
+
const isValid = await validateRouteDependencies({
|
|
4969
|
+
routeId: relatedRoute ? relatedRoute.documentId : null,
|
|
4970
|
+
newParentId: webatlas_parent
|
|
4971
|
+
});
|
|
4972
|
+
if (isValid) {
|
|
4973
|
+
parent = await strapi2.documents(waRoute).findOne({
|
|
4974
|
+
documentId: webatlas_parent
|
|
4975
|
+
});
|
|
4976
|
+
}
|
|
4977
|
+
} catch (err) {
|
|
4978
|
+
strapi2.log.error(`Route dependency validation failed: ${err.message}`);
|
|
4979
|
+
}
|
|
4980
|
+
}
|
|
4981
|
+
const transformedPath = transformToUrl(webatlas_path);
|
|
4982
|
+
const rawPath = parent ? `${parent.path}/${transformedPath}` : transformedPath;
|
|
4983
|
+
const path = await duplicateCheck(rawPath, relatedRoute ? relatedRoute.documentId : null);
|
|
4984
|
+
const canonicalPath = await buildCanonicalPath(transformedPath, parent?.documentId);
|
|
4985
|
+
const title = event.params.data[ctSettings?.default]?.trim() || path;
|
|
4560
4986
|
const routeData = {
|
|
4561
4987
|
title,
|
|
4562
4988
|
path,
|
|
4563
|
-
slug:
|
|
4564
|
-
isOverride: webatlas_override || false
|
|
4989
|
+
slug: transformedPath,
|
|
4990
|
+
isOverride: webatlas_override || false,
|
|
4991
|
+
parent: parent?.documentId || null
|
|
4565
4992
|
};
|
|
4993
|
+
let routeDocumentId = relatedRoute?.documentId;
|
|
4566
4994
|
if (!relatedRoute) {
|
|
4567
|
-
await strapi2.documents(waRoute).create({
|
|
4995
|
+
const createdRoute = await strapi2.documents(waRoute).create({
|
|
4568
4996
|
data: {
|
|
4569
4997
|
relatedContentType: event.model.uid,
|
|
4570
4998
|
relatedId: event.result.id,
|
|
4571
4999
|
relatedDocumentId: event.result.documentId,
|
|
4572
5000
|
uidPath: `${event.model.singularName}/${event.result.id}`,
|
|
5001
|
+
canonicalPath,
|
|
4573
5002
|
...routeData
|
|
4574
5003
|
}
|
|
4575
5004
|
});
|
|
5005
|
+
routeDocumentId = createdRoute?.documentId;
|
|
4576
5006
|
} else {
|
|
4577
5007
|
await strapi2.documents(waRoute).update({
|
|
4578
5008
|
documentId: relatedRoute.documentId,
|
|
4579
5009
|
data: {
|
|
4580
|
-
...routeData
|
|
5010
|
+
...routeData,
|
|
5011
|
+
canonicalPath
|
|
4581
5012
|
}
|
|
4582
5013
|
});
|
|
4583
5014
|
}
|
|
5015
|
+
if (routeDocumentId) {
|
|
5016
|
+
await cascadeCanonicalPathUpdates(routeDocumentId, canonicalPath);
|
|
5017
|
+
}
|
|
4584
5018
|
},
|
|
4585
5019
|
async afterDelete(event) {
|
|
4586
5020
|
try {
|
|
4587
5021
|
await findAndDeleteNavItem(event.result.id, event.model.uid);
|
|
4588
5022
|
} catch (err) {
|
|
4589
|
-
|
|
5023
|
+
strapi2.log.error(err);
|
|
4590
5024
|
}
|
|
4591
5025
|
},
|
|
4592
5026
|
async afterDeleteMany(event) {
|
|
@@ -4620,7 +5054,7 @@ async function findAndDeleteNavItem(relatedId, relatedContentType) {
|
|
|
4620
5054
|
await strapi.documents(waRoute).delete({ documentId: route2.documentId });
|
|
4621
5055
|
if (navItem?.documentId) await strapi.documents(waNavItem).delete({ documentId: navItem.documentId });
|
|
4622
5056
|
} catch (err) {
|
|
4623
|
-
|
|
5057
|
+
strapi.log.error(err);
|
|
4624
5058
|
}
|
|
4625
5059
|
}
|
|
4626
5060
|
const destroy = ({ strapi: strapi2 }) => {
|
|
@@ -5157,6 +5591,11 @@ const register = ({ strapi: strapi2 }) => {
|
|
|
5157
5591
|
type: "boolean",
|
|
5158
5592
|
private: true
|
|
5159
5593
|
});
|
|
5594
|
+
set$1(attributes, "webatlas_parent", {
|
|
5595
|
+
...fieldSettings,
|
|
5596
|
+
type: "string",
|
|
5597
|
+
private: true
|
|
5598
|
+
});
|
|
5160
5599
|
});
|
|
5161
5600
|
};
|
|
5162
5601
|
const config = {
|
|
@@ -5215,6 +5654,10 @@ const schema$2 = {
|
|
|
5215
5654
|
type: "string",
|
|
5216
5655
|
configurable: false
|
|
5217
5656
|
},
|
|
5657
|
+
canonicalPath: {
|
|
5658
|
+
type: "string",
|
|
5659
|
+
configurable: false
|
|
5660
|
+
},
|
|
5218
5661
|
slug: {
|
|
5219
5662
|
type: "string",
|
|
5220
5663
|
configurable: false
|
|
@@ -5246,6 +5689,20 @@ const schema$2 = {
|
|
|
5246
5689
|
default: "internal",
|
|
5247
5690
|
configurable: false,
|
|
5248
5691
|
required: true
|
|
5692
|
+
},
|
|
5693
|
+
parent: {
|
|
5694
|
+
type: "relation",
|
|
5695
|
+
relation: "manyToOne",
|
|
5696
|
+
target: "plugin::webatlas.route",
|
|
5697
|
+
inversedBy: "children",
|
|
5698
|
+
configurable: false
|
|
5699
|
+
},
|
|
5700
|
+
children: {
|
|
5701
|
+
type: "relation",
|
|
5702
|
+
relation: "oneToMany",
|
|
5703
|
+
target: "plugin::webatlas.route",
|
|
5704
|
+
mappedBy: "parent",
|
|
5705
|
+
configurable: false
|
|
5249
5706
|
}
|
|
5250
5707
|
}
|
|
5251
5708
|
};
|
|
@@ -5374,19 +5831,18 @@ const admin$2 = () => ({
|
|
|
5374
5831
|
return ctx.throw(500, e);
|
|
5375
5832
|
}
|
|
5376
5833
|
},
|
|
5377
|
-
async
|
|
5834
|
+
async getRoute(ctx) {
|
|
5378
5835
|
try {
|
|
5379
|
-
|
|
5836
|
+
const { documentId } = ctx.params;
|
|
5837
|
+
if (!documentId) return ctx.throw(400, "Route documentId is required");
|
|
5838
|
+
return await getAdminService().getRoute(documentId);
|
|
5380
5839
|
} catch (e) {
|
|
5381
5840
|
return ctx.throw(500, e);
|
|
5382
5841
|
}
|
|
5383
5842
|
},
|
|
5384
|
-
async
|
|
5843
|
+
async getAllRoutes(ctx) {
|
|
5385
5844
|
try {
|
|
5386
|
-
|
|
5387
|
-
if (!documentId) return ctx.throw(400, "Route documentId is required");
|
|
5388
|
-
const { data } = ctx.request.body;
|
|
5389
|
-
return await getAdminService().updateRoute(documentId, data);
|
|
5845
|
+
return await getAdminService().getAllRoutes();
|
|
5390
5846
|
} catch (e) {
|
|
5391
5847
|
return ctx.throw(500, e);
|
|
5392
5848
|
}
|
|
@@ -5400,6 +5856,14 @@ const admin$2 = () => ({
|
|
|
5400
5856
|
return ctx.throw(500, e);
|
|
5401
5857
|
}
|
|
5402
5858
|
},
|
|
5859
|
+
async getProhibitedRouteIds(ctx) {
|
|
5860
|
+
try {
|
|
5861
|
+
const { documentId } = ctx.params;
|
|
5862
|
+
return await getAdminService().getProhibitedRouteIds(documentId);
|
|
5863
|
+
} catch (e) {
|
|
5864
|
+
return ctx.throw(500, e);
|
|
5865
|
+
}
|
|
5866
|
+
},
|
|
5403
5867
|
async getNavigation(ctx) {
|
|
5404
5868
|
try {
|
|
5405
5869
|
const { documentId, variant } = ctx.query;
|
|
@@ -5554,7 +6018,7 @@ const admin$1 = {
|
|
|
5554
6018
|
{
|
|
5555
6019
|
method: "GET",
|
|
5556
6020
|
path: "/route",
|
|
5557
|
-
handler: "admin.
|
|
6021
|
+
handler: "admin.getAllRoutes",
|
|
5558
6022
|
config: {
|
|
5559
6023
|
policies: [
|
|
5560
6024
|
"admin::isAuthenticatedAdmin",
|
|
@@ -5571,9 +6035,9 @@ const admin$1 = {
|
|
|
5571
6035
|
}
|
|
5572
6036
|
},
|
|
5573
6037
|
{
|
|
5574
|
-
method: "
|
|
5575
|
-
path: "/route",
|
|
5576
|
-
handler: "admin.
|
|
6038
|
+
method: "GET",
|
|
6039
|
+
path: "/route/related",
|
|
6040
|
+
handler: "admin.getRelatedRoute",
|
|
5577
6041
|
config: {
|
|
5578
6042
|
policies: [
|
|
5579
6043
|
"admin::isAuthenticatedAdmin",
|
|
@@ -5581,6 +6045,7 @@ const admin$1 = {
|
|
|
5581
6045
|
name: `plugin::${PLUGIN_ID}.has-permissions`,
|
|
5582
6046
|
config: {
|
|
5583
6047
|
actions: [
|
|
6048
|
+
`plugin::${PLUGIN_ID}.cm.aside`,
|
|
5584
6049
|
`plugin::${PLUGIN_ID}.page.navigation`
|
|
5585
6050
|
]
|
|
5586
6051
|
}
|
|
@@ -5590,8 +6055,26 @@ const admin$1 = {
|
|
|
5590
6055
|
},
|
|
5591
6056
|
{
|
|
5592
6057
|
method: "GET",
|
|
5593
|
-
path: "/route/
|
|
5594
|
-
handler: "admin.
|
|
6058
|
+
path: "/route/prohibitedIds/:documentId?",
|
|
6059
|
+
handler: "admin.getProhibitedRouteIds",
|
|
6060
|
+
config: {
|
|
6061
|
+
policies: [
|
|
6062
|
+
"admin::isAuthenticatedAdmin",
|
|
6063
|
+
{
|
|
6064
|
+
name: `plugin::${PLUGIN_ID}.has-permissions`,
|
|
6065
|
+
config: {
|
|
6066
|
+
actions: [
|
|
6067
|
+
`plugin::${PLUGIN_ID}.cm.aside`
|
|
6068
|
+
]
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6071
|
+
]
|
|
6072
|
+
}
|
|
6073
|
+
},
|
|
6074
|
+
{
|
|
6075
|
+
method: "GET",
|
|
6076
|
+
path: "/route/:documentId",
|
|
6077
|
+
handler: "admin.getRoute",
|
|
5595
6078
|
config: {
|
|
5596
6079
|
policies: [
|
|
5597
6080
|
"admin::isAuthenticatedAdmin",
|
|
@@ -5599,7 +6082,6 @@ const admin$1 = {
|
|
|
5599
6082
|
name: `plugin::${PLUGIN_ID}.has-permissions`,
|
|
5600
6083
|
config: {
|
|
5601
6084
|
actions: [
|
|
5602
|
-
`plugin::${PLUGIN_ID}.cm.aside`,
|
|
5603
6085
|
`plugin::${PLUGIN_ID}.page.navigation`
|
|
5604
6086
|
]
|
|
5605
6087
|
}
|
|
@@ -5755,7 +6237,7 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5755
6237
|
newConfigMerged = { ...config2, ...newConfig };
|
|
5756
6238
|
await pluginStore.set({ key: "config", value: newConfigMerged });
|
|
5757
6239
|
} catch (err) {
|
|
5758
|
-
|
|
6240
|
+
strapi2.log.error(err);
|
|
5759
6241
|
return "Error. Couldn't update config";
|
|
5760
6242
|
}
|
|
5761
6243
|
return newConfigMerged;
|
|
@@ -5776,35 +6258,21 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5776
6258
|
};
|
|
5777
6259
|
return config2;
|
|
5778
6260
|
},
|
|
5779
|
-
async
|
|
6261
|
+
async getRoute(documentId) {
|
|
5780
6262
|
try {
|
|
5781
|
-
|
|
5782
|
-
|
|
6263
|
+
return await strapi2.documents(waRoute).findOne({
|
|
6264
|
+
documentId
|
|
6265
|
+
});
|
|
5783
6266
|
} catch (e) {
|
|
5784
|
-
|
|
6267
|
+
strapi2.log.error(e);
|
|
5785
6268
|
}
|
|
5786
6269
|
},
|
|
5787
|
-
|
|
5788
|
-
async updateRoute(documentId, data) {
|
|
6270
|
+
async getAllRoutes() {
|
|
5789
6271
|
try {
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
const parent = data.parent ? await strapi2.documents(waNavItem).findOne({
|
|
5793
|
-
documentId: data.parent
|
|
5794
|
-
}) : null;
|
|
5795
|
-
const path = data.isOverride ? data.slug : getPath(parent?.path, data.slug);
|
|
5796
|
-
checkedPath = await duplicateCheck(path, documentId);
|
|
5797
|
-
}
|
|
5798
|
-
const entity = await strapi2.documents(waRoute).update({
|
|
5799
|
-
documentId,
|
|
5800
|
-
data: {
|
|
5801
|
-
...data,
|
|
5802
|
-
path: checkedPath
|
|
5803
|
-
}
|
|
5804
|
-
});
|
|
5805
|
-
return entity;
|
|
6272
|
+
const entities = await strapi2.documents(waRoute).findMany();
|
|
6273
|
+
return entities;
|
|
5806
6274
|
} catch (e) {
|
|
5807
|
-
|
|
6275
|
+
strapi2.log.error(e);
|
|
5808
6276
|
}
|
|
5809
6277
|
},
|
|
5810
6278
|
async getRelatedRoute(documentId) {
|
|
@@ -5812,10 +6280,28 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5812
6280
|
return await strapi2.db?.query(waRoute).findOne({
|
|
5813
6281
|
where: {
|
|
5814
6282
|
relatedDocumentId: documentId
|
|
5815
|
-
}
|
|
6283
|
+
},
|
|
6284
|
+
populate: ["parent"]
|
|
5816
6285
|
});
|
|
5817
6286
|
} catch (e) {
|
|
5818
|
-
|
|
6287
|
+
strapi2.log.error(e);
|
|
6288
|
+
}
|
|
6289
|
+
},
|
|
6290
|
+
async getProhibitedRouteIds(documentId) {
|
|
6291
|
+
try {
|
|
6292
|
+
let route2 = null;
|
|
6293
|
+
if (documentId) {
|
|
6294
|
+
route2 = await strapi2.documents(waRoute).findOne({
|
|
6295
|
+
documentId
|
|
6296
|
+
});
|
|
6297
|
+
}
|
|
6298
|
+
const descendants = route2?.documentId ? await getRouteDescendants(route2.documentId) : [];
|
|
6299
|
+
const nonInternalRouteIds = await getNonInternalRouteIds();
|
|
6300
|
+
const prohibitedRouteIds = [...descendants, ...nonInternalRouteIds];
|
|
6301
|
+
route2?.documentId && prohibitedRouteIds.push(route2.documentId);
|
|
6302
|
+
return prohibitedRouteIds;
|
|
6303
|
+
} catch (e) {
|
|
6304
|
+
strapi2.log.error(e);
|
|
5819
6305
|
}
|
|
5820
6306
|
},
|
|
5821
6307
|
async getNavigation(documentId, variant) {
|
|
@@ -5851,7 +6337,7 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5851
6337
|
}
|
|
5852
6338
|
return navigation2;
|
|
5853
6339
|
} catch (e) {
|
|
5854
|
-
|
|
6340
|
+
strapi2.log.error(e);
|
|
5855
6341
|
}
|
|
5856
6342
|
},
|
|
5857
6343
|
async createNavigation(name2, visible) {
|
|
@@ -5864,7 +6350,7 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5864
6350
|
}
|
|
5865
6351
|
});
|
|
5866
6352
|
} catch (e) {
|
|
5867
|
-
|
|
6353
|
+
strapi2.log.error(e);
|
|
5868
6354
|
}
|
|
5869
6355
|
},
|
|
5870
6356
|
async updateNavigation(documentId, data) {
|
|
@@ -5878,7 +6364,7 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5878
6364
|
});
|
|
5879
6365
|
return entity;
|
|
5880
6366
|
} catch (e) {
|
|
5881
|
-
|
|
6367
|
+
strapi2.log.error(e);
|
|
5882
6368
|
}
|
|
5883
6369
|
},
|
|
5884
6370
|
async deleteNavigation(documentId) {
|
|
@@ -5897,115 +6383,46 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
5897
6383
|
documentId
|
|
5898
6384
|
});
|
|
5899
6385
|
} catch (e) {
|
|
5900
|
-
|
|
6386
|
+
strapi2.log.error(e);
|
|
5901
6387
|
}
|
|
5902
6388
|
},
|
|
5903
6389
|
async updateNavigationItemStructure(navigationId, navigationItems) {
|
|
5904
6390
|
if (!navigationId || !navigationItems) return;
|
|
5905
6391
|
let error = false;
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
item.documentId && await deleteNavItem(item.documentId);
|
|
5911
|
-
const newItems = reduceDepthOfOrphanedItems(navigationItems, item.documentId);
|
|
5912
|
-
if (!newItems) throw new Error("Failed to reduce depth of orphaned items");
|
|
5913
|
-
navigationItems = newItems;
|
|
5914
|
-
} catch (error2) {
|
|
5915
|
-
error2 = true;
|
|
5916
|
-
console.error("Error deleting navigation item ", error2);
|
|
5917
|
-
}
|
|
5918
|
-
continue;
|
|
5919
|
-
}
|
|
5920
|
-
if (!item.route && item.documentId) {
|
|
5921
|
-
try {
|
|
5922
|
-
console.warn("Navigation item without route found. Deleting it. ", item);
|
|
5923
|
-
await deleteNavItem(item.documentId);
|
|
5924
|
-
} catch (error2) {
|
|
5925
|
-
console.error("Error deleting navigation item without route ", error2);
|
|
5926
|
-
}
|
|
5927
|
-
continue;
|
|
5928
|
-
}
|
|
5929
|
-
if (item.update && !item.isNew) {
|
|
5930
|
-
try {
|
|
5931
|
-
await this.updateRoute(item.route.documentId, {
|
|
5932
|
-
title: item.update.title || item.route.title,
|
|
5933
|
-
slug: item.update.slug || item.route.slug,
|
|
5934
|
-
path: item.update.path || item.route.path,
|
|
5935
|
-
isOverride: item.update.isOverride !== void 0 ? item.update.isOverride : item.route.isOverride
|
|
5936
|
-
});
|
|
5937
|
-
} catch (error2) {
|
|
5938
|
-
error2 = true;
|
|
5939
|
-
console.error("Error updating route ", error2);
|
|
5940
|
-
}
|
|
5941
|
-
}
|
|
6392
|
+
let newNavItemsMap = /* @__PURE__ */ new Map();
|
|
6393
|
+
const deletionResult = await handleItemDeletion(navigationItems);
|
|
6394
|
+
if (!deletionResult.success) {
|
|
6395
|
+
strapi2.log.error("Deletion errors:", deletionResult.errors);
|
|
5942
6396
|
}
|
|
6397
|
+
navigationItems = deletionResult.items;
|
|
5943
6398
|
let parentIds = [];
|
|
5944
6399
|
let groupIndices = [];
|
|
5945
6400
|
for (const [index2, item] of navigationItems.entries()) {
|
|
5946
6401
|
if (typeof item.depth !== "number") {
|
|
5947
6402
|
continue;
|
|
5948
6403
|
}
|
|
5949
|
-
if (item.depth === 0) {
|
|
5950
|
-
if (groupIndices[0] !== void 0) {
|
|
5951
|
-
groupIndices[0] = groupIndices[0] + 1;
|
|
5952
|
-
} else {
|
|
5953
|
-
groupIndices[0] = 0;
|
|
5954
|
-
}
|
|
5955
|
-
parentIds = [];
|
|
5956
|
-
} else {
|
|
5957
|
-
const previousItem = navigationItems[index2 - 1];
|
|
5958
|
-
if (previousItem && typeof previousItem.depth === "number") {
|
|
5959
|
-
if (item.depth === previousItem.depth + 1) {
|
|
5960
|
-
parentIds.push(previousItem.documentId.startsWith("temp-") ? newNavItemsMap.get(previousItem.documentId)?.documentId || previousItem.documentId : previousItem.documentId);
|
|
5961
|
-
groupIndices[item.depth] = 0;
|
|
5962
|
-
} else if (item.depth <= previousItem.depth) {
|
|
5963
|
-
const diff = previousItem.depth - item.depth;
|
|
5964
|
-
for (let i = 0; i < diff; i++) {
|
|
5965
|
-
parentIds.pop();
|
|
5966
|
-
groupIndices.pop();
|
|
5967
|
-
}
|
|
5968
|
-
groupIndices[item.depth] = (groupIndices[item.depth] || 0) + 1;
|
|
5969
|
-
} else {
|
|
5970
|
-
groupIndices[item.depth] = (groupIndices[item.depth] || 0) + 1;
|
|
5971
|
-
}
|
|
5972
|
-
}
|
|
5973
|
-
}
|
|
5974
|
-
const calculatedParent = parentIds.at(-1) || null;
|
|
5975
|
-
const calculatedOrder = groupIndices[item.depth] || 0;
|
|
5976
6404
|
try {
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
navigation: navigationId,
|
|
5995
|
-
parent: calculatedParent,
|
|
5996
|
-
order: calculatedOrder
|
|
5997
|
-
});
|
|
5998
|
-
if (newNavItem) newNavItemsMap.set(item.documentId, newNavItem);
|
|
5999
|
-
}
|
|
6000
|
-
} else {
|
|
6001
|
-
await updateNavItem(item.documentId, {
|
|
6002
|
-
order: calculatedOrder,
|
|
6003
|
-
parent: calculatedParent
|
|
6004
|
-
});
|
|
6405
|
+
const { calculatedParent, calculatedOrder } = calculateParentAndOrder({
|
|
6406
|
+
navigationItems,
|
|
6407
|
+
item,
|
|
6408
|
+
index: index2,
|
|
6409
|
+
parentIds,
|
|
6410
|
+
groupIndices,
|
|
6411
|
+
newNavItemsMap
|
|
6412
|
+
});
|
|
6413
|
+
const result = await handleItemUpdate({
|
|
6414
|
+
item,
|
|
6415
|
+
calculatedParent,
|
|
6416
|
+
calculatedOrder,
|
|
6417
|
+
navigationId,
|
|
6418
|
+
newNavItemsMap
|
|
6419
|
+
});
|
|
6420
|
+
if (!result.success) {
|
|
6421
|
+
strapi2.log.error("Error updating item: ", item);
|
|
6005
6422
|
}
|
|
6006
6423
|
} catch (errorMsg) {
|
|
6007
6424
|
error = true;
|
|
6008
|
-
|
|
6425
|
+
strapi2.log.error("Error updating navigation item ", errorMsg);
|
|
6009
6426
|
}
|
|
6010
6427
|
}
|
|
6011
6428
|
return !error;
|
|
@@ -6014,7 +6431,7 @@ const admin = ({ strapi: strapi2 }) => ({
|
|
|
6014
6431
|
try {
|
|
6015
6432
|
return await duplicateCheck(initialPath, targetRouteDocumentId);
|
|
6016
6433
|
} catch (e) {
|
|
6017
|
-
|
|
6434
|
+
strapi2.log.error(e);
|
|
6018
6435
|
}
|
|
6019
6436
|
}
|
|
6020
6437
|
});
|
|
@@ -6025,6 +6442,7 @@ const client = ({ strapi: strapi2 }) => ({
|
|
|
6025
6442
|
filters: {
|
|
6026
6443
|
$or: [
|
|
6027
6444
|
{ path: slug },
|
|
6445
|
+
{ canonicalPath: slug },
|
|
6028
6446
|
{ uidPath: slug }
|
|
6029
6447
|
]
|
|
6030
6448
|
}
|
|
@@ -6051,9 +6469,21 @@ const client = ({ strapi: strapi2 }) => ({
|
|
|
6051
6469
|
if (!entity) return null;
|
|
6052
6470
|
let cleanEntity = cleanRootKeys(entity);
|
|
6053
6471
|
cleanEntity = removeWaFields(cleanEntity);
|
|
6054
|
-
|
|
6472
|
+
const webatlasFields = {
|
|
6473
|
+
path: route2.path,
|
|
6474
|
+
canonicalPath: route2.canonicalPath,
|
|
6475
|
+
slug: route2.slug,
|
|
6476
|
+
uidPath: route2.uidPath
|
|
6477
|
+
};
|
|
6478
|
+
return {
|
|
6479
|
+
contentType: contentType.info.singularName,
|
|
6480
|
+
webatlas: {
|
|
6481
|
+
...webatlasFields
|
|
6482
|
+
},
|
|
6483
|
+
...cleanEntity
|
|
6484
|
+
};
|
|
6055
6485
|
} catch (e) {
|
|
6056
|
-
|
|
6486
|
+
strapi2.log.error(e);
|
|
6057
6487
|
return e;
|
|
6058
6488
|
}
|
|
6059
6489
|
},
|
|
@@ -6091,7 +6521,7 @@ const client = ({ strapi: strapi2 }) => ({
|
|
|
6091
6521
|
try {
|
|
6092
6522
|
navigation2 = await method.lookup();
|
|
6093
6523
|
} catch (error) {
|
|
6094
|
-
|
|
6524
|
+
strapi2.log.error(`Navigation lookup by ${method.name} failed:`, error);
|
|
6095
6525
|
}
|
|
6096
6526
|
}
|
|
6097
6527
|
}
|
|
@@ -6101,7 +6531,7 @@ const client = ({ strapi: strapi2 }) => ({
|
|
|
6101
6531
|
const entityNavigation = extractRouteAndItems(structured.items);
|
|
6102
6532
|
return { ...structured, items: entityNavigation };
|
|
6103
6533
|
} catch (e) {
|
|
6104
|
-
|
|
6534
|
+
strapi2.log.error(e);
|
|
6105
6535
|
return e;
|
|
6106
6536
|
}
|
|
6107
6537
|
}
|