@orion-studios/payload-studio 0.6.0-beta.4 → 0.6.0-beta.41
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/dist/admin/client.d.mts +1 -0
- package/dist/admin/client.d.ts +1 -0
- package/dist/admin/client.js +3924 -1355
- package/dist/admin/client.mjs +4090 -1533
- package/dist/admin/index.d.mts +2 -3
- package/dist/admin/index.d.ts +2 -3
- package/dist/admin/index.js +141 -1522
- package/dist/admin/index.mjs +2 -4
- package/dist/admin-app/client.js +11 -4
- package/dist/admin-app/client.mjs +1 -1
- package/dist/admin-app/index.d.mts +2 -2
- package/dist/admin-app/index.d.ts +2 -2
- package/dist/admin-app/index.mjs +4 -4
- package/dist/admin-app/styles.css +343 -41
- package/dist/admin.css +18 -2
- package/dist/{chunk-KPIX7OSV.mjs → chunk-2XH7X34N.mjs} +11 -4
- package/dist/{chunk-PF3EBZXF.mjs → chunk-7ZMXZRBP.mjs} +39 -3
- package/dist/chunk-JC3UV74N.mjs +1033 -0
- package/dist/{chunk-XKUTZ7IU.mjs → chunk-OL53KHTB.mjs} +46 -2
- package/dist/{chunk-EHUE4LCT.mjs → chunk-RKTIFEUY.mjs} +33 -3
- package/dist/chunk-W2UOCJDX.mjs +32 -0
- package/dist/{chunk-OTHERBGX.mjs → chunk-ZADL33R6.mjs} +1 -1
- package/dist/{index-bbA3HSxa.d.ts → index-BV0vEGl6.d.ts} +6 -9
- package/dist/{index-Cv-6qnrw.d.mts → index-D5zrOdyv.d.mts} +3 -1
- package/dist/{index-52HdVLQq.d.ts → index-DAdN56fM.d.ts} +1 -1
- package/dist/{index-DEkV-sMs.d.mts → index-DLfPOqYA.d.mts} +6 -9
- package/dist/{index-Crx_MtPw.d.ts → index-Dv-Alx4h.d.ts} +3 -1
- package/dist/{index-DEQC3Dwj.d.mts → index-G_uTNffQ.d.mts} +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +287 -1542
- package/dist/index.mjs +6 -6
- package/dist/nextjs/index.js +39 -3
- package/dist/nextjs/index.mjs +2 -2
- package/dist/{sitePreviewTypes-BkHCWxNW.d.mts → sitePreviewTypes-BrJwGzJj.d.mts} +1 -1
- package/dist/{sitePreviewTypes-BkHCWxNW.d.ts → sitePreviewTypes-BrJwGzJj.d.ts} +1 -1
- package/dist/studio-pages/builder.css +24 -5
- package/dist/studio-pages/client.js +529 -63
- package/dist/studio-pages/client.mjs +529 -63
- package/dist/studio-pages/index.d.mts +1 -1
- package/dist/studio-pages/index.d.ts +1 -1
- package/dist/studio-pages/index.js +84 -4
- package/dist/studio-pages/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-DYXSAVUQ.mjs +0 -2372
- package/dist/chunk-Z6L5K5MH.mjs +0 -64
package/dist/admin/index.js
CHANGED
|
@@ -30,7 +30,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/admin/index.ts
|
|
31
31
|
var admin_exports = {};
|
|
32
32
|
__export(admin_exports, {
|
|
33
|
-
AdminStudioDashboard: () => AdminStudioDashboard,
|
|
34
33
|
SOCIAL_MEDIA_DEFAULT_ICON_BY_PLATFORM: () => SOCIAL_MEDIA_DEFAULT_ICON_BY_PLATFORM,
|
|
35
34
|
SOCIAL_MEDIA_ICON_OPTIONS: () => SOCIAL_MEDIA_ICON_OPTIONS,
|
|
36
35
|
SOCIAL_MEDIA_PLATFORMS: () => SOCIAL_MEDIA_PLATFORMS,
|
|
@@ -80,26 +79,10 @@ var adminNavIcons = [
|
|
|
80
79
|
"account",
|
|
81
80
|
"analytics"
|
|
82
81
|
];
|
|
83
|
-
var roleCanAccessNav = (role, item) => {
|
|
84
|
-
if (!item.roles || item.roles.length === 0) {
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
if (!role) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
return item.roles.includes(role);
|
|
91
|
-
};
|
|
92
|
-
var navItemIsActive = (pathname, item) => {
|
|
93
|
-
if (item.href === "/admin") {
|
|
94
|
-
return pathname === "/admin";
|
|
95
|
-
}
|
|
96
|
-
return item.matchPrefixes.some((prefix) => pathname.startsWith(prefix));
|
|
97
|
-
};
|
|
98
82
|
|
|
99
83
|
// src/shared/studioSections.ts
|
|
100
|
-
var studioRoles = /* @__PURE__ */ new Set(["admin", "editor", "client"]);
|
|
84
|
+
var studioRoles = /* @__PURE__ */ new Set(["admin", "developer", "editor", "client"]);
|
|
101
85
|
var studioIcons = new Set(adminNavIcons);
|
|
102
|
-
var dashboardSpans = /* @__PURE__ */ new Set(["full", "half"]);
|
|
103
86
|
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
104
87
|
var isAbsoluteExternalURL = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value) || value.startsWith("//");
|
|
105
88
|
var normalizePathLikeValue = (value) => {
|
|
@@ -141,22 +124,6 @@ var normalizeCard = (value) => {
|
|
|
141
124
|
};
|
|
142
125
|
};
|
|
143
126
|
var normalizeIcon = (value) => typeof value === "string" && studioIcons.has(value) ? value : void 0;
|
|
144
|
-
var normalizeComponent = (value) => {
|
|
145
|
-
if (!isRecord(value)) {
|
|
146
|
-
return void 0;
|
|
147
|
-
}
|
|
148
|
-
const componentPath = typeof value.path === "string" ? value.path.trim() : "";
|
|
149
|
-
const exportName = typeof value.exportName === "string" ? value.exportName.trim() : "";
|
|
150
|
-
if (!componentPath || !exportName) {
|
|
151
|
-
return void 0;
|
|
152
|
-
}
|
|
153
|
-
return {
|
|
154
|
-
exportName,
|
|
155
|
-
path: componentPath,
|
|
156
|
-
...isRecord(value.clientProps) ? { clientProps: value.clientProps } : {}
|
|
157
|
-
};
|
|
158
|
-
};
|
|
159
|
-
var normalizeDashboardSpan = (value) => typeof value === "string" && dashboardSpans.has(value) ? value : "half";
|
|
160
127
|
var resolveStudioSections = (value) => {
|
|
161
128
|
if (!Array.isArray(value)) {
|
|
162
129
|
return [];
|
|
@@ -222,38 +189,6 @@ var resolveStudioSectionViews = (value) => {
|
|
|
222
189
|
}
|
|
223
190
|
return views;
|
|
224
191
|
};
|
|
225
|
-
var resolveStudioSectionDashboards = (value) => {
|
|
226
|
-
if (!Array.isArray(value)) {
|
|
227
|
-
return [];
|
|
228
|
-
}
|
|
229
|
-
const panels = [];
|
|
230
|
-
const seen = /* @__PURE__ */ new Set();
|
|
231
|
-
for (const entry of value) {
|
|
232
|
-
if (!isRecord(entry) || typeof entry.id !== "string" || typeof entry.label !== "string") {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
const id = entry.id.trim();
|
|
236
|
-
const label = entry.label.trim();
|
|
237
|
-
const dashboard = isRecord(entry.dashboard) ? entry.dashboard : null;
|
|
238
|
-
const component = dashboard ? normalizeComponent(dashboard.Component) : void 0;
|
|
239
|
-
const href = typeof entry.href === "string" && entry.href.trim().length > 0 ? normalizePathLikeValue(entry.href) : isRecord(entry.view) && typeof entry.view.path === "string" ? normalizePathLikeValue(entry.view.path) : "";
|
|
240
|
-
if (!id || !label || !dashboard || !component || !href || seen.has(id)) {
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
const priority = typeof dashboard.priority === "number" && Number.isFinite(dashboard.priority) ? dashboard.priority : 100;
|
|
244
|
-
panels.push({
|
|
245
|
-
Component: component,
|
|
246
|
-
href,
|
|
247
|
-
id,
|
|
248
|
-
label,
|
|
249
|
-
priority,
|
|
250
|
-
...normalizeRoles(dashboard.roles ?? entry.roles) ? { roles: normalizeRoles(dashboard.roles ?? entry.roles) } : {},
|
|
251
|
-
span: normalizeDashboardSpan(dashboard.span)
|
|
252
|
-
});
|
|
253
|
-
seen.add(id);
|
|
254
|
-
}
|
|
255
|
-
return panels.sort((a, b) => a.priority === b.priority ? a.label.localeCompare(b.label) : a.priority - b.priority);
|
|
256
|
-
};
|
|
257
192
|
|
|
258
193
|
// src/admin/helpers/configureAdmin.ts
|
|
259
194
|
var import_meta = {};
|
|
@@ -280,8 +215,10 @@ function configureAdmin(config) {
|
|
|
280
215
|
brandPrimary = "#3b82f6",
|
|
281
216
|
brandSecondary = "#8b5cf6",
|
|
282
217
|
defaultTheme = "brand-light",
|
|
218
|
+
logoOnDarkUrl,
|
|
283
219
|
logoUrl,
|
|
284
|
-
allowThemePreference = false
|
|
220
|
+
allowThemePreference = false,
|
|
221
|
+
userSessionDurationSeconds = 60 * 60 * 24
|
|
285
222
|
} = config;
|
|
286
223
|
const studioEnabled = config.studio?.enabled ?? true;
|
|
287
224
|
const formsEnabled = config.studio?.forms?.enabled ?? false;
|
|
@@ -313,7 +250,6 @@ function configureAdmin(config) {
|
|
|
313
250
|
};
|
|
314
251
|
});
|
|
315
252
|
const studioSections = resolveStudioSections(config.studio?.sections || []);
|
|
316
|
-
const studioDashboardPanels = resolveStudioSectionDashboards(config.studio?.sections || []);
|
|
317
253
|
const studioSectionViews = resolveStudioSectionViews(config.studio?.sections || []);
|
|
318
254
|
const sitePreview = config.studio?.sitePreview;
|
|
319
255
|
let cssPath;
|
|
@@ -343,7 +279,6 @@ function configureAdmin(config) {
|
|
|
343
279
|
cssPath = genPath;
|
|
344
280
|
}
|
|
345
281
|
const clientPath = "@orion-studios/payload-studio/admin/client";
|
|
346
|
-
const adminPath = "@orion-studios/payload-studio/admin";
|
|
347
282
|
const studioNavClientProps = {
|
|
348
283
|
brandName,
|
|
349
284
|
formSubmissionsCollectionSlug,
|
|
@@ -355,14 +290,8 @@ function configureAdmin(config) {
|
|
|
355
290
|
logoUrl,
|
|
356
291
|
mediaCollectionSlug,
|
|
357
292
|
pagesCollectionSlug,
|
|
358
|
-
dashboardPanels: studioDashboardPanels,
|
|
359
293
|
sections: studioSections
|
|
360
294
|
};
|
|
361
|
-
const dashboardImportMapGenerator = studioDashboardPanels.length > 0 ? ({ addToImportMap }) => {
|
|
362
|
-
addToImportMap(
|
|
363
|
-
studioDashboardPanels.map((panel) => panel.Component)
|
|
364
|
-
);
|
|
365
|
-
} : void 0;
|
|
366
295
|
const studioBackBreadcrumbComponent = {
|
|
367
296
|
exportName: "StudioBackBreadcrumb",
|
|
368
297
|
path: clientPath
|
|
@@ -394,14 +323,52 @@ function configureAdmin(config) {
|
|
|
394
323
|
}
|
|
395
324
|
};
|
|
396
325
|
};
|
|
326
|
+
const attachStudioEditRedirectToCollection = (collection, options) => {
|
|
327
|
+
if (!studioEnabled) {
|
|
328
|
+
return collection;
|
|
329
|
+
}
|
|
330
|
+
const collectionWithBreadcrumb = attachStudioBackBreadcrumbToCollection(collection);
|
|
331
|
+
const existingViews = collectionWithBreadcrumb.admin?.components?.views;
|
|
332
|
+
const existingEditViews = existingViews?.edit;
|
|
333
|
+
const hasCustomEditView = Boolean(
|
|
334
|
+
existingEditViews?.root || existingEditViews?.default && typeof existingEditViews.default === "object" && existingEditViews.default.Component
|
|
335
|
+
);
|
|
336
|
+
if (hasCustomEditView) {
|
|
337
|
+
return collectionWithBreadcrumb;
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
...collectionWithBreadcrumb,
|
|
341
|
+
admin: {
|
|
342
|
+
...collectionWithBreadcrumb.admin,
|
|
343
|
+
components: {
|
|
344
|
+
...collectionWithBreadcrumb.admin?.components,
|
|
345
|
+
views: {
|
|
346
|
+
...existingViews,
|
|
347
|
+
edit: {
|
|
348
|
+
...existingEditViews,
|
|
349
|
+
default: {
|
|
350
|
+
...typeof existingEditViews?.default === "object" ? existingEditViews.default : {},
|
|
351
|
+
Component: {
|
|
352
|
+
exportName: "StudioDocumentRedirect",
|
|
353
|
+
path: clientPath,
|
|
354
|
+
clientProps: {
|
|
355
|
+
description: options.description,
|
|
356
|
+
...options.emptyHref ? { emptyHref: options.emptyHref } : {},
|
|
357
|
+
...options.emptyLabel ? { emptyLabel: options.emptyLabel } : {},
|
|
358
|
+
pathBase: options.pathBase,
|
|
359
|
+
title: options.title
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
};
|
|
397
369
|
return {
|
|
398
370
|
admin: {
|
|
399
371
|
css: cssPath,
|
|
400
|
-
...dashboardImportMapGenerator ? {
|
|
401
|
-
importMap: {
|
|
402
|
-
generators: [dashboardImportMapGenerator]
|
|
403
|
-
}
|
|
404
|
-
} : {},
|
|
405
372
|
components: {
|
|
406
373
|
...studioEnabled ? {
|
|
407
374
|
Nav: {
|
|
@@ -416,6 +383,7 @@ function configureAdmin(config) {
|
|
|
416
383
|
path: clientPath,
|
|
417
384
|
clientProps: {
|
|
418
385
|
brandName,
|
|
386
|
+
logoOnDarkUrl,
|
|
419
387
|
logoUrl
|
|
420
388
|
}
|
|
421
389
|
},
|
|
@@ -424,6 +392,7 @@ function configureAdmin(config) {
|
|
|
424
392
|
path: clientPath,
|
|
425
393
|
clientProps: {
|
|
426
394
|
brandName,
|
|
395
|
+
logoOnDarkUrl,
|
|
427
396
|
logoUrl
|
|
428
397
|
}
|
|
429
398
|
}
|
|
@@ -432,12 +401,13 @@ function configureAdmin(config) {
|
|
|
432
401
|
dashboard: {
|
|
433
402
|
Component: {
|
|
434
403
|
exportName: studioEnabled ? "AdminStudioDashboard" : "Dashboard",
|
|
435
|
-
path:
|
|
404
|
+
path: clientPath,
|
|
436
405
|
clientProps: studioNavClientProps
|
|
437
406
|
}
|
|
438
407
|
},
|
|
439
408
|
...studioEnabled ? {
|
|
440
409
|
studioGlobals: {
|
|
410
|
+
exact: true,
|
|
441
411
|
path: globalsBasePath,
|
|
442
412
|
Component: {
|
|
443
413
|
exportName: "AdminStudioGlobalsView",
|
|
@@ -449,10 +419,11 @@ function configureAdmin(config) {
|
|
|
449
419
|
}
|
|
450
420
|
}
|
|
451
421
|
},
|
|
452
|
-
|
|
453
|
-
|
|
422
|
+
studioPageNew: {
|
|
423
|
+
exact: true,
|
|
424
|
+
path: `${pagesBasePath}/new`,
|
|
454
425
|
Component: {
|
|
455
|
-
exportName: "
|
|
426
|
+
exportName: "AdminStudioNewPageView",
|
|
456
427
|
path: clientPath,
|
|
457
428
|
clientProps: {
|
|
458
429
|
...studioNavClientProps,
|
|
@@ -461,6 +432,7 @@ function configureAdmin(config) {
|
|
|
461
432
|
}
|
|
462
433
|
},
|
|
463
434
|
studioPageEditor: {
|
|
435
|
+
exact: true,
|
|
464
436
|
path: `${pagesBasePath}/:id`,
|
|
465
437
|
Component: {
|
|
466
438
|
exportName: "AdminStudioPageEditView",
|
|
@@ -471,10 +443,11 @@ function configureAdmin(config) {
|
|
|
471
443
|
}
|
|
472
444
|
}
|
|
473
445
|
},
|
|
474
|
-
|
|
475
|
-
|
|
446
|
+
studioPages: {
|
|
447
|
+
exact: true,
|
|
448
|
+
path: pagesBasePath,
|
|
476
449
|
Component: {
|
|
477
|
-
exportName: "
|
|
450
|
+
exportName: "AdminStudioPagesListView",
|
|
478
451
|
path: clientPath,
|
|
479
452
|
clientProps: {
|
|
480
453
|
...studioNavClientProps,
|
|
@@ -483,6 +456,7 @@ function configureAdmin(config) {
|
|
|
483
456
|
}
|
|
484
457
|
},
|
|
485
458
|
studioContactForm: {
|
|
459
|
+
exact: true,
|
|
486
460
|
path: contactFormStudioPath,
|
|
487
461
|
Component: {
|
|
488
462
|
exportName: "AdminStudioContactFormView",
|
|
@@ -495,7 +469,47 @@ function configureAdmin(config) {
|
|
|
495
469
|
}
|
|
496
470
|
},
|
|
497
471
|
...formsEnabled ? {
|
|
472
|
+
studioFormSubmission: {
|
|
473
|
+
exact: true,
|
|
474
|
+
path: `${formsBasePath}/submissions/:id`,
|
|
475
|
+
Component: {
|
|
476
|
+
exportName: "AdminStudioFormSubmissionView",
|
|
477
|
+
path: clientPath,
|
|
478
|
+
clientProps: {
|
|
479
|
+
...studioNavClientProps,
|
|
480
|
+
formsCollectionSlug,
|
|
481
|
+
formSubmissionsCollectionSlug,
|
|
482
|
+
formUploadsCollectionSlug
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
studioFormUpload: {
|
|
487
|
+
exact: true,
|
|
488
|
+
path: `${formsBasePath}/uploads/:id`,
|
|
489
|
+
Component: {
|
|
490
|
+
exportName: "AdminStudioFormUploadView",
|
|
491
|
+
path: clientPath,
|
|
492
|
+
clientProps: {
|
|
493
|
+
...studioNavClientProps,
|
|
494
|
+
formUploadsCollectionSlug
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
studioFormDetail: {
|
|
499
|
+
exact: true,
|
|
500
|
+
path: `${formsBasePath}/:id`,
|
|
501
|
+
Component: {
|
|
502
|
+
exportName: "AdminStudioFormDetailView",
|
|
503
|
+
path: clientPath,
|
|
504
|
+
clientProps: {
|
|
505
|
+
...studioNavClientProps,
|
|
506
|
+
formsCollectionSlug,
|
|
507
|
+
formSubmissionsCollectionSlug
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
},
|
|
498
511
|
studioForms: {
|
|
512
|
+
exact: true,
|
|
499
513
|
path: formsBasePath,
|
|
500
514
|
Component: {
|
|
501
515
|
exportName: "AdminStudioFormsView",
|
|
@@ -509,10 +523,11 @@ function configureAdmin(config) {
|
|
|
509
523
|
}
|
|
510
524
|
}
|
|
511
525
|
} : {},
|
|
512
|
-
|
|
513
|
-
|
|
526
|
+
studioMediaItem: {
|
|
527
|
+
exact: true,
|
|
528
|
+
path: `${mediaBasePath}/:id`,
|
|
514
529
|
Component: {
|
|
515
|
-
exportName: "
|
|
530
|
+
exportName: "AdminStudioMediaItemView",
|
|
516
531
|
path: clientPath,
|
|
517
532
|
clientProps: {
|
|
518
533
|
...studioNavClientProps,
|
|
@@ -520,10 +535,11 @@ function configureAdmin(config) {
|
|
|
520
535
|
}
|
|
521
536
|
}
|
|
522
537
|
},
|
|
523
|
-
|
|
524
|
-
|
|
538
|
+
studioMedia: {
|
|
539
|
+
exact: true,
|
|
540
|
+
path: mediaBasePath,
|
|
525
541
|
Component: {
|
|
526
|
-
exportName: "
|
|
542
|
+
exportName: "AdminStudioMediaView",
|
|
527
543
|
path: clientPath,
|
|
528
544
|
clientProps: {
|
|
529
545
|
...studioNavClientProps,
|
|
@@ -532,6 +548,7 @@ function configureAdmin(config) {
|
|
|
532
548
|
}
|
|
533
549
|
},
|
|
534
550
|
studioTools: {
|
|
551
|
+
exact: true,
|
|
535
552
|
path: toolsBasePath,
|
|
536
553
|
Component: {
|
|
537
554
|
exportName: "AdminStudioToolsView",
|
|
@@ -576,6 +593,7 @@ function configureAdmin(config) {
|
|
|
576
593
|
path: clientPath,
|
|
577
594
|
clientProps: {
|
|
578
595
|
brandName,
|
|
596
|
+
logoOnDarkUrl,
|
|
579
597
|
logoUrl
|
|
580
598
|
}
|
|
581
599
|
}
|
|
@@ -612,8 +630,17 @@ function configureAdmin(config) {
|
|
|
612
630
|
const hasThemePreference = existingFields.some(
|
|
613
631
|
(field) => typeof field === "object" && field !== null && "name" in field && field.name === "themePreference"
|
|
614
632
|
);
|
|
633
|
+
const normalizedAuth = usersCollection.auth === true ? {
|
|
634
|
+
tokenExpiration: userSessionDurationSeconds,
|
|
635
|
+
useSessions: true
|
|
636
|
+
} : usersCollection.auth && typeof usersCollection.auth === "object" ? {
|
|
637
|
+
...usersCollection.auth,
|
|
638
|
+
tokenExpiration: usersCollection.auth.tokenExpiration ?? userSessionDurationSeconds,
|
|
639
|
+
useSessions: usersCollection.auth.useSessions ?? true
|
|
640
|
+
} : usersCollection.auth;
|
|
615
641
|
const nextCollection = {
|
|
616
642
|
...usersCollection,
|
|
643
|
+
auth: normalizedAuth,
|
|
617
644
|
fields: !allowThemePreference || hasThemePreference ? existingFields : [...existingFields, createThemePreferenceField(defaultTheme)]
|
|
618
645
|
};
|
|
619
646
|
return attachStudioBackBreadcrumbToCollection(nextCollection);
|
|
@@ -675,13 +702,31 @@ function configureAdmin(config) {
|
|
|
675
702
|
return attachStudioBackBreadcrumbToCollection(mediaCollection);
|
|
676
703
|
},
|
|
677
704
|
wrapFormsCollection(formsCollection) {
|
|
678
|
-
return
|
|
705
|
+
return attachStudioEditRedirectToCollection(formsCollection, {
|
|
706
|
+
description: "Redirecting to the Studio form workspace.",
|
|
707
|
+
emptyHref: formsBasePath,
|
|
708
|
+
emptyLabel: "Open Forms",
|
|
709
|
+
pathBase: formsBasePath,
|
|
710
|
+
title: "Opening Form..."
|
|
711
|
+
});
|
|
679
712
|
},
|
|
680
713
|
wrapFormSubmissionsCollection(formSubmissionsCollection) {
|
|
681
|
-
return
|
|
714
|
+
return attachStudioEditRedirectToCollection(formSubmissionsCollection, {
|
|
715
|
+
description: "Redirecting to the Studio submission workspace.",
|
|
716
|
+
emptyHref: formsBasePath,
|
|
717
|
+
emptyLabel: "Open Forms",
|
|
718
|
+
pathBase: `${formsBasePath}/submissions`,
|
|
719
|
+
title: "Opening Submission..."
|
|
720
|
+
});
|
|
682
721
|
},
|
|
683
722
|
wrapFormUploadsCollection(formUploadsCollection) {
|
|
684
|
-
return
|
|
723
|
+
return attachStudioEditRedirectToCollection(formUploadsCollection, {
|
|
724
|
+
description: "Redirecting to the Studio upload workspace.",
|
|
725
|
+
emptyHref: formsBasePath,
|
|
726
|
+
emptyLabel: "Open Forms",
|
|
727
|
+
pathBase: `${formsBasePath}/uploads`,
|
|
728
|
+
title: "Opening Upload..."
|
|
729
|
+
});
|
|
685
730
|
},
|
|
686
731
|
wrapGlobals(globals2) {
|
|
687
732
|
const labelMap = {
|
|
@@ -828,1431 +873,6 @@ function configureAdmin(config) {
|
|
|
828
873
|
};
|
|
829
874
|
}
|
|
830
875
|
|
|
831
|
-
// src/admin/components/studio/AdminStudioDashboard.tsx
|
|
832
|
-
var import_RenderServerComponent = require("@payloadcms/ui/elements/RenderServerComponent");
|
|
833
|
-
|
|
834
|
-
// src/admin-app/components/AdminBreadcrumbs.tsx
|
|
835
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
836
|
-
function AdminBreadcrumbs({ items }) {
|
|
837
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { "aria-label": "Breadcrumb", className: "orion-admin-breadcrumbs", children: items.map((item, index) => {
|
|
838
|
-
const isLast = index === items.length - 1;
|
|
839
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
840
|
-
item.href && !isLast ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: item.href, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: item.label }),
|
|
841
|
-
!isLast ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "orion-admin-breadcrumb-sep", children: "/" }) : null
|
|
842
|
-
] }, `${item.label}-${index}`);
|
|
843
|
-
}) });
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
// src/admin-app/components/AdminPage.tsx
|
|
847
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
848
|
-
function AdminPage({ title, description, breadcrumbs, actions, children }) {
|
|
849
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "orion-admin-page", children: [
|
|
850
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "orion-admin-page-header", children: [
|
|
851
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AdminBreadcrumbs, { items: breadcrumbs }),
|
|
852
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "orion-admin-page-title-row", children: [
|
|
853
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
854
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { children: title }),
|
|
855
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: description }) : null
|
|
856
|
-
] }),
|
|
857
|
-
actions ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "orion-admin-page-actions", children: actions }) : null
|
|
858
|
-
] })
|
|
859
|
-
] }),
|
|
860
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "orion-admin-page-content", children })
|
|
861
|
-
] });
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
// src/admin/components/studio/AdminStudioDashboardClient.tsx
|
|
865
|
-
var import_react = require("react");
|
|
866
|
-
var import_link = __toESM(require("next/link"));
|
|
867
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
868
|
-
var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
869
|
-
var isRole = (value) => value === "admin" || value === "editor" || value === "client";
|
|
870
|
-
var canReviewForms = (role) => role === "admin" || role === "editor";
|
|
871
|
-
var canCreatePages = (role) => role === "admin" || role === "editor";
|
|
872
|
-
var canAccess = (role, roles) => {
|
|
873
|
-
if (!roles || roles.length === 0) {
|
|
874
|
-
return true;
|
|
875
|
-
}
|
|
876
|
-
if (!role) {
|
|
877
|
-
return false;
|
|
878
|
-
}
|
|
879
|
-
return roles.includes(role);
|
|
880
|
-
};
|
|
881
|
-
var asText = (value, fallback) => typeof value === "string" && value.trim().length > 0 ? value.trim() : fallback;
|
|
882
|
-
var asID = (value) => {
|
|
883
|
-
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
884
|
-
return "";
|
|
885
|
-
};
|
|
886
|
-
var toTimestamp = (value) => {
|
|
887
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
888
|
-
return Number.NaN;
|
|
889
|
-
}
|
|
890
|
-
const timestamp = Date.parse(value);
|
|
891
|
-
return Number.isFinite(timestamp) ? timestamp : Number.NaN;
|
|
892
|
-
};
|
|
893
|
-
var isRecent = (value) => {
|
|
894
|
-
const timestamp = toTimestamp(value);
|
|
895
|
-
return Number.isFinite(timestamp) && Date.now() - timestamp <= SEVEN_DAYS_MS;
|
|
896
|
-
};
|
|
897
|
-
var formatDateTime = (value) => {
|
|
898
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
899
|
-
return "Unknown time";
|
|
900
|
-
}
|
|
901
|
-
const date = new Date(value);
|
|
902
|
-
if (Number.isNaN(date.getTime())) {
|
|
903
|
-
return value;
|
|
904
|
-
}
|
|
905
|
-
return new Intl.DateTimeFormat(void 0, {
|
|
906
|
-
dateStyle: "medium",
|
|
907
|
-
timeStyle: "short"
|
|
908
|
-
}).format(date);
|
|
909
|
-
};
|
|
910
|
-
var formatRelativeTime = (timestamp) => {
|
|
911
|
-
if (!Number.isFinite(timestamp)) {
|
|
912
|
-
return "Unknown time";
|
|
913
|
-
}
|
|
914
|
-
const diffMs = timestamp - Date.now();
|
|
915
|
-
const diffMinutes = Math.round(diffMs / (60 * 1e3));
|
|
916
|
-
const rtf = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
|
|
917
|
-
if (Math.abs(diffMinutes) < 60) {
|
|
918
|
-
return rtf.format(diffMinutes, "minute");
|
|
919
|
-
}
|
|
920
|
-
const diffHours = Math.round(diffMinutes / 60);
|
|
921
|
-
if (Math.abs(diffHours) < 24) {
|
|
922
|
-
return rtf.format(diffHours, "hour");
|
|
923
|
-
}
|
|
924
|
-
const diffDays = Math.round(diffHours / 24);
|
|
925
|
-
return rtf.format(diffDays, "day");
|
|
926
|
-
};
|
|
927
|
-
var readSubmissionIdentity = (value) => {
|
|
928
|
-
if (!value || typeof value !== "object") {
|
|
929
|
-
return "New submission";
|
|
930
|
-
}
|
|
931
|
-
const data = value;
|
|
932
|
-
const firstName = typeof data.firstName === "string" ? data.firstName.trim() : "";
|
|
933
|
-
const lastName = typeof data.lastName === "string" ? data.lastName.trim() : "";
|
|
934
|
-
const name = typeof data.name === "string" ? data.name.trim() : "";
|
|
935
|
-
const email = typeof data.email === "string" ? data.email.trim() : typeof data.contactEmail === "string" ? data.contactEmail.trim() : "";
|
|
936
|
-
const fullName = [firstName, lastName].filter(Boolean).join(" ").trim();
|
|
937
|
-
return fullName || name || email || "New submission";
|
|
938
|
-
};
|
|
939
|
-
var getFormID = (value) => {
|
|
940
|
-
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
941
|
-
if (value && typeof value === "object") {
|
|
942
|
-
const nestedID = value.id;
|
|
943
|
-
if (typeof nestedID === "string" || typeof nestedID === "number") return String(nestedID);
|
|
944
|
-
}
|
|
945
|
-
return "";
|
|
946
|
-
};
|
|
947
|
-
var getFormTitle = (value) => {
|
|
948
|
-
if (!value || typeof value !== "object") {
|
|
949
|
-
return "";
|
|
950
|
-
}
|
|
951
|
-
const title = value.title;
|
|
952
|
-
if (typeof title === "string" && title.trim().length > 0) {
|
|
953
|
-
return title.trim();
|
|
954
|
-
}
|
|
955
|
-
const slug = value.slug;
|
|
956
|
-
return typeof slug === "string" && slug.trim().length > 0 ? slug.trim() : "";
|
|
957
|
-
};
|
|
958
|
-
var buildSearchParams = (params) => new URLSearchParams(
|
|
959
|
-
Object.entries(params).filter(([, value]) => typeof value === "string" && value.length > 0)
|
|
960
|
-
).toString();
|
|
961
|
-
async function loadCollection(path2) {
|
|
962
|
-
const response = await fetch(path2, {
|
|
963
|
-
cache: "no-store",
|
|
964
|
-
credentials: "include"
|
|
965
|
-
});
|
|
966
|
-
if (!response.ok) {
|
|
967
|
-
const body = await response.text();
|
|
968
|
-
throw new Error(body || `Request failed: ${response.status}`);
|
|
969
|
-
}
|
|
970
|
-
return await response.json();
|
|
971
|
-
}
|
|
972
|
-
async function loadPages(collectionSlug) {
|
|
973
|
-
const params = buildSearchParams({
|
|
974
|
-
depth: "0",
|
|
975
|
-
draft: "true",
|
|
976
|
-
limit: "200",
|
|
977
|
-
sort: "-updatedAt"
|
|
978
|
-
});
|
|
979
|
-
const result = await loadCollection(`/api/${collectionSlug}?${params}`);
|
|
980
|
-
const docs = Array.isArray(result.docs) ? result.docs : [];
|
|
981
|
-
return {
|
|
982
|
-
draftCount: docs.filter((doc) => doc._status === "draft").length,
|
|
983
|
-
recent: docs.slice(0, 8),
|
|
984
|
-
total: typeof result.totalDocs === "number" ? result.totalDocs : docs.length,
|
|
985
|
-
updatedThisWeek: docs.filter((doc) => isRecent(doc.updatedAt)).length
|
|
986
|
-
};
|
|
987
|
-
}
|
|
988
|
-
async function loadForms(formsCollectionSlug, submissionsCollectionSlug) {
|
|
989
|
-
const [formsResult, submissionsResult] = await Promise.all([
|
|
990
|
-
loadCollection(
|
|
991
|
-
`/api/${formsCollectionSlug}?${buildSearchParams({
|
|
992
|
-
depth: "0",
|
|
993
|
-
draft: "true",
|
|
994
|
-
limit: "80",
|
|
995
|
-
sort: "-updatedAt"
|
|
996
|
-
})}`
|
|
997
|
-
),
|
|
998
|
-
loadCollection(
|
|
999
|
-
`/api/${submissionsCollectionSlug}?${buildSearchParams({
|
|
1000
|
-
depth: "1",
|
|
1001
|
-
limit: "40",
|
|
1002
|
-
sort: "-submittedAt"
|
|
1003
|
-
})}`
|
|
1004
|
-
)
|
|
1005
|
-
]);
|
|
1006
|
-
const forms = Array.isArray(formsResult.docs) ? formsResult.docs : [];
|
|
1007
|
-
const recentSubmissions = Array.isArray(submissionsResult.docs) ? submissionsResult.docs : [];
|
|
1008
|
-
const submissionsByForm = /* @__PURE__ */ new Map();
|
|
1009
|
-
for (const submission of recentSubmissions) {
|
|
1010
|
-
const formID = getFormID(submission.form);
|
|
1011
|
-
if (!formID) continue;
|
|
1012
|
-
submissionsByForm.set(formID, (submissionsByForm.get(formID) || 0) + 1);
|
|
1013
|
-
}
|
|
1014
|
-
let busiestFormTitle = null;
|
|
1015
|
-
let busiestFormCount = 0;
|
|
1016
|
-
for (const form of forms) {
|
|
1017
|
-
const formID = asID(form.id);
|
|
1018
|
-
if (!formID) continue;
|
|
1019
|
-
const submissionCount = submissionsByForm.get(formID) || 0;
|
|
1020
|
-
if (submissionCount > busiestFormCount) {
|
|
1021
|
-
busiestFormCount = submissionCount;
|
|
1022
|
-
busiestFormTitle = asText(form.title, "Untitled form");
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
return {
|
|
1026
|
-
busiestFormTitle,
|
|
1027
|
-
forms,
|
|
1028
|
-
recentSubmissions,
|
|
1029
|
-
submissionsThisWeek: recentSubmissions.filter((submission) => isRecent(submission.submittedAt)).length,
|
|
1030
|
-
totalForms: typeof formsResult.totalDocs === "number" ? formsResult.totalDocs : forms.length
|
|
1031
|
-
};
|
|
1032
|
-
}
|
|
1033
|
-
async function loadMedia(collectionSlug) {
|
|
1034
|
-
const params = buildSearchParams({
|
|
1035
|
-
depth: "0",
|
|
1036
|
-
limit: "24",
|
|
1037
|
-
sort: "-updatedAt"
|
|
1038
|
-
});
|
|
1039
|
-
const result = await loadCollection(`/api/${collectionSlug}?${params}`);
|
|
1040
|
-
const docs = Array.isArray(result.docs) ? result.docs : [];
|
|
1041
|
-
return {
|
|
1042
|
-
recent: docs.slice(0, 8),
|
|
1043
|
-
total: typeof result.totalDocs === "number" ? result.totalDocs : docs.length,
|
|
1044
|
-
uploadsThisWeek: docs.filter((doc) => isRecent(doc.updatedAt)).length
|
|
1045
|
-
};
|
|
1046
|
-
}
|
|
1047
|
-
var loadingState = {
|
|
1048
|
-
forms: null,
|
|
1049
|
-
media: { status: "loading" },
|
|
1050
|
-
pages: { status: "loading" }
|
|
1051
|
-
};
|
|
1052
|
-
function ModuleStatus({ message }) {
|
|
1053
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-dashboard-inline-note", children: message });
|
|
1054
|
-
}
|
|
1055
|
-
function EmptyState({
|
|
1056
|
-
body,
|
|
1057
|
-
title
|
|
1058
|
-
}) {
|
|
1059
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-empty-state", children: [
|
|
1060
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: title }),
|
|
1061
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: body })
|
|
1062
|
-
] });
|
|
1063
|
-
}
|
|
1064
|
-
function SnapshotMetric({ card }) {
|
|
1065
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "orion-dashboard-snapshot-card", children: [
|
|
1066
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-snapshot-kicker", children: card.kicker }),
|
|
1067
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: card.value }),
|
|
1068
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: card.detail })
|
|
1069
|
-
] });
|
|
1070
|
-
}
|
|
1071
|
-
function AdminStudioDashboardClient({
|
|
1072
|
-
extensionPanels = [],
|
|
1073
|
-
formSubmissionsCollectionSlug,
|
|
1074
|
-
formsCollectionSlug,
|
|
1075
|
-
formsEnabled,
|
|
1076
|
-
formsPath,
|
|
1077
|
-
globalsBasePath,
|
|
1078
|
-
mediaCollectionSlug,
|
|
1079
|
-
mediaPath,
|
|
1080
|
-
pagesCollectionSlug,
|
|
1081
|
-
pagesPath,
|
|
1082
|
-
sectionLinks,
|
|
1083
|
-
toolsPath,
|
|
1084
|
-
userRole
|
|
1085
|
-
}) {
|
|
1086
|
-
const role = isRole(userRole) ? userRole : void 0;
|
|
1087
|
-
const [state, setState] = (0, import_react.useState)(
|
|
1088
|
-
() => formsEnabled && canReviewForms(role) ? {
|
|
1089
|
-
forms: { status: "loading" },
|
|
1090
|
-
media: { status: "loading" },
|
|
1091
|
-
pages: { status: "loading" }
|
|
1092
|
-
} : loadingState
|
|
1093
|
-
);
|
|
1094
|
-
(0, import_react.useEffect)(() => {
|
|
1095
|
-
let cancelled = false;
|
|
1096
|
-
const run = async () => {
|
|
1097
|
-
const includeForms = formsEnabled && canReviewForms(role);
|
|
1098
|
-
(0, import_react.startTransition)(() => {
|
|
1099
|
-
setState({
|
|
1100
|
-
forms: includeForms ? { status: "loading" } : null,
|
|
1101
|
-
media: { status: "loading" },
|
|
1102
|
-
pages: { status: "loading" }
|
|
1103
|
-
});
|
|
1104
|
-
});
|
|
1105
|
-
const [pagesResult, formsResult, mediaResult] = await Promise.allSettled([
|
|
1106
|
-
loadPages(pagesCollectionSlug),
|
|
1107
|
-
includeForms ? loadForms(formsCollectionSlug, formSubmissionsCollectionSlug) : Promise.resolve(null),
|
|
1108
|
-
loadMedia(mediaCollectionSlug)
|
|
1109
|
-
]);
|
|
1110
|
-
if (cancelled) return;
|
|
1111
|
-
(0, import_react.startTransition)(() => {
|
|
1112
|
-
setState({
|
|
1113
|
-
forms: includeForms && formsResult.status === "rejected" ? {
|
|
1114
|
-
error: formsResult.reason instanceof Error ? formsResult.reason.message : "Unable to load form activity.",
|
|
1115
|
-
status: "error"
|
|
1116
|
-
} : includeForms && formsResult.status === "fulfilled" && formsResult.value ? {
|
|
1117
|
-
data: formsResult.value,
|
|
1118
|
-
status: "success"
|
|
1119
|
-
} : null,
|
|
1120
|
-
media: mediaResult.status === "rejected" ? {
|
|
1121
|
-
error: mediaResult.reason instanceof Error ? mediaResult.reason.message : "Unable to load media activity.",
|
|
1122
|
-
status: "error"
|
|
1123
|
-
} : {
|
|
1124
|
-
data: mediaResult.value,
|
|
1125
|
-
status: "success"
|
|
1126
|
-
},
|
|
1127
|
-
pages: pagesResult.status === "rejected" ? {
|
|
1128
|
-
error: pagesResult.reason instanceof Error ? pagesResult.reason.message : "Unable to load page activity.",
|
|
1129
|
-
status: "error"
|
|
1130
|
-
} : {
|
|
1131
|
-
data: pagesResult.value,
|
|
1132
|
-
status: "success"
|
|
1133
|
-
}
|
|
1134
|
-
});
|
|
1135
|
-
});
|
|
1136
|
-
};
|
|
1137
|
-
void run();
|
|
1138
|
-
return () => {
|
|
1139
|
-
cancelled = true;
|
|
1140
|
-
};
|
|
1141
|
-
}, [
|
|
1142
|
-
formSubmissionsCollectionSlug,
|
|
1143
|
-
formsCollectionSlug,
|
|
1144
|
-
formsEnabled,
|
|
1145
|
-
mediaCollectionSlug,
|
|
1146
|
-
pagesCollectionSlug,
|
|
1147
|
-
role
|
|
1148
|
-
]);
|
|
1149
|
-
const visibleWorkspaceLinks = (0, import_react.useMemo)(
|
|
1150
|
-
() => sectionLinks.filter((section) => canAccess(role, section.roles)),
|
|
1151
|
-
[role, sectionLinks]
|
|
1152
|
-
);
|
|
1153
|
-
const activityItems = (0, import_react.useMemo)(() => {
|
|
1154
|
-
const items = [];
|
|
1155
|
-
if (state.pages.status === "success") {
|
|
1156
|
-
for (const doc of state.pages.data.recent) {
|
|
1157
|
-
const id = asID(doc.id);
|
|
1158
|
-
if (!id) continue;
|
|
1159
|
-
const timestamp = toTimestamp(doc.updatedAt);
|
|
1160
|
-
items.push({
|
|
1161
|
-
href: `${pagesPath}/${id}`,
|
|
1162
|
-
id: `page-${id}`,
|
|
1163
|
-
kind: "page",
|
|
1164
|
-
label: typeof doc._status === "string" ? doc._status : "page",
|
|
1165
|
-
meta: Number.isFinite(timestamp) ? formatDateTime(doc.updatedAt) : "Update time unavailable",
|
|
1166
|
-
timestamp,
|
|
1167
|
-
title: asText(doc.title, "Untitled page")
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
if (state.forms?.status === "success") {
|
|
1172
|
-
for (const submission of state.forms.data.recentSubmissions) {
|
|
1173
|
-
const id = asID(submission.id);
|
|
1174
|
-
const formID = getFormID(submission.form);
|
|
1175
|
-
if (!id || !formID) continue;
|
|
1176
|
-
const timestamp = toTimestamp(submission.submittedAt);
|
|
1177
|
-
const formTitle = getFormTitle(submission.form) || "Form response";
|
|
1178
|
-
items.push({
|
|
1179
|
-
href: `${formsPath}?form=${encodeURIComponent(formID)}`,
|
|
1180
|
-
id: `submission-${id}`,
|
|
1181
|
-
kind: "submission",
|
|
1182
|
-
label: formTitle,
|
|
1183
|
-
meta: Number.isFinite(timestamp) ? `${readSubmissionIdentity(submission.data)} \xB7 ${formatDateTime(submission.submittedAt)}` : readSubmissionIdentity(submission.data),
|
|
1184
|
-
timestamp,
|
|
1185
|
-
title: "New submission"
|
|
1186
|
-
});
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
if (state.media.status === "success") {
|
|
1190
|
-
for (const doc of state.media.data.recent) {
|
|
1191
|
-
const id = asID(doc.id);
|
|
1192
|
-
if (!id) continue;
|
|
1193
|
-
const timestamp = toTimestamp(doc.updatedAt);
|
|
1194
|
-
items.push({
|
|
1195
|
-
href: `${mediaPath}/${id}`,
|
|
1196
|
-
id: `media-${id}`,
|
|
1197
|
-
kind: "media",
|
|
1198
|
-
label: asText(doc.mimeType, "Media asset"),
|
|
1199
|
-
meta: Number.isFinite(timestamp) ? formatDateTime(doc.updatedAt) : "Update time unavailable",
|
|
1200
|
-
timestamp,
|
|
1201
|
-
title: asText(doc.filename, "Untitled asset")
|
|
1202
|
-
});
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
return items.filter((item) => Number.isFinite(item.timestamp)).sort((a, b) => b.timestamp - a.timestamp).slice(0, 10);
|
|
1206
|
-
}, [formsPath, mediaPath, pagesPath, state.forms, state.media, state.pages]);
|
|
1207
|
-
const attentionItems = (0, import_react.useMemo)(() => {
|
|
1208
|
-
if (role === "client") {
|
|
1209
|
-
const items2 = [];
|
|
1210
|
-
if (state.pages.status === "success" && state.pages.data.updatedThisWeek > 0) {
|
|
1211
|
-
items2.push({
|
|
1212
|
-
href: pagesPath,
|
|
1213
|
-
id: "pages-updated",
|
|
1214
|
-
label: `${state.pages.data.updatedThisWeek} page${state.pages.data.updatedThisWeek === 1 ? "" : "s"} changed in the last 7 days.`
|
|
1215
|
-
});
|
|
1216
|
-
}
|
|
1217
|
-
if (state.media.status === "success" && state.media.data.uploadsThisWeek > 0) {
|
|
1218
|
-
items2.push({
|
|
1219
|
-
href: mediaPath,
|
|
1220
|
-
id: "media-updated",
|
|
1221
|
-
label: `${state.media.data.uploadsThisWeek} new media asset${state.media.data.uploadsThisWeek === 1 ? "" : "s"} landed this week.`
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
return items2;
|
|
1225
|
-
}
|
|
1226
|
-
const items = [];
|
|
1227
|
-
if (state.pages.status === "success" && state.pages.data.draftCount > 0) {
|
|
1228
|
-
items.push({
|
|
1229
|
-
href: pagesPath,
|
|
1230
|
-
id: "draft-pages",
|
|
1231
|
-
label: `${state.pages.data.draftCount} page${state.pages.data.draftCount === 1 ? "" : "s"} still need publishing review.`,
|
|
1232
|
-
tone: "accent"
|
|
1233
|
-
});
|
|
1234
|
-
}
|
|
1235
|
-
if (state.forms?.status === "success" && state.forms.data.submissionsThisWeek > 0) {
|
|
1236
|
-
items.push({
|
|
1237
|
-
href: formsPath,
|
|
1238
|
-
id: "recent-submissions",
|
|
1239
|
-
label: `${state.forms.data.submissionsThisWeek} form submission${state.forms.data.submissionsThisWeek === 1 ? "" : "s"} arrived in the last 7 days.`,
|
|
1240
|
-
tone: "accent"
|
|
1241
|
-
});
|
|
1242
|
-
}
|
|
1243
|
-
if (state.media.status === "success" && state.media.data.total === 0) {
|
|
1244
|
-
items.push({
|
|
1245
|
-
href: mediaPath,
|
|
1246
|
-
id: "empty-media",
|
|
1247
|
-
label: "The media library is still empty. Add brand assets before content expands."
|
|
1248
|
-
});
|
|
1249
|
-
}
|
|
1250
|
-
if (state.pages.status === "error") {
|
|
1251
|
-
items.push({
|
|
1252
|
-
href: pagesPath,
|
|
1253
|
-
id: "pages-error",
|
|
1254
|
-
label: "Page activity could not be loaded for the dashboard.",
|
|
1255
|
-
tone: "muted"
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
|
-
if (state.forms?.status === "error") {
|
|
1259
|
-
items.push({
|
|
1260
|
-
href: formsPath,
|
|
1261
|
-
id: "forms-error",
|
|
1262
|
-
label: "Form activity could not be loaded for the dashboard.",
|
|
1263
|
-
tone: "muted"
|
|
1264
|
-
});
|
|
1265
|
-
}
|
|
1266
|
-
if (state.media.status === "error") {
|
|
1267
|
-
items.push({
|
|
1268
|
-
href: mediaPath,
|
|
1269
|
-
id: "media-error",
|
|
1270
|
-
label: "Media activity could not be loaded for the dashboard.",
|
|
1271
|
-
tone: "muted"
|
|
1272
|
-
});
|
|
1273
|
-
}
|
|
1274
|
-
return items;
|
|
1275
|
-
}, [formsPath, mediaPath, pagesPath, role, state.forms, state.media, state.pages]);
|
|
1276
|
-
const snapshotCards = (0, import_react.useMemo)(() => {
|
|
1277
|
-
const cards = [];
|
|
1278
|
-
if (state.pages.status === "success") {
|
|
1279
|
-
cards.push(
|
|
1280
|
-
role === "client" ? {
|
|
1281
|
-
detail: `${state.pages.data.updatedThisWeek} updated this week`,
|
|
1282
|
-
kicker: "Pages",
|
|
1283
|
-
value: `${state.pages.data.total}`
|
|
1284
|
-
} : {
|
|
1285
|
-
detail: `${state.pages.data.draftCount} draft${state.pages.data.draftCount === 1 ? "" : "s"} waiting`,
|
|
1286
|
-
kicker: "Pages",
|
|
1287
|
-
value: `${state.pages.data.total}`
|
|
1288
|
-
}
|
|
1289
|
-
);
|
|
1290
|
-
}
|
|
1291
|
-
if (state.forms?.status === "success") {
|
|
1292
|
-
cards.push({
|
|
1293
|
-
detail: state.forms.data.busiestFormTitle ? `Most active: ${state.forms.data.busiestFormTitle}` : "Waiting on the first submission",
|
|
1294
|
-
kicker: "Forms",
|
|
1295
|
-
value: `${state.forms.data.submissionsThisWeek}`
|
|
1296
|
-
});
|
|
1297
|
-
}
|
|
1298
|
-
if (state.media.status === "success") {
|
|
1299
|
-
cards.push({
|
|
1300
|
-
detail: `${state.media.data.uploadsThisWeek} uploaded this week`,
|
|
1301
|
-
kicker: "Media",
|
|
1302
|
-
value: `${state.media.data.total}`
|
|
1303
|
-
});
|
|
1304
|
-
}
|
|
1305
|
-
cards.push({
|
|
1306
|
-
detail: `${visibleWorkspaceLinks.length} section${visibleWorkspaceLinks.length === 1 ? "" : "s"} available`,
|
|
1307
|
-
kicker: "Workspace",
|
|
1308
|
-
value: role ? role.toUpperCase() : "CMS"
|
|
1309
|
-
});
|
|
1310
|
-
return cards.slice(0, 4);
|
|
1311
|
-
}, [role, state.forms, state.media, state.pages, visibleWorkspaceLinks.length]);
|
|
1312
|
-
const primaryActions = (0, import_react.useMemo)(() => {
|
|
1313
|
-
const actions = [];
|
|
1314
|
-
if (canCreatePages(role)) {
|
|
1315
|
-
actions.push({
|
|
1316
|
-
description: "Create or revise content in the visual builder.",
|
|
1317
|
-
href: `${pagesPath}/new`,
|
|
1318
|
-
label: "New Page"
|
|
1319
|
-
});
|
|
1320
|
-
}
|
|
1321
|
-
actions.push({
|
|
1322
|
-
description: "Review live pages and recent edits.",
|
|
1323
|
-
href: pagesPath,
|
|
1324
|
-
label: "Open Pages",
|
|
1325
|
-
tone: "ghost"
|
|
1326
|
-
});
|
|
1327
|
-
if (formsEnabled && canReviewForms(role)) {
|
|
1328
|
-
actions.push({
|
|
1329
|
-
description: "Check submissions and form performance.",
|
|
1330
|
-
href: formsPath,
|
|
1331
|
-
label: "Review Forms",
|
|
1332
|
-
tone: "soft"
|
|
1333
|
-
});
|
|
1334
|
-
}
|
|
1335
|
-
actions.push({
|
|
1336
|
-
description: "Update site settings, navigation, and footer content.",
|
|
1337
|
-
href: globalsBasePath,
|
|
1338
|
-
label: "Open Globals",
|
|
1339
|
-
tone: "ghost"
|
|
1340
|
-
});
|
|
1341
|
-
actions.push({
|
|
1342
|
-
description: "Upload or organize brand and campaign assets.",
|
|
1343
|
-
href: mediaPath,
|
|
1344
|
-
label: "Manage Media",
|
|
1345
|
-
tone: "ghost"
|
|
1346
|
-
});
|
|
1347
|
-
if (role === "admin") {
|
|
1348
|
-
actions.push({
|
|
1349
|
-
description: "Manage users, roles, and fallback tools.",
|
|
1350
|
-
href: toolsPath,
|
|
1351
|
-
label: "Admin Tools",
|
|
1352
|
-
tone: "ghost"
|
|
1353
|
-
});
|
|
1354
|
-
}
|
|
1355
|
-
return actions;
|
|
1356
|
-
}, [formsEnabled, formsPath, globalsBasePath, mediaPath, pagesPath, role, toolsPath]);
|
|
1357
|
-
const attentionTitle = role === "client" ? "What Changed" : "Needs Attention";
|
|
1358
|
-
const attentionDescription = role === "client" ? "A quick read on recent content and asset changes." : "The highest-signal items that still need review.";
|
|
1359
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-layout", children: [
|
|
1360
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "orion-dashboard-panel orion-dashboard-panel--attention", children: [
|
|
1361
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-panel-header", children: [
|
|
1362
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1363
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-panel-kicker", children: attentionTitle }),
|
|
1364
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: attentionDescription })
|
|
1365
|
-
] }),
|
|
1366
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-panel-meta", children: "Last 7 days" })
|
|
1367
|
-
] }),
|
|
1368
|
-
attentionItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-dashboard-attention-list", children: attentionItems.map(
|
|
1369
|
-
(item) => item.href ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1370
|
-
import_link.default,
|
|
1371
|
-
{
|
|
1372
|
-
className: ["orion-dashboard-attention-item", item.tone ? `is-${item.tone}` : ""].filter(Boolean).join(" "),
|
|
1373
|
-
href: item.href,
|
|
1374
|
-
children: [
|
|
1375
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: item.label }),
|
|
1376
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Open" })
|
|
1377
|
-
]
|
|
1378
|
-
},
|
|
1379
|
-
item.id
|
|
1380
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1381
|
-
"div",
|
|
1382
|
-
{
|
|
1383
|
-
className: ["orion-dashboard-attention-item", item.tone ? `is-${item.tone}` : ""].filter(Boolean).join(" "),
|
|
1384
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: item.label })
|
|
1385
|
-
},
|
|
1386
|
-
item.id
|
|
1387
|
-
)
|
|
1388
|
-
) }) : state.pages.status === "loading" || state.media.status === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModuleStatus, { message: "Loading attention items..." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1389
|
-
EmptyState,
|
|
1390
|
-
{
|
|
1391
|
-
body: role === "client" ? "No major changes landed during the current review window." : "No urgent follow-up surfaced from content, forms, or media activity.",
|
|
1392
|
-
title: "Everything looks steady"
|
|
1393
|
-
}
|
|
1394
|
-
)
|
|
1395
|
-
] }),
|
|
1396
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "orion-dashboard-panel orion-dashboard-panel--actions", children: [
|
|
1397
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-panel-header", children: [
|
|
1398
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1399
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-panel-kicker", children: "Quick Actions" }),
|
|
1400
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: "Jump into the work that matters most." })
|
|
1401
|
-
] }),
|
|
1402
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "orion-dashboard-panel-meta", children: [
|
|
1403
|
-
role || "studio",
|
|
1404
|
-
" mode"
|
|
1405
|
-
] })
|
|
1406
|
-
] }),
|
|
1407
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-dashboard-action-list", children: primaryActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1408
|
-
import_link.default,
|
|
1409
|
-
{
|
|
1410
|
-
className: [
|
|
1411
|
-
"orion-dashboard-action",
|
|
1412
|
-
action.tone === "ghost" ? "is-ghost" : action.tone === "soft" ? "is-soft" : ""
|
|
1413
|
-
].filter(Boolean).join(" "),
|
|
1414
|
-
href: action.href,
|
|
1415
|
-
children: [
|
|
1416
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: action.label }),
|
|
1417
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: action.description })
|
|
1418
|
-
]
|
|
1419
|
-
},
|
|
1420
|
-
action.label
|
|
1421
|
-
)) }),
|
|
1422
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-workspace-strip", children: [
|
|
1423
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-workspace-label", children: "Workspace" }),
|
|
1424
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-dashboard-workspace-pills", children: visibleWorkspaceLinks.map((section) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link.default, { className: "orion-dashboard-workspace-pill", href: section.href, children: section.label }, section.id)) })
|
|
1425
|
-
] })
|
|
1426
|
-
] }),
|
|
1427
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "orion-dashboard-panel orion-dashboard-panel--activity", children: [
|
|
1428
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-panel-header", children: [
|
|
1429
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1430
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-panel-kicker", children: "Recent Activity" }),
|
|
1431
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: "The freshest edits, responses, and uploads across the studio." })
|
|
1432
|
-
] }),
|
|
1433
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "orion-dashboard-panel-meta", children: [
|
|
1434
|
-
activityItems.length,
|
|
1435
|
-
" items"
|
|
1436
|
-
] })
|
|
1437
|
-
] }),
|
|
1438
|
-
activityItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-dashboard-activity-list", children: activityItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_link.default, { className: `orion-dashboard-activity-item is-${item.kind}`, href: item.href, children: [
|
|
1439
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-activity-copy", children: [
|
|
1440
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-activity-topline", children: [
|
|
1441
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: item.title }),
|
|
1442
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: formatRelativeTime(item.timestamp) })
|
|
1443
|
-
] }),
|
|
1444
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: item.meta })
|
|
1445
|
-
] }),
|
|
1446
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-activity-pill", children: item.label })
|
|
1447
|
-
] }, item.id)) }) : state.pages.status === "loading" || state.media.status === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModuleStatus, { message: "Loading activity feed..." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1448
|
-
EmptyState,
|
|
1449
|
-
{
|
|
1450
|
-
body: "Recent page edits, submissions, and uploads will start stacking here as soon as the team gets moving.",
|
|
1451
|
-
title: "No recent activity yet"
|
|
1452
|
-
}
|
|
1453
|
-
)
|
|
1454
|
-
] }),
|
|
1455
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "orion-dashboard-panel orion-dashboard-panel--snapshot", children: [
|
|
1456
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-panel-header", children: [
|
|
1457
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
1458
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-panel-kicker", children: "Business Snapshot" }),
|
|
1459
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { children: "A compact read on content momentum and performance." })
|
|
1460
|
-
] }),
|
|
1461
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-dashboard-panel-meta", children: "30-day lens" })
|
|
1462
|
-
] }),
|
|
1463
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-dashboard-snapshot-grid", children: [
|
|
1464
|
-
snapshotCards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SnapshotMetric, { card }, card.kicker)),
|
|
1465
|
-
extensionPanels.map((panel) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1466
|
-
"div",
|
|
1467
|
-
{
|
|
1468
|
-
className: [
|
|
1469
|
-
"orion-dashboard-extension-panel",
|
|
1470
|
-
panel.span === "full" ? "is-full" : "is-half"
|
|
1471
|
-
].filter(Boolean).join(" "),
|
|
1472
|
-
children: panel.node
|
|
1473
|
-
},
|
|
1474
|
-
panel.id
|
|
1475
|
-
))
|
|
1476
|
-
] }),
|
|
1477
|
-
state.pages.status === "error" || state.media.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "orion-dashboard-inline-note", children: "Some dashboard modules could not be loaded. The rest of the workspace remains available." }) : null
|
|
1478
|
-
] })
|
|
1479
|
-
] });
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
// src/admin/components/studio/StudioSectionLayout.tsx
|
|
1483
|
-
var import_react5 = require("react");
|
|
1484
|
-
var import_navigation = require("next/navigation");
|
|
1485
|
-
var import_ui = require("@payloadcms/ui");
|
|
1486
|
-
|
|
1487
|
-
// src/admin-app/components/AdminShellClient.tsx
|
|
1488
|
-
var import_react2 = require("react");
|
|
1489
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1490
|
-
var iconSize = 20;
|
|
1491
|
-
var iconStyle = { display: "block", flexShrink: 0 };
|
|
1492
|
-
function NavIcon({ name }) {
|
|
1493
|
-
const props = { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: iconStyle };
|
|
1494
|
-
switch (name) {
|
|
1495
|
-
case "dashboard":
|
|
1496
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1497
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "3", y: "3", width: "7", height: "9", rx: "1" }),
|
|
1498
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "14", y: "3", width: "7", height: "5", rx: "1" }),
|
|
1499
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "14", y: "12", width: "7", height: "9", rx: "1" }),
|
|
1500
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "3", y: "16", width: "7", height: "5", rx: "1" })
|
|
1501
|
-
] });
|
|
1502
|
-
case "pages":
|
|
1503
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1504
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" }),
|
|
1505
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "14 2 14 8 20 8" }),
|
|
1506
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "8", y1: "13", x2: "16", y2: "13" }),
|
|
1507
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "8", y1: "17", x2: "12", y2: "17" })
|
|
1508
|
-
] });
|
|
1509
|
-
case "forms":
|
|
1510
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1511
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M9 3h6" }),
|
|
1512
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M12 3v18" }),
|
|
1513
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M5 7h14a2 2 0 0 1 2 2v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a2 2 0 0 1 2-2Z" }),
|
|
1514
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M7 11h10" }),
|
|
1515
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M7 15h6" })
|
|
1516
|
-
] });
|
|
1517
|
-
case "globals":
|
|
1518
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1519
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "3" }),
|
|
1520
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" })
|
|
1521
|
-
] });
|
|
1522
|
-
case "media":
|
|
1523
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1524
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
1525
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
|
|
1526
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "21 15 16 10 5 21" })
|
|
1527
|
-
] });
|
|
1528
|
-
case "tools":
|
|
1529
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76Z" }) });
|
|
1530
|
-
case "analytics":
|
|
1531
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1532
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4 19V5" }),
|
|
1533
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M10 19V10" }),
|
|
1534
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M16 19v-6" }),
|
|
1535
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M22 19V3" })
|
|
1536
|
-
] });
|
|
1537
|
-
case "account":
|
|
1538
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { ...props, children: [
|
|
1539
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
|
|
1540
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "7", r: "4" })
|
|
1541
|
-
] });
|
|
1542
|
-
default:
|
|
1543
|
-
return null;
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
function AdminShellClient({
|
|
1547
|
-
children,
|
|
1548
|
-
brandName,
|
|
1549
|
-
logoUrl,
|
|
1550
|
-
userEmail,
|
|
1551
|
-
userRole,
|
|
1552
|
-
pathname,
|
|
1553
|
-
navItems,
|
|
1554
|
-
onLogout,
|
|
1555
|
-
storageKey = "orion-admin-shell-collapsed"
|
|
1556
|
-
}) {
|
|
1557
|
-
const [collapsed, setCollapsed] = (0, import_react2.useState)(false);
|
|
1558
|
-
const [loggingOut, setLoggingOut] = (0, import_react2.useState)(false);
|
|
1559
|
-
(0, import_react2.useEffect)(() => {
|
|
1560
|
-
try {
|
|
1561
|
-
const stored = window.localStorage.getItem(storageKey);
|
|
1562
|
-
if (stored === "1") {
|
|
1563
|
-
setCollapsed(true);
|
|
1564
|
-
}
|
|
1565
|
-
} catch {
|
|
1566
|
-
}
|
|
1567
|
-
}, [storageKey]);
|
|
1568
|
-
const toggleSidebar = () => {
|
|
1569
|
-
setCollapsed((current) => {
|
|
1570
|
-
const next = !current;
|
|
1571
|
-
try {
|
|
1572
|
-
window.localStorage.setItem(storageKey, next ? "1" : "0");
|
|
1573
|
-
} catch {
|
|
1574
|
-
}
|
|
1575
|
-
return next;
|
|
1576
|
-
});
|
|
1577
|
-
};
|
|
1578
|
-
const handleLogout = async () => {
|
|
1579
|
-
setLoggingOut(true);
|
|
1580
|
-
try {
|
|
1581
|
-
await onLogout();
|
|
1582
|
-
} finally {
|
|
1583
|
-
setLoggingOut(false);
|
|
1584
|
-
}
|
|
1585
|
-
};
|
|
1586
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `orion-admin-shell ${collapsed ? "is-collapsed" : ""}`, children: [
|
|
1587
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("aside", { className: "orion-admin-sidebar", children: [
|
|
1588
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1589
|
-
"button",
|
|
1590
|
-
{
|
|
1591
|
-
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
1592
|
-
className: "orion-admin-sidebar-toggle",
|
|
1593
|
-
onClick: toggleSidebar,
|
|
1594
|
-
type: "button",
|
|
1595
|
-
children: collapsed ? ">" : "<"
|
|
1596
|
-
}
|
|
1597
|
-
),
|
|
1598
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "orion-admin-brand-wrap", children: [
|
|
1599
|
-
logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-brand-logo", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("img", { alt: `${brandName} logo`, src: logoUrl }) }) : null,
|
|
1600
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "orion-admin-brand-text", children: [
|
|
1601
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-brand-name", title: brandName, children: collapsed ? brandName.slice(0, 1).toUpperCase() : brandName }),
|
|
1602
|
-
!collapsed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-brand-subtitle", children: "Studio" }) : null
|
|
1603
|
-
] })
|
|
1604
|
-
] }),
|
|
1605
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("nav", { className: "orion-admin-nav", children: navItems.filter((item) => roleCanAccessNav(userRole, item)).map((item) => {
|
|
1606
|
-
const active = navItemIsActive(pathname, item);
|
|
1607
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1608
|
-
"a",
|
|
1609
|
-
{
|
|
1610
|
-
className: `orion-admin-nav-link ${active ? "is-active" : ""}`,
|
|
1611
|
-
href: item.href,
|
|
1612
|
-
title: item.label,
|
|
1613
|
-
children: item.icon ? collapsed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavIcon, { name: item.icon }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: { alignItems: "center", display: "flex", gap: "0.6rem" }, children: [
|
|
1614
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavIcon, { name: item.icon }),
|
|
1615
|
-
item.label
|
|
1616
|
-
] }) : collapsed ? item.label.slice(0, 1) : item.label
|
|
1617
|
-
},
|
|
1618
|
-
item.href
|
|
1619
|
-
);
|
|
1620
|
-
}) }),
|
|
1621
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "orion-admin-sidebar-footer", children: [
|
|
1622
|
-
!collapsed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1623
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-user-label", children: "Signed in as" }),
|
|
1624
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "orion-admin-user-email", children: userEmail })
|
|
1625
|
-
] }) : null,
|
|
1626
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { className: "orion-admin-logout", disabled: loggingOut, onClick: handleLogout, type: "button", children: loggingOut ? "..." : "Log out" })
|
|
1627
|
-
] })
|
|
1628
|
-
] }),
|
|
1629
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("main", { className: "orion-admin-main", children })
|
|
1630
|
-
] });
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
// src/admin/hooks/useSiteBranding.ts
|
|
1634
|
-
var import_react3 = require("react");
|
|
1635
|
-
var asRecord = (value) => {
|
|
1636
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
1637
|
-
return value;
|
|
1638
|
-
};
|
|
1639
|
-
var pickString = (value) => {
|
|
1640
|
-
if (typeof value !== "string") return null;
|
|
1641
|
-
const next = value.trim();
|
|
1642
|
-
return next.length > 0 ? next : null;
|
|
1643
|
-
};
|
|
1644
|
-
var resolveUploadUrl = (value) => {
|
|
1645
|
-
const direct = pickString(value);
|
|
1646
|
-
if (direct) return direct;
|
|
1647
|
-
const record = asRecord(value);
|
|
1648
|
-
if (!record) return null;
|
|
1649
|
-
const fromUrl = pickString(record.url);
|
|
1650
|
-
if (fromUrl) return fromUrl;
|
|
1651
|
-
const fromFilename = pickString(record.filename);
|
|
1652
|
-
if (fromFilename) return `/api/media/file/${fromFilename}`;
|
|
1653
|
-
return null;
|
|
1654
|
-
};
|
|
1655
|
-
var resolveLogoUrl = (settings) => {
|
|
1656
|
-
return resolveUploadUrl(settings.logo) || resolveUploadUrl(settings.adminLogo) || resolveUploadUrl(settings.brandLogo) || null;
|
|
1657
|
-
};
|
|
1658
|
-
var cachedBranding = null;
|
|
1659
|
-
function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
1660
|
-
const [branding, setBranding] = (0, import_react3.useState)(() => {
|
|
1661
|
-
if (cachedBranding) {
|
|
1662
|
-
return {
|
|
1663
|
-
logoUrl: cachedBranding.logoUrl || defaultLogoUrl || null,
|
|
1664
|
-
siteName: cachedBranding.siteName || defaultName || null
|
|
1665
|
-
};
|
|
1666
|
-
}
|
|
1667
|
-
return {
|
|
1668
|
-
logoUrl: defaultLogoUrl || null,
|
|
1669
|
-
siteName: defaultName || null
|
|
1670
|
-
};
|
|
1671
|
-
});
|
|
1672
|
-
(0, import_react3.useEffect)(() => {
|
|
1673
|
-
let cancelled = false;
|
|
1674
|
-
const run = async () => {
|
|
1675
|
-
try {
|
|
1676
|
-
const res = await fetch("/api/globals/site-settings?depth=1&draft=true", {
|
|
1677
|
-
credentials: "include"
|
|
1678
|
-
});
|
|
1679
|
-
if (!res.ok) return;
|
|
1680
|
-
const data = await res.json();
|
|
1681
|
-
const record = asRecord(data);
|
|
1682
|
-
if (!record) return;
|
|
1683
|
-
const siteName = pickString(record.siteName);
|
|
1684
|
-
const logoUrl = resolveLogoUrl(record);
|
|
1685
|
-
cachedBranding = { logoUrl, siteName };
|
|
1686
|
-
if (!cancelled) {
|
|
1687
|
-
setBranding({
|
|
1688
|
-
logoUrl: logoUrl || defaultLogoUrl || null,
|
|
1689
|
-
siteName: siteName || defaultName || null
|
|
1690
|
-
});
|
|
1691
|
-
}
|
|
1692
|
-
} catch {
|
|
1693
|
-
}
|
|
1694
|
-
};
|
|
1695
|
-
void run();
|
|
1696
|
-
return () => {
|
|
1697
|
-
cancelled = true;
|
|
1698
|
-
};
|
|
1699
|
-
}, [defaultLogoUrl, defaultName]);
|
|
1700
|
-
return branding;
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
// src/admin/components/studio/adminPathUtils.ts
|
|
1704
|
-
var import_react4 = require("react");
|
|
1705
|
-
var DEFAULT_ADMIN_BASE_PATH = "/admin";
|
|
1706
|
-
var normalizePath = (value) => {
|
|
1707
|
-
if (!value || value === "/") return "/";
|
|
1708
|
-
const withLeadingSlash = value.startsWith("/") ? value : `/${value}`;
|
|
1709
|
-
const trimmed = withLeadingSlash.replace(/\/+$/, "");
|
|
1710
|
-
return trimmed.length > 0 ? trimmed : "/";
|
|
1711
|
-
};
|
|
1712
|
-
var normalizeAdminBasePath = (value) => {
|
|
1713
|
-
const normalized = normalizePath(value);
|
|
1714
|
-
return normalized === "/" ? DEFAULT_ADMIN_BASE_PATH : normalized;
|
|
1715
|
-
};
|
|
1716
|
-
var detectAdminBasePath = (pathname, fallback = DEFAULT_ADMIN_BASE_PATH) => {
|
|
1717
|
-
const normalizedPathname = normalizePath(pathname);
|
|
1718
|
-
const normalizedFallback = normalizeAdminBasePath(fallback);
|
|
1719
|
-
const markers = [
|
|
1720
|
-
"/contact-form",
|
|
1721
|
-
"/collections/",
|
|
1722
|
-
"/globals/",
|
|
1723
|
-
"/forms",
|
|
1724
|
-
"/pages/",
|
|
1725
|
-
"/tools",
|
|
1726
|
-
"/media",
|
|
1727
|
-
"/logout",
|
|
1728
|
-
"/login"
|
|
1729
|
-
];
|
|
1730
|
-
for (const marker of markers) {
|
|
1731
|
-
const index = normalizedPathname.indexOf(marker);
|
|
1732
|
-
if (index > 0) {
|
|
1733
|
-
return normalizeAdminBasePath(normalizedPathname.slice(0, index));
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
if (normalizedPathname === normalizedFallback || normalizedPathname.startsWith(`${normalizedFallback}/`)) {
|
|
1737
|
-
return normalizedFallback;
|
|
1738
|
-
}
|
|
1739
|
-
const segments = normalizedPathname.split("/").filter(Boolean);
|
|
1740
|
-
if (segments.length > 0) {
|
|
1741
|
-
return normalizeAdminBasePath(`/${segments[0]}`);
|
|
1742
|
-
}
|
|
1743
|
-
return normalizedFallback;
|
|
1744
|
-
};
|
|
1745
|
-
var isAbsoluteExternalURL2 = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value) || value.startsWith("//");
|
|
1746
|
-
var resolveAdminPath = (adminBasePath, targetPath) => {
|
|
1747
|
-
if (!targetPath) return adminBasePath;
|
|
1748
|
-
if (isAbsoluteExternalURL2(targetPath)) return targetPath;
|
|
1749
|
-
const normalizedBasePath = normalizeAdminBasePath(adminBasePath);
|
|
1750
|
-
const normalizedTargetPath = normalizePath(targetPath);
|
|
1751
|
-
if (normalizedTargetPath === "/admin") {
|
|
1752
|
-
return normalizedBasePath;
|
|
1753
|
-
}
|
|
1754
|
-
if (normalizedTargetPath.startsWith("/admin/")) {
|
|
1755
|
-
return `${normalizedBasePath}${normalizedTargetPath.slice("/admin".length)}`;
|
|
1756
|
-
}
|
|
1757
|
-
if (normalizedTargetPath === normalizedBasePath || normalizedTargetPath.startsWith(`${normalizedBasePath}/`)) {
|
|
1758
|
-
return normalizedTargetPath;
|
|
1759
|
-
}
|
|
1760
|
-
if (normalizedTargetPath === "/") {
|
|
1761
|
-
return normalizedBasePath;
|
|
1762
|
-
}
|
|
1763
|
-
return `${normalizedBasePath}${normalizedTargetPath}`;
|
|
1764
|
-
};
|
|
1765
|
-
var useAdminBasePath = (fallback = DEFAULT_ADMIN_BASE_PATH) => {
|
|
1766
|
-
const [adminBasePath, setAdminBasePath] = (0, import_react4.useState)(normalizeAdminBasePath(fallback));
|
|
1767
|
-
(0, import_react4.useEffect)(() => {
|
|
1768
|
-
const update = () => {
|
|
1769
|
-
setAdminBasePath(detectAdminBasePath(window.location.pathname, fallback));
|
|
1770
|
-
};
|
|
1771
|
-
update();
|
|
1772
|
-
window.addEventListener("popstate", update);
|
|
1773
|
-
return () => window.removeEventListener("popstate", update);
|
|
1774
|
-
}, [fallback]);
|
|
1775
|
-
return adminBasePath;
|
|
1776
|
-
};
|
|
1777
|
-
|
|
1778
|
-
// src/admin/components/studio/studioNavModel.ts
|
|
1779
|
-
var getPropString = (props, key, fallback) => {
|
|
1780
|
-
if (!props || typeof props !== "object") return fallback;
|
|
1781
|
-
const direct = props[key];
|
|
1782
|
-
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
1783
|
-
const clientProps = props.clientProps;
|
|
1784
|
-
if (clientProps && typeof clientProps === "object") {
|
|
1785
|
-
const nested = clientProps[key];
|
|
1786
|
-
if (typeof nested === "string" && nested.length > 0) return nested;
|
|
1787
|
-
}
|
|
1788
|
-
return fallback;
|
|
1789
|
-
};
|
|
1790
|
-
var getPropBoolean = (props, key, fallback) => {
|
|
1791
|
-
if (!props || typeof props !== "object") return fallback;
|
|
1792
|
-
const direct = props[key];
|
|
1793
|
-
if (typeof direct === "boolean") return direct;
|
|
1794
|
-
const clientProps = props.clientProps;
|
|
1795
|
-
if (clientProps && typeof clientProps === "object") {
|
|
1796
|
-
const nested = clientProps[key];
|
|
1797
|
-
if (typeof nested === "boolean") return nested;
|
|
1798
|
-
}
|
|
1799
|
-
return fallback;
|
|
1800
|
-
};
|
|
1801
|
-
var getPropStringArray = (props, key, fallback) => {
|
|
1802
|
-
if (!props || typeof props !== "object") return fallback;
|
|
1803
|
-
const read = (candidate) => Array.isArray(candidate) ? candidate.filter((value) => typeof value === "string" && value.length > 0) : null;
|
|
1804
|
-
const direct = read(props[key]);
|
|
1805
|
-
if (direct) return direct;
|
|
1806
|
-
const clientProps = props.clientProps;
|
|
1807
|
-
if (clientProps && typeof clientProps === "object") {
|
|
1808
|
-
const nested = read(clientProps[key]);
|
|
1809
|
-
if (nested) return nested;
|
|
1810
|
-
}
|
|
1811
|
-
return fallback;
|
|
1812
|
-
};
|
|
1813
|
-
var getPropSections = (props) => {
|
|
1814
|
-
if (!props || typeof props !== "object") return [];
|
|
1815
|
-
const direct = resolveStudioSections(props.sections);
|
|
1816
|
-
if (direct.length > 0) return direct;
|
|
1817
|
-
const clientProps = props.clientProps;
|
|
1818
|
-
if (clientProps && typeof clientProps === "object") {
|
|
1819
|
-
return resolveStudioSections(clientProps.sections);
|
|
1820
|
-
}
|
|
1821
|
-
return [];
|
|
1822
|
-
};
|
|
1823
|
-
var readUserRole = (user) => {
|
|
1824
|
-
if (!user || typeof user !== "object") {
|
|
1825
|
-
return void 0;
|
|
1826
|
-
}
|
|
1827
|
-
const role = user.role;
|
|
1828
|
-
return typeof role === "string" ? role : void 0;
|
|
1829
|
-
};
|
|
1830
|
-
var buildStudioNavItems = (props, adminBasePath) => {
|
|
1831
|
-
const formsEnabled = getPropBoolean(props, "formsEnabled", false);
|
|
1832
|
-
const formsCollectionSlug = getPropString(props, "formsCollectionSlug", "forms");
|
|
1833
|
-
const formSubmissionsCollectionSlug = getPropString(
|
|
1834
|
-
props,
|
|
1835
|
-
"formSubmissionsCollectionSlug",
|
|
1836
|
-
"form-submissions"
|
|
1837
|
-
);
|
|
1838
|
-
const formUploadsCollectionSlug = getPropString(props, "formUploadsCollectionSlug", "form-uploads");
|
|
1839
|
-
const mediaCollectionSlug = getPropString(props, "mediaCollectionSlug", "media");
|
|
1840
|
-
const globalsBasePath = getPropString(props, "globalsBasePath", "/globals");
|
|
1841
|
-
const globalsExtraMatchPrefixes = getPropStringArray(props, "globalsExtraMatchPrefixes", []);
|
|
1842
|
-
const sections = getPropSections(props);
|
|
1843
|
-
const pagesPath = resolveAdminPath(adminBasePath, "/pages");
|
|
1844
|
-
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
1845
|
-
const mediaPath = resolveAdminPath(adminBasePath, "/media");
|
|
1846
|
-
const toolsPath = resolveAdminPath(adminBasePath, "/tools");
|
|
1847
|
-
const resolvedGlobalsBasePath = resolveAdminPath(adminBasePath, globalsBasePath);
|
|
1848
|
-
const resolvedGlobalsExtraMatchPrefixes = globalsExtraMatchPrefixes.map(
|
|
1849
|
-
(prefix) => resolveAdminPath(adminBasePath, prefix)
|
|
1850
|
-
);
|
|
1851
|
-
const baseItemsBeforeTools = [
|
|
1852
|
-
{
|
|
1853
|
-
href: adminBasePath,
|
|
1854
|
-
icon: "dashboard",
|
|
1855
|
-
label: "Dashboard",
|
|
1856
|
-
matchPrefixes: [adminBasePath]
|
|
1857
|
-
},
|
|
1858
|
-
{
|
|
1859
|
-
href: pagesPath,
|
|
1860
|
-
icon: "pages",
|
|
1861
|
-
label: "Pages",
|
|
1862
|
-
matchPrefixes: [pagesPath]
|
|
1863
|
-
},
|
|
1864
|
-
...formsEnabled ? [
|
|
1865
|
-
{
|
|
1866
|
-
href: formsPath,
|
|
1867
|
-
icon: "forms",
|
|
1868
|
-
label: "Forms",
|
|
1869
|
-
matchPrefixes: [
|
|
1870
|
-
formsPath,
|
|
1871
|
-
resolveAdminPath(adminBasePath, `/collections/${formsCollectionSlug}`),
|
|
1872
|
-
resolveAdminPath(adminBasePath, `/collections/${formSubmissionsCollectionSlug}`),
|
|
1873
|
-
resolveAdminPath(adminBasePath, `/collections/${formUploadsCollectionSlug}`)
|
|
1874
|
-
]
|
|
1875
|
-
}
|
|
1876
|
-
] : [],
|
|
1877
|
-
{
|
|
1878
|
-
href: resolvedGlobalsBasePath,
|
|
1879
|
-
icon: "globals",
|
|
1880
|
-
label: "Globals",
|
|
1881
|
-
matchPrefixes: [
|
|
1882
|
-
resolvedGlobalsBasePath,
|
|
1883
|
-
resolveAdminPath(adminBasePath, "/globals"),
|
|
1884
|
-
...resolvedGlobalsExtraMatchPrefixes
|
|
1885
|
-
]
|
|
1886
|
-
},
|
|
1887
|
-
{
|
|
1888
|
-
href: mediaPath,
|
|
1889
|
-
icon: "media",
|
|
1890
|
-
label: "Media",
|
|
1891
|
-
matchPrefixes: [mediaPath, resolveAdminPath(adminBasePath, `/collections/${mediaCollectionSlug}`)]
|
|
1892
|
-
}
|
|
1893
|
-
];
|
|
1894
|
-
const adminToolsItem = {
|
|
1895
|
-
href: toolsPath,
|
|
1896
|
-
icon: "tools",
|
|
1897
|
-
label: "Admin Tools",
|
|
1898
|
-
matchPrefixes: [toolsPath, resolveAdminPath(adminBasePath, "/collections/users")],
|
|
1899
|
-
roles: ["admin"]
|
|
1900
|
-
};
|
|
1901
|
-
const extensionItems = sections.map((section) => ({
|
|
1902
|
-
href: resolveAdminPath(adminBasePath, section.href),
|
|
1903
|
-
...section.icon ? { icon: section.icon } : {},
|
|
1904
|
-
label: section.label,
|
|
1905
|
-
matchPrefixes: section.matchPrefixes.map((prefix) => resolveAdminPath(adminBasePath, prefix)),
|
|
1906
|
-
roles: section.roles
|
|
1907
|
-
}));
|
|
1908
|
-
return [...baseItemsBeforeTools, ...extensionItems, adminToolsItem];
|
|
1909
|
-
};
|
|
1910
|
-
|
|
1911
|
-
// src/admin/components/studio/StudioSectionLayout.tsx
|
|
1912
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1913
|
-
function StudioSectionLayout({ children, navProps }) {
|
|
1914
|
-
const { user } = (0, import_ui.useAuth)();
|
|
1915
|
-
const pathname = (0, import_navigation.usePathname)() || "";
|
|
1916
|
-
const router = (0, import_navigation.useRouter)();
|
|
1917
|
-
const adminBasePath = useAdminBasePath();
|
|
1918
|
-
const defaultBrandName = getPropString(navProps, "brandName", "Orion Studio");
|
|
1919
|
-
const defaultLogoUrl = getPropString(navProps, "logoUrl", "");
|
|
1920
|
-
const navItems = (0, import_react5.useMemo)(
|
|
1921
|
-
() => buildStudioNavItems(navProps, adminBasePath),
|
|
1922
|
-
[adminBasePath, navProps]
|
|
1923
|
-
);
|
|
1924
|
-
const branding = useSiteBranding(defaultBrandName, defaultLogoUrl || void 0);
|
|
1925
|
-
(0, import_react5.useLayoutEffect)(() => {
|
|
1926
|
-
document.body.classList.add("orion-studio-shell-active");
|
|
1927
|
-
return () => {
|
|
1928
|
-
document.body.classList.remove("orion-studio-shell-active");
|
|
1929
|
-
};
|
|
1930
|
-
}, []);
|
|
1931
|
-
const logout = (0, import_react5.useMemo)(
|
|
1932
|
-
() => async () => {
|
|
1933
|
-
await fetch("/api/users/logout", {
|
|
1934
|
-
credentials: "include",
|
|
1935
|
-
method: "POST"
|
|
1936
|
-
});
|
|
1937
|
-
router.push(resolveAdminPath(adminBasePath, "/login"));
|
|
1938
|
-
router.refresh();
|
|
1939
|
-
},
|
|
1940
|
-
[adminBasePath, router]
|
|
1941
|
-
);
|
|
1942
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1943
|
-
AdminShellClient,
|
|
1944
|
-
{
|
|
1945
|
-
brandName: branding.siteName || defaultBrandName,
|
|
1946
|
-
logoUrl: branding.logoUrl || defaultLogoUrl || void 0,
|
|
1947
|
-
navItems,
|
|
1948
|
-
onLogout: logout,
|
|
1949
|
-
pathname,
|
|
1950
|
-
storageKey: "orion-admin-sidebar-collapsed-v1",
|
|
1951
|
-
userEmail: typeof user?.email === "string" ? user.email : "user",
|
|
1952
|
-
userRole: readUserRole(user),
|
|
1953
|
-
children
|
|
1954
|
-
}
|
|
1955
|
-
);
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
|
-
// src/admin/components/studio/AdminStudioDashboard.tsx
|
|
1959
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1960
|
-
var DEFAULT_ADMIN_BASE_PATH2 = "/admin";
|
|
1961
|
-
var normalizePath2 = (value) => {
|
|
1962
|
-
if (!value || value === "/") return "/";
|
|
1963
|
-
const withLeadingSlash = value.startsWith("/") ? value : `/${value}`;
|
|
1964
|
-
const trimmed = withLeadingSlash.replace(/\/+$/, "");
|
|
1965
|
-
return trimmed.length > 0 ? trimmed : "/";
|
|
1966
|
-
};
|
|
1967
|
-
var normalizeAdminBasePath2 = (value) => {
|
|
1968
|
-
const normalized = normalizePath2(value);
|
|
1969
|
-
return normalized === "/" ? DEFAULT_ADMIN_BASE_PATH2 : normalized;
|
|
1970
|
-
};
|
|
1971
|
-
var isAbsoluteExternalURL3 = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value) || value.startsWith("//");
|
|
1972
|
-
var resolveAdminPath2 = (adminBasePath, targetPath) => {
|
|
1973
|
-
if (!targetPath) return adminBasePath;
|
|
1974
|
-
if (isAbsoluteExternalURL3(targetPath)) return targetPath;
|
|
1975
|
-
const normalizedBasePath = normalizeAdminBasePath2(adminBasePath);
|
|
1976
|
-
const normalizedTargetPath = normalizePath2(targetPath);
|
|
1977
|
-
if (normalizedTargetPath === "/admin") {
|
|
1978
|
-
return normalizedBasePath;
|
|
1979
|
-
}
|
|
1980
|
-
if (normalizedTargetPath.startsWith("/admin/")) {
|
|
1981
|
-
return `${normalizedBasePath}${normalizedTargetPath.slice("/admin".length)}`;
|
|
1982
|
-
}
|
|
1983
|
-
if (normalizedTargetPath === normalizedBasePath || normalizedTargetPath.startsWith(`${normalizedBasePath}/`)) {
|
|
1984
|
-
return normalizedTargetPath;
|
|
1985
|
-
}
|
|
1986
|
-
if (normalizedTargetPath === "/") {
|
|
1987
|
-
return normalizedBasePath;
|
|
1988
|
-
}
|
|
1989
|
-
return `${normalizedBasePath}${normalizedTargetPath}`;
|
|
1990
|
-
};
|
|
1991
|
-
var getPropString2 = (props, key, fallback) => {
|
|
1992
|
-
if (!props || typeof props !== "object") return fallback;
|
|
1993
|
-
const direct = props[key];
|
|
1994
|
-
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
1995
|
-
const clientProps = props.clientProps;
|
|
1996
|
-
if (clientProps && typeof clientProps === "object") {
|
|
1997
|
-
const nested = clientProps[key];
|
|
1998
|
-
if (typeof nested === "string" && nested.length > 0) return nested;
|
|
1999
|
-
}
|
|
2000
|
-
return fallback;
|
|
2001
|
-
};
|
|
2002
|
-
var getPropBoolean2 = (props, key, fallback) => {
|
|
2003
|
-
if (!props || typeof props !== "object") return fallback;
|
|
2004
|
-
const direct = props[key];
|
|
2005
|
-
if (typeof direct === "boolean") return direct;
|
|
2006
|
-
const clientProps = props.clientProps;
|
|
2007
|
-
if (clientProps && typeof clientProps === "object") {
|
|
2008
|
-
const nested = clientProps[key];
|
|
2009
|
-
if (typeof nested === "boolean") return nested;
|
|
2010
|
-
}
|
|
2011
|
-
return fallback;
|
|
2012
|
-
};
|
|
2013
|
-
var getPropSections2 = (props) => {
|
|
2014
|
-
if (!props || typeof props !== "object") return [];
|
|
2015
|
-
const direct = resolveStudioSections(props.sections);
|
|
2016
|
-
if (direct.length > 0) return direct;
|
|
2017
|
-
const clientProps = props.clientProps;
|
|
2018
|
-
if (clientProps && typeof clientProps === "object") {
|
|
2019
|
-
return resolveStudioSections(clientProps.sections);
|
|
2020
|
-
}
|
|
2021
|
-
return [];
|
|
2022
|
-
};
|
|
2023
|
-
var getPropDashboardPanels = (props) => {
|
|
2024
|
-
if (!props || typeof props !== "object") return [];
|
|
2025
|
-
const direct = resolveStudioSectionDashboards(props.dashboardPanels);
|
|
2026
|
-
if (direct.length > 0) return direct;
|
|
2027
|
-
const clientProps = props.clientProps;
|
|
2028
|
-
if (clientProps && typeof clientProps === "object") {
|
|
2029
|
-
return resolveStudioSectionDashboards(clientProps.dashboardPanels);
|
|
2030
|
-
}
|
|
2031
|
-
return [];
|
|
2032
|
-
};
|
|
2033
|
-
var readImportMap = (props) => {
|
|
2034
|
-
if (!props || typeof props !== "object") return void 0;
|
|
2035
|
-
const direct = props.importMap;
|
|
2036
|
-
if (direct && typeof direct === "object") {
|
|
2037
|
-
return direct;
|
|
2038
|
-
}
|
|
2039
|
-
const payloadLike = props.payload;
|
|
2040
|
-
if (payloadLike && typeof payloadLike === "object") {
|
|
2041
|
-
const nested = payloadLike.importMap;
|
|
2042
|
-
if (nested && typeof nested === "object") {
|
|
2043
|
-
return nested;
|
|
2044
|
-
}
|
|
2045
|
-
}
|
|
2046
|
-
const initPageResult = props.initPageResult;
|
|
2047
|
-
if (initPageResult && typeof initPageResult === "object") {
|
|
2048
|
-
const req = initPageResult.req;
|
|
2049
|
-
if (req && typeof req === "object") {
|
|
2050
|
-
const payload = req.payload;
|
|
2051
|
-
if (payload && typeof payload === "object") {
|
|
2052
|
-
const nested = payload.importMap;
|
|
2053
|
-
if (nested && typeof nested === "object") {
|
|
2054
|
-
return nested;
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
return void 0;
|
|
2060
|
-
};
|
|
2061
|
-
var readUserRole2 = (props) => {
|
|
2062
|
-
if (!props || typeof props !== "object") return void 0;
|
|
2063
|
-
const user = props.user;
|
|
2064
|
-
if (user && typeof user === "object") {
|
|
2065
|
-
const role = user.role;
|
|
2066
|
-
if (typeof role === "string") {
|
|
2067
|
-
return role;
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
const initPageResult = props.initPageResult;
|
|
2071
|
-
if (initPageResult && typeof initPageResult === "object") {
|
|
2072
|
-
const req = initPageResult.req;
|
|
2073
|
-
if (req && typeof req === "object") {
|
|
2074
|
-
const nestedUser = req.user;
|
|
2075
|
-
if (nestedUser && typeof nestedUser === "object") {
|
|
2076
|
-
const role = nestedUser.role;
|
|
2077
|
-
if (typeof role === "string") {
|
|
2078
|
-
return role;
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
return void 0;
|
|
2084
|
-
};
|
|
2085
|
-
var readAdminBasePath = (props) => {
|
|
2086
|
-
if (!props || typeof props !== "object") {
|
|
2087
|
-
return DEFAULT_ADMIN_BASE_PATH2;
|
|
2088
|
-
}
|
|
2089
|
-
const payloadLike = props.payload;
|
|
2090
|
-
if (payloadLike && typeof payloadLike === "object") {
|
|
2091
|
-
const config = payloadLike.config;
|
|
2092
|
-
const routes = config && typeof config === "object" ? config.routes : null;
|
|
2093
|
-
const admin = routes && typeof routes === "object" ? routes.admin : null;
|
|
2094
|
-
if (typeof admin === "string" && admin.length > 0) {
|
|
2095
|
-
return normalizeAdminBasePath2(admin);
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
const initPageResult = props.initPageResult;
|
|
2099
|
-
if (initPageResult && typeof initPageResult === "object") {
|
|
2100
|
-
const req = initPageResult.req;
|
|
2101
|
-
if (req && typeof req === "object") {
|
|
2102
|
-
const nestedPayload = req.payload;
|
|
2103
|
-
if (nestedPayload && typeof nestedPayload === "object") {
|
|
2104
|
-
const config = nestedPayload.config;
|
|
2105
|
-
const routes = config && typeof config === "object" ? config.routes : null;
|
|
2106
|
-
const admin = routes && typeof routes === "object" ? routes.admin : null;
|
|
2107
|
-
if (typeof admin === "string" && admin.length > 0) {
|
|
2108
|
-
return normalizeAdminBasePath2(admin);
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
return DEFAULT_ADMIN_BASE_PATH2;
|
|
2114
|
-
};
|
|
2115
|
-
var canAccess2 = (role, roles) => {
|
|
2116
|
-
if (!roles || roles.length === 0) {
|
|
2117
|
-
return true;
|
|
2118
|
-
}
|
|
2119
|
-
if (!role) {
|
|
2120
|
-
return false;
|
|
2121
|
-
}
|
|
2122
|
-
return roles.includes(role);
|
|
2123
|
-
};
|
|
2124
|
-
var buildSectionLinks = (adminBasePath, sections, formsEnabled, globalsBasePath) => {
|
|
2125
|
-
const links = [
|
|
2126
|
-
{
|
|
2127
|
-
href: resolveAdminPath2(adminBasePath, "/pages"),
|
|
2128
|
-
id: "pages",
|
|
2129
|
-
label: "Pages"
|
|
2130
|
-
},
|
|
2131
|
-
...formsEnabled ? [
|
|
2132
|
-
{
|
|
2133
|
-
href: resolveAdminPath2(adminBasePath, "/forms"),
|
|
2134
|
-
id: "forms",
|
|
2135
|
-
label: "Forms",
|
|
2136
|
-
roles: ["admin", "editor"]
|
|
2137
|
-
}
|
|
2138
|
-
] : [],
|
|
2139
|
-
{
|
|
2140
|
-
href: resolveAdminPath2(adminBasePath, globalsBasePath),
|
|
2141
|
-
id: "globals",
|
|
2142
|
-
label: "Globals"
|
|
2143
|
-
},
|
|
2144
|
-
{
|
|
2145
|
-
href: resolveAdminPath2(adminBasePath, "/media"),
|
|
2146
|
-
id: "media",
|
|
2147
|
-
label: "Media"
|
|
2148
|
-
},
|
|
2149
|
-
...sections.map((section) => ({
|
|
2150
|
-
href: resolveAdminPath2(adminBasePath, section.href),
|
|
2151
|
-
id: section.id,
|
|
2152
|
-
label: section.label,
|
|
2153
|
-
...section.roles ? { roles: section.roles } : {}
|
|
2154
|
-
})),
|
|
2155
|
-
{
|
|
2156
|
-
href: resolveAdminPath2(adminBasePath, "/tools"),
|
|
2157
|
-
id: "admin-tools",
|
|
2158
|
-
label: "Admin Tools",
|
|
2159
|
-
roles: ["admin"]
|
|
2160
|
-
}
|
|
2161
|
-
];
|
|
2162
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2163
|
-
return links.filter((link) => {
|
|
2164
|
-
if (seen.has(link.id)) {
|
|
2165
|
-
return false;
|
|
2166
|
-
}
|
|
2167
|
-
seen.add(link.id);
|
|
2168
|
-
return true;
|
|
2169
|
-
});
|
|
2170
|
-
};
|
|
2171
|
-
function DashboardPanelFallback({ label }) {
|
|
2172
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "orion-dashboard-extension-fallback", children: [
|
|
2173
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "orion-dashboard-panel-kicker", children: "Extension Unavailable" }),
|
|
2174
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: label }),
|
|
2175
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "This dashboard panel could not be rendered, but the rest of the dashboard is still available." })
|
|
2176
|
-
] });
|
|
2177
|
-
}
|
|
2178
|
-
function buildExtensionPanels(adminBasePath, importMap, panels, userRole) {
|
|
2179
|
-
const visiblePanels = panels.filter((panel) => canAccess2(userRole, panel.roles));
|
|
2180
|
-
return visiblePanels.map((panel) => {
|
|
2181
|
-
const href = resolveAdminPath2(adminBasePath, panel.href);
|
|
2182
|
-
return {
|
|
2183
|
-
id: panel.id,
|
|
2184
|
-
node: importMap ? (0, import_RenderServerComponent.RenderServerComponent)({
|
|
2185
|
-
Component: panel.Component,
|
|
2186
|
-
Fallback: () => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DashboardPanelFallback, { label: panel.label }),
|
|
2187
|
-
importMap,
|
|
2188
|
-
serverProps: {
|
|
2189
|
-
adminBasePath,
|
|
2190
|
-
href,
|
|
2191
|
-
label: panel.label
|
|
2192
|
-
}
|
|
2193
|
-
}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DashboardPanelFallback, { label: panel.label }),
|
|
2194
|
-
span: panel.span
|
|
2195
|
-
};
|
|
2196
|
-
});
|
|
2197
|
-
}
|
|
2198
|
-
function AdminStudioDashboard(rawProps) {
|
|
2199
|
-
const props = rawProps || {};
|
|
2200
|
-
const formsEnabled = getPropBoolean2(props, "formsEnabled", false);
|
|
2201
|
-
const globalsBasePath = getPropString2(props, "globalsBasePath", "/globals");
|
|
2202
|
-
const sections = getPropSections2(props);
|
|
2203
|
-
const dashboardPanels = getPropDashboardPanels(props);
|
|
2204
|
-
const pagesCollectionSlug = getPropString2(props, "pagesCollectionSlug", "pages");
|
|
2205
|
-
const formsCollectionSlug = getPropString2(props, "formsCollectionSlug", "forms");
|
|
2206
|
-
const formSubmissionsCollectionSlug = getPropString2(
|
|
2207
|
-
props,
|
|
2208
|
-
"formSubmissionsCollectionSlug",
|
|
2209
|
-
"form-submissions"
|
|
2210
|
-
);
|
|
2211
|
-
const mediaCollectionSlug = getPropString2(props, "mediaCollectionSlug", "media");
|
|
2212
|
-
const adminBasePath = readAdminBasePath(props);
|
|
2213
|
-
const importMap = readImportMap(props);
|
|
2214
|
-
const userRole = readUserRole2(props);
|
|
2215
|
-
const navProps = {
|
|
2216
|
-
brandName: getPropString2(props, "brandName", "Orion Studio"),
|
|
2217
|
-
dashboardPanels,
|
|
2218
|
-
formSubmissionsCollectionSlug,
|
|
2219
|
-
formsCollectionSlug,
|
|
2220
|
-
formsEnabled,
|
|
2221
|
-
globalsBasePath,
|
|
2222
|
-
logoUrl: getPropString2(props, "logoUrl", ""),
|
|
2223
|
-
mediaCollectionSlug,
|
|
2224
|
-
pagesCollectionSlug,
|
|
2225
|
-
sections
|
|
2226
|
-
};
|
|
2227
|
-
const extensionPanels = buildExtensionPanels(adminBasePath, importMap, dashboardPanels, userRole);
|
|
2228
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StudioSectionLayout, { navProps, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2229
|
-
AdminPage,
|
|
2230
|
-
{
|
|
2231
|
-
breadcrumbs: [{ label: "Dashboard" }],
|
|
2232
|
-
description: "What needs attention, what changed recently, and how the site is performing.",
|
|
2233
|
-
title: "Studio",
|
|
2234
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2235
|
-
AdminStudioDashboardClient,
|
|
2236
|
-
{
|
|
2237
|
-
extensionPanels,
|
|
2238
|
-
formSubmissionsCollectionSlug,
|
|
2239
|
-
formsCollectionSlug,
|
|
2240
|
-
formsEnabled,
|
|
2241
|
-
formsPath: resolveAdminPath2(adminBasePath, "/forms"),
|
|
2242
|
-
globalsBasePath: resolveAdminPath2(adminBasePath, globalsBasePath),
|
|
2243
|
-
mediaCollectionSlug,
|
|
2244
|
-
mediaPath: resolveAdminPath2(adminBasePath, "/media"),
|
|
2245
|
-
pagesCollectionSlug,
|
|
2246
|
-
pagesPath: resolveAdminPath2(adminBasePath, "/pages"),
|
|
2247
|
-
sectionLinks: buildSectionLinks(adminBasePath, sections, formsEnabled, globalsBasePath),
|
|
2248
|
-
toolsPath: resolveAdminPath2(adminBasePath, "/tools"),
|
|
2249
|
-
userRole
|
|
2250
|
-
}
|
|
2251
|
-
)
|
|
2252
|
-
}
|
|
2253
|
-
) });
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
876
|
// src/admin/helpers/withTooltips.ts
|
|
2257
877
|
var defaultTooltips = {
|
|
2258
878
|
title: "The main title displayed on this page.",
|
|
@@ -2509,7 +1129,6 @@ var createSocialMediaGlobal = (options = {}) => ({
|
|
|
2509
1129
|
});
|
|
2510
1130
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2511
1131
|
0 && (module.exports = {
|
|
2512
|
-
AdminStudioDashboard,
|
|
2513
1132
|
SOCIAL_MEDIA_DEFAULT_ICON_BY_PLATFORM,
|
|
2514
1133
|
SOCIAL_MEDIA_ICON_OPTIONS,
|
|
2515
1134
|
SOCIAL_MEDIA_PLATFORMS,
|