headroom-cms 0.2.0 → 0.2.1
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/admin/assets/{AdminsPage-DUMTsCEp.js → AdminsPage-lGd1MFW3.js} +1 -1
- package/admin/assets/AllContentPage-YykTt4xH.js +1 -0
- package/admin/assets/{ApiKeysPage-CzUOSoz_.js → ApiKeysPage-BCpNEKxF.js} +1 -1
- package/admin/assets/{AuditPage-CYAg4dbI.js → AuditPage-DBKiujoI.js} +1 -1
- package/admin/assets/{BackupsPage-04_oMy3v.js → BackupsPage-DCrmYnQc.js} +1 -1
- package/admin/assets/{BlockEditor-s0CRZsjy.js → BlockEditor-BQVXN_Yn.js} +3 -3
- package/admin/assets/{BlockTypeEditPage-D1OFIlJZ.js → BlockTypeEditPage-BZmvEezy.js} +1 -1
- package/admin/assets/{BlockTypesPage-cJNR25fN.js → BlockTypesPage-CAr2JDj9.js} +1 -1
- package/admin/assets/BulkActionBar-CgHMxSkm.js +1 -0
- package/admin/assets/{CollectionEditPage-DRmCA_73.js → CollectionEditPage-BQoXWAB-.js} +1 -1
- package/admin/assets/{CollectionsPage-CeQB5e9u.js → CollectionsPage-Dakk_NyE.js} +1 -1
- package/admin/assets/{ContentCreatePage-Cq8Pi8EF.js → ContentCreatePage-d-xxhoxO.js} +1 -1
- package/admin/assets/ContentEditPage-CUi_mFRC.js +1 -0
- package/admin/assets/{ContentField-BZT4OUfI.js → ContentField-D6UO6W9G.js} +1 -1
- package/admin/assets/ContentListPage-8riubzdw.js +1 -0
- package/admin/assets/{CustomBlockPreview-Kc6bb3oq.js → CustomBlockPreview-BuRfUKgt.js} +1 -1
- package/admin/assets/{FieldRenderer-CT-DgCbC.js → FieldRenderer-CUVay-yx.js} +2 -2
- package/admin/assets/{FileTypeIcon-CNHtffHC.js → FileTypeIcon-DRD08pW_.js} +1 -1
- package/admin/assets/{FloatingComposerController-D4uLQfUX-0_Y8mkGU.js → FloatingComposerController-D4uLQfUX-Dc1_NZ4l.js} +1 -1
- package/admin/assets/{IconPicker-BpPlHJO0.js → IconPicker-DR-6b0GI.js} +1 -1
- package/admin/assets/{LoginPage-Dya8sF_P.js → LoginPage-DbHhSxgY.js} +1 -1
- package/admin/assets/{MediaField-C3qFf3g5.js → MediaField-eRyEALYH.js} +1 -1
- package/admin/assets/{MediaPage-BNxc0wLq.js → MediaPage-DW85F2UV.js} +1 -1
- package/admin/assets/{Pagination-Dx8h11Rn.js → Pagination-DTboMLK6.js} +1 -1
- package/admin/assets/{RelationshipPicker-C2MTxrhl.js → RelationshipPicker-VVZN4dlP.js} +1 -1
- package/admin/assets/{SiteSettingsPage-BDZaUBmf.js → SiteSettingsPage-5-HzcJLC.js} +1 -1
- package/admin/assets/{SiteUserEditPage-MfzhPW7v.js → SiteUserEditPage-C_PPvEye.js} +1 -1
- package/admin/assets/{SiteUsersPage-CrYugXpx.js → SiteUsersPage-CIgMMi-T.js} +1 -1
- package/admin/assets/{SitesPage-Cl8V3Hb7.js → SitesPage-DkG0gyHT.js} +1 -1
- package/admin/assets/SubmissionDetailPage-BwFWjkVu.js +1 -0
- package/admin/assets/{SubmissionEditPage-B0Kq52fb.js → SubmissionEditPage-C6Og25NH.js} +1 -1
- package/admin/assets/SubmissionListPage-spPh8dwQ.js +1 -0
- package/admin/assets/{TagInput-C6tcB5Xw.js → TagInput-DxktEo07.js} +1 -1
- package/admin/assets/{TagsPage-BONR6bSu.js → TagsPage-Dcc1IkF7.js} +1 -1
- package/admin/assets/TrashPage-8ybk22ZM.js +1 -0
- package/admin/assets/{UsersPage-C2iCy0UR.js → UsersPage-D5uXgLV4.js} +1 -1
- package/admin/assets/{WebhookEditPage-DjZFxT72.js → WebhookEditPage-T5KsZGqe.js} +1 -1
- package/admin/assets/{WebhooksPage-g_a224a4.js → WebhooksPage-DEIu5cX0.js} +1 -1
- package/admin/assets/{card-DlfsF8lU.js → card-CVAiqxnT.js} +1 -1
- package/admin/assets/{checkbox-BX8EcGFf.js → checkbox-BO-Fusdb.js} +1 -1
- package/admin/assets/{command-DaTsImUa.js → command-D0ojin3H.js} +1 -1
- package/admin/assets/index-BCa3VYjL.css +1 -0
- package/admin/assets/{index-DC1UyCW2.js → index-CbEa9yyd.js} +10 -10
- package/admin/assets/{listCellValue-CBqXAwce.js → listCellValue-BUdbRyCz.js} +1 -1
- package/admin/assets/{popover-BA-47SRI.js → popover-B9WNjj2t.js} +1 -1
- package/admin/assets/{select-waaVyoQ5.js → select-B2yTIHJT.js} +1 -1
- package/admin/assets/{serializeToText-CjHhyvXp.js → serializeToText-Tv-7pIdy.js} +1 -1
- package/admin/assets/{table-Br-QgtTL.js → table-C3EQVw1z.js} +1 -1
- package/admin/assets/{textarea-BILv1DQB.js → textarea-DIHLWabG.js} +1 -1
- package/admin/assets/useAdminResolver-_OHcUYwq.js +1 -0
- package/admin/assets/useContent-DLo6FUYZ.js +1 -0
- package/admin/assets/{useContentSearch-DbiA8aG-.js → useContentSearch-D-D0veFh.js} +1 -1
- package/admin/assets/{usePageTitle-DOEFrHbj.js → usePageTitle-BJ2ARyuc.js} +1 -1
- package/admin/assets/{useSiteUsers-BFYAbJNT.js → useSiteUsers-Bn3GiEYB.js} +1 -1
- package/admin/assets/{useTags-DJlXwDyc.js → useTags-CyGo0zXa.js} +1 -1
- package/admin/assets/useTrash-BFJMIP8N.js +1 -0
- package/admin/assets/{useWebhooks-BkpJKNLN.js → useWebhooks-BgJL2-Ek.js} +1 -1
- package/admin/index.html +2 -2
- package/admin/sw.js +1 -1
- package/dist/cron.d.ts +42 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +128 -0
- package/dist/cron.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/lambda/api/bootstrap +0 -0
- package/lambda/backup-worker/bootstrap +0 -0
- package/lambda/trash-sweeper/bootstrap +0 -0
- package/lambda/webhook-worker/bootstrap +0 -0
- package/package.json +1 -1
- package/src/cron.ts +153 -0
- package/src/index.ts +21 -0
- package/src/sst-env.d.ts +17 -0
- package/admin/assets/AllContentPage-D5ey5AOV.js +0 -1
- package/admin/assets/BulkActionBar-BWysX7Wo.js +0 -1
- package/admin/assets/ContentEditPage-CEJ7I3WH.js +0 -1
- package/admin/assets/ContentListPage-BCEQrYVs.js +0 -1
- package/admin/assets/SubmissionDetailPage-BnVlsGb-.js +0 -1
- package/admin/assets/SubmissionListPage-K665VwMp.js +0 -1
- package/admin/assets/index-9sbb3-yI.css +0 -1
- package/admin/assets/useAdminResolver-CbDzGoDp.js +0 -1
- package/admin/assets/useContent-Bp4f9qe0.js +0 -1
package/src/cron.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron Infrastructure
|
|
3
|
+
*
|
|
4
|
+
* EventBridge-driven scheduled Lambdas for periodic CMS maintenance. Today
|
|
5
|
+
* this is just the trash sweeper (Phase 2b of `steering/TRASH_CAN.md`); other
|
|
6
|
+
* cron-shaped workers (backup retention, etc.) live in their own modules.
|
|
7
|
+
*
|
|
8
|
+
* The trash sweeper Lambda walks every site, every collection, and purges
|
|
9
|
+
* content trashed more than `model.TrashRetentionDays` (30) days ago via the
|
|
10
|
+
* service-layer `Purge` — which fans out to drafts, slug lookups, tag counts,
|
|
11
|
+
* relationships, audit, and a `content.deleted` webhook per item. See
|
|
12
|
+
* `packages/api/cmd/trash_sweeper/main.go` for the entrypoint.
|
|
13
|
+
*
|
|
14
|
+
* Mass-delete protection is a per-run circuit breaker inside the sweeper
|
|
15
|
+
* (`TRASH_PURGE_RUN_CAP`), not a CloudWatch alarm: a run that would purge at
|
|
16
|
+
* least the cap aborts and logs at ERROR instead of completing. This keeps the
|
|
17
|
+
* feature at $0-at-rest (no custom CloudWatch metric, no alarm, no SNS topic)
|
|
18
|
+
* while actively *preventing* a runaway purge rather than alerting after the
|
|
19
|
+
* fact. The abort is visible in the sweeper's daily CloudWatch Logs line.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import path from "path";
|
|
23
|
+
import type { StorageResources } from "./storage.js";
|
|
24
|
+
import type { WebhookResources } from "./webhooks.js";
|
|
25
|
+
|
|
26
|
+
export interface CronArgs {
|
|
27
|
+
storage: StorageResources;
|
|
28
|
+
webhooks: WebhookResources;
|
|
29
|
+
pkgRoot: string;
|
|
30
|
+
/**
|
|
31
|
+
* Stage name (`$app.stage`). Used to tune per-stage alarm thresholds: prod
|
|
32
|
+
* is tight (1000 purges/day signals mass-delete), dev/PR stages are loose
|
|
33
|
+
* to absorb manual testing without paging.
|
|
34
|
+
*/
|
|
35
|
+
stage: string;
|
|
36
|
+
dev?: {
|
|
37
|
+
/** Go source path for the trash sweeper, e.g. "packages/api/cmd/trash_sweeper" */
|
|
38
|
+
handler: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Per-stage value for the sweeper's per-run purge circuit breaker
|
|
44
|
+
* (`TRASH_PURGE_RUN_CAP`). A run that would purge at least this many items
|
|
45
|
+
* aborts instead of completing — the cheap, $0 replacement for the old
|
|
46
|
+
* CloudWatch mass-delete alarm. Production is tight (1000/run signals a likely
|
|
47
|
+
* mass-delete); dev/PR stages are loose so manual testing doesn't trip it.
|
|
48
|
+
* Read by `packages/api/cmd/trash_sweeper/main.go`.
|
|
49
|
+
*/
|
|
50
|
+
function trashPurgeRunCap(stage: string): number {
|
|
51
|
+
return stage === "production" ? 1000 : 10000;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function createCron(name: string, args: CronArgs) {
|
|
55
|
+
const { storage, webhooks } = args;
|
|
56
|
+
|
|
57
|
+
const trashSweeperConfig = args.dev
|
|
58
|
+
? {
|
|
59
|
+
handler: args.dev.handler,
|
|
60
|
+
runtime: "go" as const,
|
|
61
|
+
}
|
|
62
|
+
: {
|
|
63
|
+
bundle: path.join(args.pkgRoot, "lambda/trash-sweeper"),
|
|
64
|
+
handler: "bootstrap",
|
|
65
|
+
runtime: "provided.al2023" as const,
|
|
66
|
+
architecture: "arm64" as const,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Daily at 03:00 UTC. Cron syntax: minute hour day-of-month month day-of-week year.
|
|
70
|
+
// EventBridge requires either day-of-month or day-of-week to be `?`.
|
|
71
|
+
const trashSweeperCron = new sst.aws.Cron(`${name}TrashSweeper`, {
|
|
72
|
+
schedule: "cron(0 3 * * ? *)",
|
|
73
|
+
job: {
|
|
74
|
+
...trashSweeperConfig,
|
|
75
|
+
// The sweeper pages through every site × every collection. 5 minutes
|
|
76
|
+
// is generous; a single site rarely has > 100 trashed items per
|
|
77
|
+
// collection per day. If we ever hit the timeout, the next run will
|
|
78
|
+
// pick up where we left off (items remain in the trash partition).
|
|
79
|
+
timeout: "5 minutes",
|
|
80
|
+
memory: "512 MB",
|
|
81
|
+
environment: {
|
|
82
|
+
// DynamoDB tables. NOTE: The sweeper's only entry point is
|
|
83
|
+
// AdminContentService.Purge, which touches content + drafts + audit
|
|
84
|
+
// + relationships + (indirectly via tagsRepo) ContentTable's
|
|
85
|
+
// tag-count items. blocksRepo and mediaRepo are passed to
|
|
86
|
+
// NewAdminContentService for symmetry with the API, but Purge's
|
|
87
|
+
// call graph never reaches them — so BLOCKS_TABLE / MEDIA_TABLE
|
|
88
|
+
// are deliberately omitted. If the sweeper ever grows a second
|
|
89
|
+
// entry point (Trash / Restore / Publish), revisit.
|
|
90
|
+
SITES_TABLE: storage.sites.name,
|
|
91
|
+
CONTENT_TABLE: storage.content.name,
|
|
92
|
+
DRAFT_CONTENT_TABLE: storage.draftContent.name,
|
|
93
|
+
COLLECTIONS_TABLE: storage.collections.name,
|
|
94
|
+
BLOCK_TYPES_TABLE: storage.blockTypes.name,
|
|
95
|
+
ADMIN_AUDIT_TABLE: storage.adminAudit.name,
|
|
96
|
+
RELATIONSHIPS_TABLE: storage.relationships.name,
|
|
97
|
+
WEBHOOKS_TABLE: webhooks.webhooks.name,
|
|
98
|
+
WEBHOOK_DELIVERIES_TABLE: webhooks.webhookDeliveries.name,
|
|
99
|
+
// Purge bumps the CDN site-version on published items, so the
|
|
100
|
+
// sweeper needs to write into the KVS just like the API Lambda.
|
|
101
|
+
KVS_ARN: storage.kvs.arn,
|
|
102
|
+
// Webhook fan-out async-invokes this Lambda per subscribed webhook.
|
|
103
|
+
WEBHOOK_WORKER_FUNCTION_NAME: webhooks.webhookWorker.name,
|
|
104
|
+
AWS_REGION_NAME: aws.getRegionOutput().name,
|
|
105
|
+
// Per-run purge circuit breaker. A sweep that would purge at least
|
|
106
|
+
// this many items aborts (and logs at ERROR) instead of completing —
|
|
107
|
+
// a $0 guard against a mass-delete / runaway, replacing the old
|
|
108
|
+
// CloudWatch mass-delete alarm. See trashPurgeRunCap above.
|
|
109
|
+
TRASH_PURGE_RUN_CAP: String(trashPurgeRunCap(args.stage)),
|
|
110
|
+
},
|
|
111
|
+
link: [
|
|
112
|
+
// Read/write — Purge mutates content (incl. tag-count items and
|
|
113
|
+
// slug-lookup rows) + drafts + audit + relationships, and emits
|
|
114
|
+
// per-item webhook delivery rows. Sites/collections/blockTypes are
|
|
115
|
+
// read-only for the sweep loop (ListAll + GetCollections).
|
|
116
|
+
// storage.blocks and storage.media are deliberately NOT linked —
|
|
117
|
+
// see env comment above.
|
|
118
|
+
storage.sites,
|
|
119
|
+
storage.content,
|
|
120
|
+
storage.draftContent,
|
|
121
|
+
storage.collections,
|
|
122
|
+
storage.blockTypes,
|
|
123
|
+
storage.adminAudit,
|
|
124
|
+
storage.relationships,
|
|
125
|
+
webhooks.webhooks,
|
|
126
|
+
webhooks.webhookDeliveries,
|
|
127
|
+
],
|
|
128
|
+
permissions: [
|
|
129
|
+
{
|
|
130
|
+
// CloudFront KVS bump on Purge of a published item — mirrors the
|
|
131
|
+
// API Lambda's KVS permission set.
|
|
132
|
+
actions: [
|
|
133
|
+
"cloudfront-keyvaluestore:DescribeKeyValueStore",
|
|
134
|
+
"cloudfront-keyvaluestore:PutKey",
|
|
135
|
+
"cloudfront-keyvaluestore:DeleteKey",
|
|
136
|
+
"cloudfront-keyvaluestore:GetKey",
|
|
137
|
+
],
|
|
138
|
+
resources: [storage.kvs.arn],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
// Async invoke of the webhook worker. Same grant pattern as the
|
|
142
|
+
// API Lambda (`webhooks.webhookWorker.arn` in `api.ts`).
|
|
143
|
+
actions: ["lambda:InvokeFunction"],
|
|
144
|
+
resources: [webhooks.webhookWorker.arn],
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return { trashSweeperCron };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export type CronResources = ReturnType<typeof createCron>;
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { createMediaCdn } from "./cdn-media.js";
|
|
|
18
18
|
import { createScheduler } from "./scheduler.js";
|
|
19
19
|
import { createCollabTable, createCollabHandler } from "./collaboration.js";
|
|
20
20
|
import { createAdminSite } from "./admin-site.js";
|
|
21
|
+
import { createCron } from "./cron.js";
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Resolve the headroom-cms package root directory.
|
|
@@ -57,6 +58,7 @@ export type { MediaCdnResources } from "./cdn-media.js";
|
|
|
57
58
|
export type { SchedulerResources } from "./scheduler.js";
|
|
58
59
|
export type { CollaborationResources } from "./collaboration.js";
|
|
59
60
|
export type { AdminSiteResources } from "./admin-site.js";
|
|
61
|
+
export type { CronResources } from "./cron.js";
|
|
60
62
|
|
|
61
63
|
export interface HeadroomCMSArgs {
|
|
62
64
|
/**
|
|
@@ -141,6 +143,8 @@ export interface HeadroomCMSArgs {
|
|
|
141
143
|
schedulerHandler?: string;
|
|
142
144
|
/** SST handler for collab Lambda, e.g. "packages/collab/src/index.handler" */
|
|
143
145
|
collabHandler?: string;
|
|
146
|
+
/** Go source path for trash sweeper Lambda, e.g. "packages/api/cmd/trash_sweeper" */
|
|
147
|
+
trashSweeperHandler?: string;
|
|
144
148
|
};
|
|
145
149
|
|
|
146
150
|
/**
|
|
@@ -257,6 +261,19 @@ export class HeadroomCMS {
|
|
|
257
261
|
: undefined,
|
|
258
262
|
});
|
|
259
263
|
|
|
264
|
+
// 7b. Cron — daily trash sweeper Lambda (with an in-sweeper per-run purge
|
|
265
|
+
// circuit breaker; no CloudWatch metric/alarm). See `steering/TRASH_CAN.md`
|
|
266
|
+
// Phase 2b.
|
|
267
|
+
const cron = createCron(name, {
|
|
268
|
+
storage,
|
|
269
|
+
webhooks,
|
|
270
|
+
pkgRoot,
|
|
271
|
+
stage: $app.stage,
|
|
272
|
+
dev: args.dev?.trashSweeperHandler
|
|
273
|
+
? { handler: args.dev.trashSweeperHandler }
|
|
274
|
+
: undefined,
|
|
275
|
+
});
|
|
276
|
+
|
|
260
277
|
// 8a. API CDN (CloudFront distribution + edge auth, /v1/* and /health)
|
|
261
278
|
const apiCdn = createApiCdn(name, {
|
|
262
279
|
api,
|
|
@@ -325,6 +342,10 @@ export class HeadroomCMS {
|
|
|
325
342
|
webhooksTable: webhooks.webhooks.name,
|
|
326
343
|
contentBucket: storage.contentBucket.name,
|
|
327
344
|
backupBucket: storage.backupBucket.name,
|
|
345
|
+
// Trash-sweeper Lambda function name (Phase 2b). Surfaced so ops/test
|
|
346
|
+
// scripts can target the sweeper by deterministic output instead of
|
|
347
|
+
// `aws lambda list-functions | grep`.
|
|
348
|
+
trashSweeperFunctionName: cron.trashSweeperCron.nodes.function.name,
|
|
328
349
|
};
|
|
329
350
|
}
|
|
330
351
|
}
|
package/src/sst-env.d.ts
CHANGED
|
@@ -74,6 +74,17 @@ declare namespace sst {
|
|
|
74
74
|
|
|
75
75
|
class Cron {
|
|
76
76
|
constructor(name: string, args: any, opts?: any);
|
|
77
|
+
nodes: {
|
|
78
|
+
function: {
|
|
79
|
+
name: PulumiOutput<string>;
|
|
80
|
+
arn: PulumiOutput<string>;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
class SnsTopic {
|
|
86
|
+
constructor(name: string, args?: any, opts?: any);
|
|
87
|
+
arn: PulumiOutput<string>;
|
|
77
88
|
}
|
|
78
89
|
}
|
|
79
90
|
}
|
|
@@ -159,6 +170,12 @@ declare namespace aws {
|
|
|
159
170
|
constructor(name: string, args?: any, opts?: any);
|
|
160
171
|
}
|
|
161
172
|
}
|
|
173
|
+
|
|
174
|
+
namespace cloudwatch {
|
|
175
|
+
class MetricAlarm {
|
|
176
|
+
constructor(name: string, args?: any, opts?: any);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
162
179
|
}
|
|
163
180
|
|
|
164
181
|
// ---------------------------------------------------------------------------
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./tanstack-Bs3zYPPV.js";import{u as H,f as F,m as V,r as j}from"./react-vendor-C2CvUxFh.js";import{u as _,a as q,b as G,c as J}from"./useContent-Bp4f9qe0.js";import{m as U}from"./media-url-DdCoIedP.js";import{w as K,x as O,v as u,S as Q,j as g,y as W}from"./index-DC1UyCW2.js";import{u as X}from"./usePageTitle-DOEFrHbj.js";import{C as Y,c as Z}from"./card-DlfsF8lU.js";import{C as b}from"./checkbox-BX8EcGFf.js";import{T as ee,a as se,b as T,c as h,d as te,e as m}from"./table-Br-QgtTL.js";import{f as B}from"./format-BRcflvs9.js";import{B as ne}from"./BulkActionBar-BWysX7Wo.js";import{P as ae}from"./Pagination-Dx8h11Rn.js";import"./radix-C5ZmWuuL.js";import"./select-waaVyoQ5.js";function be(){const{host:i}=H(),P=F(),{collections:R}=K(),w=O();X({title:"Recent"});const[x,d]=V(),r=Number(x.get("page"))||1,N=Number(x.get("perPage"))||20,S=j.useMemo(()=>{const e=x.get("after")||"";return e?e.split(","):[]},[x]),[a,c]=j.useState(new Set),p=j.useCallback(()=>{d(e=>{const n=new URLSearchParams(e);return n.delete("page"),n.delete("perPage"),n.delete("after"),n},{replace:!0}),c(new Set)},[d]),L=r>1?S[r-2]:void 0,{data:o,isLoading:D}=_(i,L,N),v=q(i),C=G(i),k=J(i),I=new Map(R.map(e=>[e.name,e.label])),f=o?.items.map(e=>e.contentId)??[],y=f.length>0&&f.every(e=>a.has(e));function A(e){c(n=>{const t=new Set(n);return t.has(e)?t.delete(e):t.add(e),t})}function M(){c(y?new Set:new Set(f))}const z=v.isPending||C.isPending||k.isPending;function $(e){d(n=>{const t=new URLSearchParams(n);return e===1?t.delete("page"):t.set("page",String(e)),t},{replace:!0})}function E(e){d(n=>{const t=new URLSearchParams(n);return t.delete("page"),t.delete("after"),e===20?t.delete("perPage"):t.set("perPage",String(e)),t},{replace:!0}),c(new Set)}return s.jsxs("div",{children:[!w&&s.jsxs("div",{className:"mb-6",children:[s.jsx("h1",{className:"text-2xl font-semibold",children:"All Content"}),s.jsx("p",{className:"text-muted-foreground text-sm",children:"Recently updated content across all collections."})]}),a.size>0&&s.jsx(ne,{selectedCount:a.size,onPublish:async()=>{const e=[...a],t=(await v.mutateAsync(e)).filter(l=>l.status==="rejected").length;t?u.error(`${t} of ${e.length} failed to publish`):u.success(`${e.length} item(s) published`),p()},onUnpublish:async()=>{const e=[...a],t=(await C.mutateAsync(e)).filter(l=>l.status==="rejected").length;t?u.error(`${t} of ${e.length} failed to unpublish`):u.success(`${e.length} item(s) unpublished`),p()},onDelete:async()=>{const e=[...a],t=(await k.mutateAsync(e)).filter(l=>l.status==="rejected").length;t?u.error(`${t} of ${e.length} failed to delete`):u.success(`${e.length} item(s) deleted`),p()},onClear:()=>c(new Set),isPending:z}),D?s.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((e,n)=>s.jsx(Q,{className:"h-12 w-full"},n))}):o?.items.length?s.jsxs(s.Fragment,{children:[w?s.jsx("div",{className:"grid gap-3","data-testid":"all-content-card-view",children:o.items.map(e=>{const n=e.cover;return s.jsx(Y,{className:W("cursor-pointer gap-0 overflow-hidden py-0 transition-shadow hover:shadow-md",a.has(e.contentId)&&"ring-2 ring-primary"),onClick:()=>P(`/sites/${i}/content/${e.collection}/${e.contentId}?from=recent`),children:s.jsx(Z,{className:"p-3",children:s.jsxs("div",{className:"flex items-start gap-3 min-w-0",children:[n?.url&&s.jsx("img",{src:U(n.url),alt:n.alt??"",className:"h-12 w-12 rounded object-cover flex-shrink-0"}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s.jsx("span",{className:"font-medium truncate",children:e.title||"Untitled"}),s.jsx(g,{variant:e.publishedAt?"default":"secondary",className:"shrink-0",children:e.publishedAt?"Published":"Draft"})]}),e.slug&&s.jsxs("p",{className:"text-xs text-muted-foreground truncate mt-0.5",children:["/",e.slug]}),s.jsxs("div",{className:"flex items-center gap-2 mt-1",children:[s.jsx(g,{variant:"outline",className:"text-[10px] px-1.5 py-0",children:I.get(e.collection)??e.collection}),s.jsx("span",{className:"text-xs text-muted-foreground",children:e.publishedAt?B(e.publishedAt):"—"})]})]}),s.jsx(b,{checked:a.has(e.contentId),onCheckedChange:()=>A(e.contentId),onClick:t=>t.stopPropagation(),className:"mt-1"})]})})},e.contentId)})}):s.jsxs(ee,{children:[s.jsx(se,{children:s.jsxs(T,{children:[s.jsx(h,{className:"w-10",children:s.jsx(b,{checked:y,onCheckedChange:M,"aria-label":"Select all"})}),s.jsx(h,{children:"Title"}),s.jsx(h,{children:"Slug"}),s.jsx(h,{children:"Collection"}),s.jsx(h,{children:"Status"}),s.jsx(h,{children:"Updated"})]})}),s.jsx(te,{children:o.items.map(e=>s.jsxs(T,{className:"cursor-pointer",onClick:()=>P(`/sites/${i}/content/${e.collection}/${e.contentId}?from=recent`),children:[s.jsx(m,{onClick:n=>n.stopPropagation(),children:s.jsx(b,{checked:a.has(e.contentId),onCheckedChange:()=>A(e.contentId),"aria-label":`Select ${e.title||"Untitled"}`})}),s.jsx(m,{className:"font-medium",children:s.jsxs("div",{className:"flex items-center gap-3",children:[(()=>{const n=e.cover;return n?.url?s.jsx("img",{src:U(n.url),alt:n.alt??"",className:"h-8 w-8 rounded object-cover flex-shrink-0"}):null})(),s.jsx("span",{children:e.title||"Untitled"})]})}),s.jsx(m,{className:"text-muted-foreground text-sm",children:e.slug||"—"}),s.jsx(m,{children:s.jsx(g,{variant:"outline",children:I.get(e.collection)??e.collection})}),s.jsx(m,{children:s.jsx(g,{variant:e.publishedAt?"default":"secondary",children:e.publishedAt?"Published":"Draft"})}),s.jsx(m,{className:"text-muted-foreground",children:e.publishedAt?B(e.publishedAt):"—"})]},e.contentId))})]}),s.jsx(ae,{page:r,hasNext:!!o?.hasMore,hasPrevious:r>1,onNext:()=>{if(o?.items.length){const e=o.items[o.items.length-1].contentId,n=[...S.slice(0,r-1),e];d(t=>{const l=new URLSearchParams(t);return l.set("page",String(r+1)),l.set("after",n.join(",")),l},{replace:!0})}else $(r+1);c(new Set)},onPrevious:()=>{const e=r-1;e<=1?d(n=>{const t=new URLSearchParams(n);return t.delete("page"),t.delete("after"),t},{replace:!0}):$(e),c(new Set)},perPage:N,onPerPageChange:E})]}):s.jsx("p",{className:"text-muted-foreground",children:"No content yet."})]})}export{be as AllContentPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./tanstack-Bs3zYPPV.js";import{r as m}from"./react-vendor-C2CvUxFh.js";import{B as a,a as t,X as x,D as h,k as j,l as p,m as u,n as D,o as b}from"./index-DC1UyCW2.js";function k({selectedCount:i,onPublish:n,onUnpublish:r,onDelete:o,onClear:c,isPending:s}){const[d,l]=m.useState(!1);return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-4 flex items-center gap-3 rounded-md border bg-muted/50 px-4 py-2",children:[e.jsxs("span",{className:"text-sm font-medium",children:[i," selected"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(a,{size:"sm",variant:"outline",onClick:n,disabled:s,children:[s&&e.jsx(t,{className:"mr-1 h-3 w-3 animate-spin"}),"Publish"]}),e.jsx(a,{size:"sm",variant:"outline",onClick:r,disabled:s,children:"Unpublish"}),e.jsx(a,{size:"sm",variant:"destructive",onClick:()=>l(!0),disabled:s,children:"Delete"})]}),e.jsx(a,{size:"sm",variant:"ghost",onClick:c,className:"ml-auto",disabled:s,children:e.jsx(x,{className:"h-4 w-4"})})]}),e.jsx(h,{open:d,onOpenChange:l,children:e.jsxs(j,{children:[e.jsxs(p,{children:[e.jsxs(u,{children:["Delete ",i," item",i!==1?"s":"","?"]}),e.jsx(D,{children:"This action cannot be undone. The selected content items will be permanently deleted."})]}),e.jsxs(b,{children:[e.jsx(a,{variant:"outline",onClick:()=>l(!1),children:"Cancel"}),e.jsxs(a,{variant:"destructive",onClick:async()=>{l(!1),await o()},disabled:s,children:[s&&e.jsx(t,{className:"mr-1 h-3 w-3 animate-spin"}),"Delete"]})]})]})})]})}export{k as B};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as Vt,u as On,b as Bn,j as e}from"./tanstack-Bs3zYPPV.js";import{r as t,u as qn,f as _n,m as $n,L as Vn}from"./react-vendor-C2CvUxFh.js";import{f as Mn,g as Es,h as Hn,i as Ps,j as Jn,k as zn,l as Kn,m as Yn,n as Qn,o as Wn,p as Gn,q as Xn,r as Ls}from"./useContent-Bp4f9qe0.js";import{C as Ce,E as os,F as lt,v as J,G as Mt,e as ft,u as Ht,J as Nt,B as F,K as Zn,y as mt,M as ea,N as ta,O as sa,Q as na,S as ve,R as Ts,V as Is,W as ot,Y as dt,Z as Us,_ as Fs,$ as Os,a0 as Bs,U as aa,a1 as ra,w as ia,d as la,x as ca,L as at,I as ds,a2 as qs,X as us,a3 as oa,a4 as hs,a5 as da,a6 as fs,a7 as ua,j as ha,a as we,a8 as ms,a9 as ps,aa as fa,ab as gs,ac as At,ad as ma,ae as pa,D as Ut,k as Ft,l as Ot,m as Bt,n as qt,o as _t,i as ga,T as ba}from"./index-DC1UyCW2.js";import{A as _s,a as $s,b as Vs,c as Ms,d as Hs,e as Js,f as zs,g as Ks,T as xa}from"./TagInput-C6tcB5Xw.js";import{a as ct,f as Ne}from"./format-BRcflvs9.js";import{u as Ys}from"./useAdminResolver-CbDzGoDp.js";import{u as va}from"./usePageTitle-DOEFrHbj.js";import{s as Me,T as ya,d as ka}from"./serializeToText-CjHhyvXp.js";import{S as ja,a as Sa,b as wa,c as Ca,d as Dt,e as Ra,f as Na,g as Aa}from"./select-waaVyoQ5.js";import{T as Da}from"./textarea-BILv1DQB.js";import{C as $e,c as Ve,a as bs,b as xs}from"./card-DlfsF8lU.js";import{C as Qs,a as Ws,b as Gs}from"./collapsible-D3d29uJp.js";import{u as Ea}from"./useTags-DJlXwDyc.js";import{M as Pa}from"./MediaField-C3qFf3g5.js";import{m as La}from"./media-url-DdCoIedP.js";import{R as Ta}from"./RelationshipPicker-C2MTxrhl.js";import{A as Ia,a as Ua,i as Fa,F as Oa,b as rt,C as Ba}from"./FieldRenderer-CT-DgCbC.js";import{g as qa,a as _a,b as $a}from"./contentStatus-WXGfd7vX.js";import{O as Va,f as Ma,g as ut,e as Xs,w as Et,a as Ha,t as Ja,r as Pt,b as za,c as Ka,d as Ya,h as Qa,i as vs,j as Wa,D as Ga}from"./yjs-tXBm_srz.js";import"./radix-C5ZmWuuL.js";import"./FileTypeIcon-CNHtffHC.js";import"./table-Br-QgtTL.js";import"./core.esm-DdQHdRkd.js";import"./sortable.esm-qVEMoaTg.js";import"./ContentField-BZT4OUfI.js";import"./popover-BA-47SRI.js";import"./command-DaTsImUa.js";import"./useContentSearch-DbiA8aG-.js";import"./checkbox-BX8EcGFf.js";const Xa=3e3,Za="__HEADROOM_API_URL__".replace(/\/+$/,""),er=4;function tr(i,s,r,a,l,c=Xa,f,d={}){const p=Mn(i,s),o=t.useRef(null),y=t.useRef(r?JSON.stringify(r):""),x=t.useRef(void 0),[R,P]=t.useState(null),[j,O]=t.useState(null),A=t.useRef(!1),D=t.useRef(!1),v=t.useRef(!1),S=t.useRef(!1),L=t.useRef(!1),B=t.useRef(!1),q=t.useRef(0),U=t.useRef(null),X=t.useCallback(N=>{const k=1e3*Math.pow(3,N);return Math.min(k,3e4)},[]),T=t.useRef(null),E=t.useRef(null),[ne,ae]=t.useState(!1),se=t.useRef(!1),M=t.useCallback(N=>{se.current!==N&&(se.current=N,ae(N))},[]),re=t.useRef(f);t.useEffect(()=>{re.current=f},[f]);const G=t.useRef(d.onBeforeFirstSave);t.useEffect(()=>{G.current=d.onBeforeFirstSave},[d.onBeforeFirstSave]);const Z=t.useRef(d.onStaleBaseConflict);t.useEffect(()=>{Z.current=d.onStaleBaseConflict},[d.onStaleBaseConflict]);const _=t.useRef(d.getCurrentParams);t.useEffect(()=>{_.current=d.getCurrentParams},[d.getCurrentParams]);const w=t.useRef(d.getBaseUpdatedAt);t.useEffect(()=>{w.current=d.getBaseUpdatedAt},[d.getBaseUpdatedAt]);const $=t.useRef(d.onNetworkError);t.useEffect(()=>{$.current=d.onNetworkError},[d.onNetworkError]);const u=t.useRef(()=>{}),m=t.useCallback(()=>{if(B.current||!o.current)return;const N=X(q.current);q.current=Math.min(q.current+1,er),clearTimeout(x.current),x.current=window.setTimeout(()=>u.current(),N)},[X]),H=t.useCallback(N=>{if(N instanceof Ce&&N.status>=500)return $.current?.({kind:"server-error",status:N.status,retryAttempt:q.current}),!0;const k=N;if(k?.name==="AbortError"){const K=k.cause;return(K&&typeof K=="object"&&"message"in K?String(K.message??""):String(K??""))===os&&$.current?.({kind:"timeout",retryAttempt:q.current}),!0}return N instanceof Ce?!1:($.current?.({kind:"network",retryAttempt:q.current}),!0)},[]),Y=t.useCallback(async()=>{if(B.current||L.current||!o.current||v.current||D.current)return;v.current=!0,T.current=new Promise(h=>{E.current=h});const N=()=>{const h=E.current;E.current=null,T.current=null,h?.()};if(!S.current&&G.current)try{if(!(await G.current()).ok){v.current=!1,N();return}S.current=!0}catch{v.current=!1,N();return}if(B.current||!o.current){v.current=!1,N();return}if(D.current){v.current=!1,N();return}const k=o.current,K=w.current?.();U.current||(U.current=lt());const ce={...k,...typeof K=="number"&&K>0?{baseUpdatedAt:K}:{},idempotencyKey:U.current},Q=JSON.stringify(ce);p.mutate(ce,{onSuccess:h=>{if(v.current=!1,N(),q.current=0,A.current){A.current=!1;return}U.current=null,o.current===k&&(o.current=null,M(!1)),y.current=Q,P(Date.now()),h?.blockId&&O(h.blockId),re.current?.(h),!B.current&&o.current&&(clearTimeout(x.current),x.current=window.setTimeout(()=>u.current(),500))},onError:h=>{if(v.current=!1,N(),h instanceof Ce&&h.code==="SLUG_TAKEN"){a?.();return}if(h instanceof Ce&&h.code==="LOCK_HELD"){S.current=!1,l?.(h);return}if(h instanceof Ce&&h.code==="STALE_BASE"){const C=h.body;Z.current?.(C?.currentUpdatedAt??0,C?.currentBlockId??"");return}if(h instanceof Ce&&h.status===400){J.error("Auto-save failed",{description:h.message});return}if(h instanceof Ce&&h.status>=500){$.current?.({kind:"server-error",status:h.status,retryAttempt:q.current}),m();return}const I=h;if(I?.name==="AbortError"){const C=I.cause;(C&&typeof C=="object"&&"message"in C?String(C.message??""):String(C??""))===os&&($.current?.({kind:"timeout",retryAttempt:q.current}),m());return}$.current?.({kind:"network",retryAttempt:q.current}),m()}})},[p,a,l,M,m]);t.useEffect(()=>{u.current=Y},[Y]);const ue=t.useCallback(N=>{L.current||JSON.stringify(N)===y.current||(U.current=lt(),o.current=N,M(!0),clearTimeout(x.current),x.current=window.setTimeout(Y,c))},[c,M,Y]),z=t.useCallback(async N=>{if(clearTimeout(x.current),D.current=!0,T.current)try{await T.current}catch{}try{let k=null;if(o.current?k={...o.current}:N?.createVersion&&_.current&&(k=_.current()),!k)return;const K=w.current?.();if(typeof K=="number"&&K>0&&(k.baseUpdatedAt=K),U.current||(U.current=lt()),k.idempotencyKey=U.current,N?.createVersion&&(k.createVersion=!0),!S.current&&G.current)try{if(!(await G.current()).ok)return;S.current=!0}catch{return}const ce=JSON.stringify(k);o.current=null,M(!1);try{const Q=await p.mutateAsync(k);y.current=ce,P(Date.now()),Q?.blockId&&O(Q.blockId),U.current=null}catch(Q){if(o.current||(o.current=k,M(!0)),!H(Q))throw Q}}finally{D.current=!1}},[p,M,H]),pe=t.useCallback(()=>{clearTimeout(x.current),o.current=null,M(!1),U.current=null},[M]),te=t.useCallback(()=>{S.current=!1},[]),Oe=t.useCallback(N=>{y.current=JSON.stringify(N),S.current=!1,U.current=null},[]),Ae=t.useCallback(()=>{clearTimeout(x.current),o.current=null,M(!1),A.current=!0,O(null),S.current=!1,U.current=null},[M]),Be=t.useCallback(()=>{L.current=!0,clearTimeout(x.current)},[]),b=t.useCallback(()=>{L.current=!1},[]);return t.useEffect(()=>(B.current=!1,()=>{if(B.current=!0,clearTimeout(x.current),o.current){const{sessionId:N,...k}=o.current,K=w.current?.(),ce={...k,...typeof K=="number"&&K>0?{baseUpdatedAt:K}:{}},Q=JSON.stringify(ce),h=Mt(),I=`${Za}/v1/admin/sites/${i}/content/${s}/draft`;fetch(I,{method:"PUT",body:Q,headers:{"Content-Type":"application/json",...h?{Authorization:`Bearer ${h}`}:{}},keepalive:!0}).catch(()=>{}),o.current=null}}),[i,s]),{schedule:ue,flush:z,cancel:pe,resetBaseline:Oe,discard:Ae,pause:Be,resume:b,markLockReleased:te,isDirty:ne,isSaving:p.isPending,lastSavedAt:R,lastSavedBlockId:j,adoptServerBlockId:N=>{O(N)},getIsSavingSync:()=>v.current||D.current,getHasPending:()=>o.current!==null}}const ys="headroom:idleHintShown",sr="__HEADROOM_API_URL__".replace(/\/+$/,""),nr=5e3,ar=3600*1e3,rr=6e4,Lt=2e3;function ir(i){const s=`headroom:editSession:${i}`;let r=sessionStorage.getItem(s);return r||(r=lt(),sessionStorage.setItem(s,r)),r}const Tt=new Map;function lr(i,s,r={}){const a=ft(),{user:l}=Ht(),c=Vt(),[f,d]=t.useState("viewing"),[p,o]=t.useState(null),[y,x]=t.useState(null),[R,P]=t.useState([]),[j,O]=t.useState(!1),[A,D]=t.useState(!1),v=s?ir(s):"",S=t.useRef(0),L=t.useRef(!1),B=t.useRef(!1),q=t.useRef(!1),U=t.useRef(null),X=t.useRef(null),T=t.useRef(0),E=t.useRef(null),ne=t.useRef(r.getIsDirty),ae=t.useRef(r.getIsSaving),se=t.useRef(r.getIsSavingSync),M=t.useRef(r.onIdleRelease),re=t.useRef(r.onLockAcquired);t.useEffect(()=>{ne.current=r.getIsDirty,ae.current=r.getIsSaving,se.current=r.getIsSavingSync,M.current=r.onIdleRelease,re.current=r.onLockAcquired});const G=t.useCallback(async(h=!1)=>{if(!i||!s||!v)return null;const I=`${i}:${s}:${h?"force":"edit"}`,C=Tt.get(I);if(C)return C;const he=a.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock`,{method:"POST",body:JSON.stringify({sessionId:v,force:h,email:l?.email,name:l?.name})}).finally(()=>{Tt.delete(I)});return Tt.set(I,he),he},[a,i,s,v,l?.email,l?.name]),Z=t.useCallback(async()=>{if(!(!i||!s||!v)&&!B.current&&!q.current){B.current=!0,q.current=!0;try{await a.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock`,{method:"DELETE",body:JSON.stringify({sessionId:v})})}catch{}finally{q.current=!1}}},[a,i,s,v]),_=t.useCallback(()=>{U.current&&(clearTimeout(U.current),U.current=null),X.current&&(clearTimeout(X.current),X.current=null)},[]),w=t.useRef(()=>{}),$=t.useCallback(()=>{const h=ne.current?ne.current():!1,I=ae.current?ae.current():!1,C=se.current?se.current():!1;if(h||I||C){X.current=setTimeout(()=>w.current(),1e3);return}if(L.current){L.current=!1,Z(),M.current?.(),d("idle-released"),o(null),x(null),P([]),D(!1);try{typeof window<"u"&&window.sessionStorage&&(window.sessionStorage.getItem(ys)||(J("Released editing — others can edit now."),window.sessionStorage.setItem(ys,"1")))}catch{}}},[Z]);t.useEffect(()=>{w.current=$},[$]);const u=t.useCallback(()=>{_(),U.current=setTimeout($,rr)},[_,$]),m=t.useCallback(()=>{if(A){_();return}L.current&&u()},[A,_,u]),H=t.useRef(A);t.useEffect(()=>{const h=H.current;H.current=A,h!==A&&(A?_():L.current&&u())},[A,_,u]);const Y=t.useCallback(async()=>{if(!i||!s||!v||!l)return{ok:!1,holder:null};if(Date.now()<T.current)return{ok:!1,holder:E.current};try{const h=await G(!1);if(!h||!h.acquired){const I=h?.lockHolder??null;return T.current=Date.now()+Lt,E.current=I,d("blocked-edit"),o(I),D(h?.collaborationEnabled??!1),S.current||(S.current=Date.now()),{ok:!1,holder:I}}return L.current=!0,B.current=!1,T.current=0,E.current=null,d("editing"),o(h.lockHolder??null),x(h.takeoverReason),D(h.collaborationEnabled),u(),re.current?.(h.updatedAt??0),{ok:!0}}catch(h){const I=h;if(I.status===409){const C=I.body?.lockHolder??null,he=I.body?.collaborationEnabled??!1;if(C&&C.sub===l.sub&&C.sessionId!==v)try{const ee=await G(!1);if(ee?.acquired)return L.current=!0,B.current=!1,T.current=0,E.current=null,d("editing"),o(ee.lockHolder??null),x(ee.takeoverReason),D(ee.collaborationEnabled),u(),re.current?.(ee.updatedAt??0),{ok:!0}}catch{}return T.current=Date.now()+Lt,E.current=C,d("blocked-edit"),o(C),D(he),S.current||(S.current=Date.now()),{ok:!1,holder:C}}return d("error"),{ok:!1,holder:null}}},[i,s,v,l,G,u]);t.useEffect(()=>{if(!i||!s||!v)return;const h=()=>{if(!L.current||B.current||q.current)return;B.current=!0;const I=Mt(),C=`${sr}/v1/admin/sites/${i}/content/${s}/edit-lock`;fetch(C,{method:"DELETE",body:JSON.stringify({sessionId:v}),headers:{"Content-Type":"application/json",...I?{Authorization:`Bearer ${I}`}:{}},keepalive:!0}).catch(()=>{})};return window.addEventListener("beforeunload",h),()=>window.removeEventListener("beforeunload",h)},[i,s,v]);const ue=t.useRef(Z),z=t.useRef(_);t.useEffect(()=>{ue.current=Z,z.current=_},[Z,_]),t.useEffect(()=>()=>{z.current(),L.current&&(L.current=!1,ue.current())},[i,s,v]);const pe=f==="blocked-edit"&&!j,te=t.useCallback(h=>{if(S.current&&Date.now()-S.current>ar){O(!0),d("poll-ceiling");return}const I=h.lock;if(!I)T.current=0,E.current=null,o(null),D(!1),P([]),d("idle-released"),S.current=0;else{o(I.heldBy),D(I.collaborationEnabled);const C=(I.accessRequests??[]).filter(he=>he.sub!==l?.sub);P(C)}},[l?.sub]);On({queryKey:["sites",i,"edit-lock",s],queryFn:async()=>{try{const h=await a.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock`);return te(h),h}catch{return{lock:p?{heldBy:p,expiresAt:0,collaborationEnabled:A,accessRequests:[]}:null}}},enabled:pe,refetchInterval:pe?nr:!1,refetchIntervalInBackground:!1,retry:!1});const Oe=Bn({mutationFn:()=>a.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock/access-requests`,{method:"POST",body:JSON.stringify({sessionId:v,email:l?.email,name:l?.name})})}),Ae=t.useCallback(async()=>{const h=await G(!0);return h?.acquired&&(L.current=!0,B.current=!1,T.current=0,E.current=null,d("editing"),o(h.lockHolder??null),x(h.takeoverReason),D(h.collaborationEnabled),u(),re.current?.(h.updatedAt??0),c.invalidateQueries({queryKey:["sites",i,"edit-lock",s]})),h},[G,c,i,s,u]),Be=t.useCallback(async()=>Y(),[Y]),b=t.useCallback(h=>{L.current=!1,_(),T.current=Date.now()+Lt,E.current=h.lockHolder??null,d("blocked-edit"),o(h.lockHolder??null),x(h.takeoverReason??null),S.current||(S.current=Date.now())},[_]),N=t.useCallback(()=>{_(),L.current&&(L.current=!1,Z()),T.current=0,E.current=null,d("viewing"),o(null),x(null),D(!1),P([]),S.current=0},[_,Z]),k=t.useCallback(()=>{_(),d("stale-reload-pending")},[_]),K=t.useCallback(()=>{d("editing"),L.current&&u()},[u]),ce=t.useCallback(()=>{_(),T.current=0,E.current=null,d("read-only-explicit")},[_]),Q=t.useCallback(()=>{d("viewing")},[]);return{status:f,lockHolder:p,takeoverReason:y,accessRequests:R,sessionId:v,pollCeiling:j,collaborationEnabled:A,acquireLock:G,releaseLock:Z,tryAcquireForEdit:Y,bumpIdleTimer:m,requestCollaboration:Oe,forceTakeover:Ae,takeEditing:Be,endEditing:N,setStaleReloadPending:k,resumeEditingAfterStale:K,setReadOnlyExplicit:ce,exitReadOnly:Q,onAutosaveConflict:b,setAccessRequests:P,setCollaborationEnabled:D}}function cr({host:i,contentId:s,isDirty:r,serverBlockId:a,serverUpdatedAt:l,onSilentReload:c,onStaleWithDirty:f,onTabHidden:d,onTabVisibleResume:p,minHiddenMs:o=3e4}){const y=Vt(),x=t.useRef(null),R=t.useRef(r),P=t.useRef(a),j=t.useRef(l),O=t.useRef(c),A=t.useRef(f),D=t.useRef(d),v=t.useRef(p),S=t.useRef(o);t.useEffect(()=>{R.current=r,P.current=a,j.current=l,O.current=c,A.current=f,D.current=d,v.current=p,S.current=o},[r,a,l,c,f,d,p,o]),t.useEffect(()=>{if(typeof document>"u"||!i||!s)return;const L=["sites",i,"content-detail",s];let B=!1;const q=async()=>{if(typeof document>"u")return;if(document.visibilityState==="hidden"){x.current=Date.now(),D.current&&D.current();return}if(document.visibilityState!=="visible")return;const U=x.current;if(x.current=null,U==null)return;if(Date.now()-U<S.current){v.current&&v.current();return}if(await y.refetchQueries({queryKey:[...L],exact:!0}),B)return;const T=y.getQueryData([...L]);if(!T){v.current&&v.current();return}const E=T.draft?.updatedAt,ne=T.draft?.blockId,ae=j.current??0,se=P.current??null;if(!(typeof E=="number"&&E>ae||ne!=null&&ne!==se)){v.current&&v.current();return}B||(R.current?A.current(T):(v.current&&v.current(),O.current(T)))};return document.addEventListener("visibilitychange",q),()=>{B=!0,document.removeEventListener("visibilitychange",q)}},[i,s,y])}function Jt(){return"__HEADROOM_COLLAB_ENABLED__"!=="false"}function ks({variant:i="read-only-explicit",lockHolder:s,onRequestCollaboration:r,onForceTakeover:a,onDiscardPending:l,onViewReadOnly:c,onResumeEditing:f,isRequesting:d,requestSent:p}){if(i==="poll-ceiling")return e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"edit-lock-banner","data-variant":"poll-ceiling",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Nt,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium text-amber-900",children:"Lock check paused"}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:"Refresh the page to retry."})]})]})});const o=Jt(),y=s?.name||s?.email||"another user";return i==="blocked-edit"?e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"edit-lock-banner","data-variant":"blocked-edit",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Nt,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("p",{className:"font-medium text-amber-900",children:[y," is editing this content"]}),e.jsxs("p",{className:"text-sm text-amber-700 mt-1",children:["Your changes are pending and will be saved when ",y," finishes."]}),e.jsxs("div",{className:"flex flex-wrap gap-2 mt-3 items-center",children:[o&&r&&e.jsx(F,{size:"sm",variant:"outline",onClick:r,disabled:d||p,"data-testid":"request-collaboration-btn",children:p?"Request sent":"Request collaboration"}),l&&e.jsx(F,{size:"sm",variant:"ghost",onClick:l,"data-testid":"discard-pending-btn",children:"Discard pending changes"}),c&&e.jsx(F,{size:"sm",variant:"ghost",onClick:c,"data-testid":"view-read-only-btn",children:"View read-only"}),a&&e.jsx(F,{size:"sm",variant:"destructive",onClick:a,"data-testid":"force-takeover-btn",children:"Take over"})]})]})]})}):e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"edit-lock-banner","data-variant":"read-only-explicit",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Nt,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("p",{className:"font-medium text-amber-900",children:["Editing: ",y]}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:o?"This content is being edited. You can view it read-only or ask to collaborate.":"This content is being edited. You can view it read-only until the editor is finished."}),e.jsxs("div",{className:"flex gap-2 mt-3",children:[o&&r&&e.jsx(F,{size:"sm",variant:"outline",onClick:r,disabled:d||p,"data-testid":"request-collaboration-btn",children:p?"Request sent":"Request collaboration"}),f&&e.jsx(F,{size:"sm",variant:"ghost",onClick:f,"data-testid":"resume-editing-btn",children:"Resume editing"})]})]})]})})}const js={serverUnreachable:"We can't reach the server — your changes are kept here and will save when we're back online.",deviceOffline:"Your device is offline — your changes are kept here and will save when we're back online."};function or({status:i}){if(i.kind===null)return null;const s=i.isDeviceOffline?js.deviceOffline:js.serverUnreachable,a=i.retryAttempt>=1?`Attempt ${i.retryAttempt+1} — retrying…`:null;return e.jsx("div",{className:"bg-amber-50 border border-amber-200 rounded-lg p-4 mb-4","data-testid":"network-status-banner","data-kind":i.kind,role:"status","aria-live":"polite",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Zn,{className:"h-5 w-5 text-amber-600 mt-0.5 shrink-0"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"font-medium text-amber-900",children:s}),a&&e.jsx("p",{className:"text-sm text-amber-700 mt-1","data-testid":"network-status-retry",children:a})]})]})})}const Ss={kind:null,retryAttempt:0,isDeviceOffline:!1};function dr(){const[i,s]=t.useState(Ss),r=t.useRef(!1),a=t.useCallback(c=>{const f=c.kind==="network"?"offline":c.kind;r.current=!0,s({kind:f,retryAttempt:c.retryAttempt,isDeviceOffline:typeof navigator<"u"&&navigator.onLine===!1})},[]),l=t.useCallback(()=>{r.current&&(r.current=!1,s(Ss),J.success("Reconnected",{description:"Your changes are saving again.",duration:3e3}))},[]);return{status:i,onNetworkError:a,onSaveSuccess:l}}function ur({open:i,trigger:s,updatedBy:r,updatedAt:a,onReload:l,onCancel:c}){const f=a>0?ct(a):"just now";return e.jsx(_s,{open:i,children:e.jsxs($s,{"data-testid":"stale-reload-modal","data-trigger":s,onEscapeKeyDown:d=>d.preventDefault(),children:[e.jsxs(Vs,{children:[e.jsx(Ms,{children:"This content was updated"}),e.jsx(Hs,{children:s==="save-conflict"?e.jsxs(e.Fragment,{children:["Your save couldn't go through —"," ",e.jsx("strong",{"data-testid":"stale-reload-updated-by",children:r})," ",e.jsxs("span",{className:"text-muted-foreground","data-testid":"stale-reload-updated-at",children:["(",f,")"]})," ","updated this content since you started editing. Reload to see the latest version (your unsaved changes will be lost), or cancel to keep your edits —"," ",e.jsx("strong",{children:"your next save will overwrite the other version"}),"."]}):e.jsxs(e.Fragment,{children:["This content was updated by"," ",e.jsx("strong",{"data-testid":"stale-reload-updated-by",children:r})," ",e.jsxs("span",{className:"text-muted-foreground","data-testid":"stale-reload-updated-at",children:["(",f,")"]})," ","while this tab was inactive. Reload to see the latest version (your unsaved changes will be lost), or cancel to keep editing your version — the next save will be rejected if it conflicts."]})})]}),e.jsxs(Js,{children:[e.jsx(zs,{onClick:c,"data-testid":"stale-reload-cancel-btn",children:"Cancel"}),e.jsx(Ks,{onClick:l,"data-testid":"stale-reload-reload-btn",children:"Reload"})]})]})})}function hr({lines:i}){return e.jsx("div",{className:"font-mono text-sm leading-relaxed",children:i.map((s,r)=>e.jsx("div",{style:{paddingLeft:`${s.indent*1.5}rem`},className:mt("min-h-[1.5em]",s.type==="label"&&"text-muted-foreground font-semibold mt-1",s.type==="heading"&&"font-bold",s.type==="empty"&&"h-2"),children:s.text},r))})}function $t(i){switch(i.kind){case"draft":return"Draft";case"published":return"Published";case"history":return Ne(i.createdAt)}}function ht(i){switch(i.kind){case"draft":return"draft";case"published":return"published";case"history":return`history:${i.blockId}`}}function ws({value:i,onChange:s,isPublished:r,versions:a,exclude:l,size:c}){const f=l?ht(l):null;function d(p){if(p==="draft")s({kind:"draft"});else if(p==="published")s({kind:"published"});else if(p.startsWith("history:")){const o=p.slice(8),y=a.find(x=>x.blockId===o);y&&s({kind:"history",blockId:y.blockId,createdAt:y.createdAt,title:y.title})}}return e.jsxs(ja,{value:ht(i),onValueChange:d,children:[e.jsx(Sa,{size:c,children:e.jsx(wa,{children:$t(i)})}),e.jsxs(Ca,{position:"popper",children:[f!=="draft"&&e.jsx(Dt,{value:"draft",children:"Draft"}),r&&f!=="published"&&e.jsx(Dt,{value:"published",children:"Published"}),a.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(Ra,{}),e.jsxs(Na,{children:[e.jsx(Aa,{children:"Version History"}),a.map(p=>{const o=`history:${p.blockId}`;return o===f?null:e.jsx(Dt,{value:o,children:Ne(p.createdAt)},o)})]})]})]})]})}function Cs({ref:i,host:s,contentId:r,collectionFields:a,isSingleton:l,draftBody:c,draftMetadata:f,collectionRelationships:d,draftRelationships:p}){const o=i?.kind==="published",y=i?.kind==="history",x=y?i.blockId:null,{data:R,isLoading:P}=Es(s,r,o),{data:j,isLoading:O}=Hn(s,r,y?x:null),A=t.useMemo(()=>(d??[]).map(S=>({name:S.name,label:S.label})),[d]);function D(S){if(A.length!==0)return{defs:A,values:S??{}}}const v=t.useMemo(()=>{if(!i)return[];if(i.kind==="draft")return c?Me(a,c,l?void 0:f,D(p)):[];if(i.kind==="published"){if(!R)return[];const B=l?void 0:{title:R.title,slug:R.slug,snippet:R.snippet,tags:R.tags},q=R.relationships;return Me(a,R.fields??{},B,D(q))}if(!j)return[];const S=l?void 0:{title:j.title,slug:j.slug,snippet:j.snippet,tags:j.tags},L=j.relationships;return Me(a,j.body??{},S,D(L))},[i,c,f,p,R,j,a,l,A]);return i?i.kind==="draft"?{lines:v,isLoading:!1,hasData:!!c}:i.kind==="published"?{lines:v,isLoading:P,hasData:!!R}:{lines:v,isLoading:O,hasData:!!j}:{lines:[],isLoading:!1,hasData:!1}}function fr({open:i,onOpenChange:s,host:r,contentId:a,collectionFields:l,isSingleton:c,isPublished:f,draftBody:d,draftMetadata:p,initialVersion:o,collectionRelationships:y,draftRelationships:x}){const[R,P]=t.useState(o??{kind:"published"}),[j,O]=t.useState({kind:"draft"}),[A,D]=t.useState(i),[v,S]=t.useState(o);if((i!==A||o!==v)&&(D(i),S(o),i)){const E=o??{kind:"published"};P(E),O(E.kind==="draft"?{kind:"published"}:{kind:"draft"})}ht(R)===ht(j)&&(R.kind!=="draft"?O({kind:"draft"}):f&&O({kind:"published"}));const{data:L}=Ps(r,a),B=L?.items??[],q={host:r,contentId:a,collectionFields:l,isSingleton:c,draftBody:d,draftMetadata:p,collectionRelationships:y,draftRelationships:x},U=Cs({ref:i?R:null,...q}),X=Cs({ref:i?j:null,...q}),T=U.isLoading;return e.jsx(ea,{open:i,onOpenChange:s,children:e.jsxs(ta,{className:"w-[calc(100vw-2rem)] sm:max-w-2xl overflow-y-auto pt-[env(safe-area-inset-top,0px)] pr-[env(safe-area-inset-right,0px)]",children:[e.jsx(sa,{children:e.jsxs(na,{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-muted-foreground text-sm font-normal",children:"Viewing"}),e.jsx(ws,{value:R,onChange:P,isPublished:f,versions:B,size:"sm"})]})}),T&&e.jsxs("div",{className:"space-y-4 p-4",children:[e.jsx(ve,{className:"h-6 w-48"}),e.jsx(ve,{className:"h-4 w-full"}),e.jsx(ve,{className:"h-4 w-full"}),e.jsx(ve,{className:"h-4 w-2/3"})]}),!T&&!U.hasData&&e.jsx("p",{className:"p-4 text-sm text-muted-foreground",children:"No data available for this version."}),!T&&U.hasData&&e.jsx("div",{className:"p-4",children:e.jsxs(Ts,{defaultValue:"changes",children:[e.jsxs(Is,{variant:"line",className:"mb-4",children:[e.jsx(ot,{value:"content",children:"Content"}),e.jsx(ot,{value:"changes",children:"Changes"})]}),e.jsx(dt,{value:"content",children:e.jsx(hr,{lines:U.lines})}),e.jsxs(dt,{value:"changes",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[e.jsx("span",{className:"text-sm text-muted-foreground",children:"Compare with"}),e.jsx(ws,{value:j,onChange:O,isPublished:f,versions:B,exclude:R,size:"sm"})]}),X.isLoading?e.jsxs("div",{className:"space-y-4",children:[e.jsx(ve,{className:"h-4 w-full"}),e.jsx(ve,{className:"h-4 w-full"}),e.jsx(ve,{className:"h-4 w-2/3"})]}):X.hasData?e.jsx(ya,{left:X.lines,right:U.lines,leftLabel:$t(j),rightLabel:$t(R)}):e.jsx("p",{className:"text-sm text-muted-foreground italic",children:"No data available for comparison."})]})]})})]})})}const It=3e4;class mr extends Va{constructor(s){super(),this.doc=s,this.clientID=s.clientID,this.states=new Map,this.meta=new Map,this._checkInterval=setInterval(()=>{const r=ut();this.getLocalState()!==null&&It/2<=r-this.meta.get(this.clientID).lastUpdated&&this.setLocalState(this.getLocalState());const a=[];this.meta.forEach((l,c)=>{c!==this.clientID&&It<=r-l.lastUpdated&&this.states.has(c)&&a.push(c)}),a.length>0&&pr(this,a,"timeout")},Ma(It/10)),s.on("destroy",()=>{this.destroy()}),this.setLocalState({})}destroy(){this.emit("destroy",[this]),this.setLocalState(null),super.destroy(),clearInterval(this._checkInterval)}getLocalState(){return this.states.get(this.clientID)||null}setLocalState(s){const r=this.clientID,a=this.meta.get(r),l=a===void 0?0:a.clock+1,c=this.states.get(r);s===null?this.states.delete(r):this.states.set(r,s),this.meta.set(r,{clock:l,lastUpdated:ut()});const f=[],d=[],p=[],o=[];s===null?o.push(r):c==null?s!=null&&f.push(r):(d.push(r),Xs(c,s)||p.push(r)),(f.length>0||p.length>0||o.length>0)&&this.emit("change",[{added:f,updated:p,removed:o},"local"]),this.emit("update",[{added:f,updated:d,removed:o},"local"])}setLocalStateField(s,r){const a=this.getLocalState();a!==null&&this.setLocalState({...a,[s]:r})}getStates(){return this.states}}const pr=(i,s,r)=>{const a=[];for(let l=0;l<s.length;l++){const c=s[l];if(i.states.has(c)){if(i.states.delete(c),c===i.clientID){const f=i.meta.get(c);i.meta.set(c,{clock:f.clock+1,lastUpdated:ut()})}a.push(c)}}a.length>0&&(i.emit("change",[{added:[],updated:[],removed:a},r]),i.emit("update",[{added:[],updated:[],removed:a},r]))},Rs=(i,s,r=i.states)=>{const a=s.length,l=Ka();Et(l,a);for(let c=0;c<a;c++){const f=s[c],d=r.get(f)||null,p=i.meta.get(f).clock;Et(l,f),Et(l,p),Ha(l,JSON.stringify(d))}return Ja(l)},gr=(i,s,r)=>{const a=Ya(s),l=ut(),c=[],f=[],d=[],p=[],o=Pt(a);for(let y=0;y<o;y++){const x=Pt(a);let R=Pt(a);const P=JSON.parse(za(a)),j=i.meta.get(x),O=i.states.get(x),A=j===void 0?0:j.clock;(A<R||A===R&&P===null&&i.states.has(x))&&(P===null?x===i.clientID&&i.getLocalState()!=null?R++:i.states.delete(x):i.states.set(x,P),i.meta.set(x,{clock:R,lastUpdated:l}),j===void 0&&P!==null?c.push(x):j!==void 0&&P===null?p.push(x):P!==null&&(Xs(P,O)||d.push(x),f.push(x)))}(c.length>0||d.length>0||p.length>0)&&i.emit("change",[{added:c,updated:d,removed:p},r]),(c.length>0||f.length>0||p.length>0)&&i.emit("update",[{added:c,updated:f,removed:p},r])},Ns=[1e3,2e3,4e3,8e3,16e3];class zt{awareness;ws=null;doc;room;wsUrl;ticket;getTicket;reconnectAttempt=0;reconnectTimer=null;connected=!1;destroyed=!1;pendingUpdates=[];pendingFieldUpdates=[];static MAX_PENDING_FIELD_UPDATES=100;statusListeners=new Set;constructor(s){this.doc=s.doc,this.room=s.room,this.wsUrl=s.wsUrl,this.ticket=s.ticket,this.getTicket=s.getTicket,this.awareness=new mr(this.doc),this.awareness.setLocalStateField("user",s.user),this.doc.on("update",this.handleDocUpdate),this.awareness.on("update",this.handleAwarenessUpdate),this.connect()}onStatus(s){return this.statusListeners.add(s),()=>{this.statusListeners.delete(s)}}connect(){if(this.destroyed)return;this.statusListeners.forEach(r=>r("connecting"));const s=`${this.wsUrl}?ticket=${encodeURIComponent(this.ticket)}&room=${encodeURIComponent(this.room)}`;this.ws=new WebSocket(s),this.ws.onopen=()=>{this.connected=!0,this.reconnectAttempt=0,this.statusListeners.forEach(l=>l("connected"));const r=Qa(this.doc);this.ws.send(JSON.stringify({action:"yjs",type:"sync-step-1",data:_e(r)}));const a=Rs(this.awareness,[this.doc.clientID]);this.ws.send(JSON.stringify({action:"awareness",data:_e(a)}))},this.ws.onmessage=r=>{const a=JSON.parse(r.data);switch(a.action){case"yjs":this.handleYjsMessage(a);break;case"field":this.fieldListeners.forEach(l=>l(a));break;case"awareness":this.handleAwarenessMessage(a);break;case"presence":this.presenceListeners.forEach(l=>l(a));break;case"leader-change":this.leaderChangeListeners.forEach(l=>l(a));break;case"collaboration-disabled":this.collabDisabledListeners.forEach(l=>l());break;case"publish-requested":this.publishRequestedListeners.forEach(l=>l(a));break;case"save-version-requested":this.saveVersionRequestedListeners.forEach(l=>l(a));break;case"publish-in-progress":this.publishInProgressListeners.forEach(l=>l());break;case"published":this.publishedListeners.forEach(l=>l(a));break}},this.ws.onclose=()=>{this.connected=!1,this.statusListeners.forEach(r=>r("disconnected")),this.scheduleReconnect()},this.ws.onerror=()=>{this.ws?.close()}}handleDocUpdate=(s,r)=>{r!=="remote"&&(this.connected?this.sendYjsUpdate(s):this.pendingUpdates.push(s))};sendYjsUpdate(s){this.ws?.send(JSON.stringify({action:"yjs",type:"update",data:_e(s)}))}flushPendingUpdates(){for(const s of this.pendingUpdates)this.sendYjsUpdate(s);this.pendingUpdates=[]}handleYjsMessage(s){const r=As(s.data);switch(s.type){case"sync-step-1":{const a=Wa(this.doc,r);this.ws.send(JSON.stringify({action:"yjs",type:"sync-step-2",data:_e(a)}));break}case"sync-step-2":vs(this.doc,r,"remote"),this.flushPendingUpdates(),this.flushPendingFieldUpdates();break;case"update":vs(this.doc,r,"remote");break}}fieldListeners=new Set;onFieldUpdate(s){return this.fieldListeners.add(s),()=>{this.fieldListeners.delete(s)}}sendFieldUpdate(s,r){if(!this.connected){const a=this.pendingFieldUpdates.findIndex(l=>l.field===s);a>=0?this.pendingFieldUpdates[a]={field:s,value:r}:(this.pendingFieldUpdates.length>=zt.MAX_PENDING_FIELD_UPDATES&&this.pendingFieldUpdates.shift(),this.pendingFieldUpdates.push({field:s,value:r}));return}this.ws?.send(JSON.stringify({action:"field",field:s,value:r}))}flushPendingFieldUpdates(){for(const{field:s,value:r}of this.pendingFieldUpdates)this.ws?.send(JSON.stringify({action:"field",field:s,value:r}));this.pendingFieldUpdates=[]}presenceListeners=new Set;onPresence(s){return this.presenceListeners.add(s),()=>{this.presenceListeners.delete(s)}}leaderChangeListeners=new Set;onLeaderChange(s){return this.leaderChangeListeners.add(s),()=>{this.leaderChangeListeners.delete(s)}}collabDisabledListeners=new Set;onCollabDisabled(s){return this.collabDisabledListeners.add(s),()=>{this.collabDisabledListeners.delete(s)}}sendDisableCollab(){this.connected&&this.ws?.send(JSON.stringify({action:"disable-collab"}))}publishRequestedListeners=new Set;onPublishRequested(s){return this.publishRequestedListeners.add(s),()=>{this.publishRequestedListeners.delete(s)}}saveVersionRequestedListeners=new Set;onSaveVersionRequested(s){return this.saveVersionRequestedListeners.add(s),()=>{this.saveVersionRequestedListeners.delete(s)}}publishInProgressListeners=new Set;onPublishInProgress(s){return this.publishInProgressListeners.add(s),()=>{this.publishInProgressListeners.delete(s)}}publishedListeners=new Set;onPublished(s){return this.publishedListeners.add(s),()=>{this.publishedListeners.delete(s)}}sendRequestPublish(){this.connected&&this.ws?.send(JSON.stringify({action:"request-publish"}))}sendRequestSaveVersion(){this.connected&&this.ws?.send(JSON.stringify({action:"request-save-version"}))}sendPublishInProgress(){this.connected&&this.ws?.send(JSON.stringify({action:"publish-in-progress"}))}sendPublished(s){this.connected&&this.ws?.send(JSON.stringify({action:"published",...s?.contentId?{contentId:s.contentId}:{},...s?.version!==void 0?{version:s.version}:{}}))}handleAwarenessUpdate=({added:s,updated:r,removed:a})=>{if(!this.connected)return;const l=Rs(this.awareness,[...s,...r,...a]);this.ws?.send(JSON.stringify({action:"awareness",data:_e(l)}))};handleAwarenessMessage(s){const r=As(s.data);gr(this.awareness,r,"remote")}scheduleReconnect(){if(this.destroyed)return;const s=Ns[Math.min(this.reconnectAttempt,Ns.length-1)];this.reconnectAttempt++,this.reconnectTimer=window.setTimeout(async()=>{try{this.ticket=await this.getTicket()}catch{this.statusListeners.forEach(r=>r("disconnected"));return}this.connect()},s)}destroy(){this.destroyed=!0,this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.doc.off("update",this.handleDocUpdate),this.awareness.off("update",this.handleAwarenessUpdate),this.awareness.destroy(),this.ws?.close()}}function _e(i){let s="";for(let a=0;a<i.length;a+=8192)s+=String.fromCharCode(...i.subarray(a,a+8192));return btoa(s)}function As(i){const s=atob(i),r=new Uint8Array(s.length);for(let a=0;a<s.length;a++)r[a]=s.charCodeAt(a);return r}const it=["#3b82f6","#ef4444","#10b981","#f59e0b","#8b5cf6","#ec4899","#14b8a6","#f97316"];function br(i,s,r,a){const{user:l}=Ht(),[c,f]=t.useState(null),[d,p]=t.useState("disconnected"),[o,y]=t.useState([]),[x,R]=t.useState({}),P=t.useRef(null),j=t.useRef(a?.onCollabDisabled),O=t.useRef(a?.onPublishRequested),A=t.useRef(a?.onSaveVersionRequested),D=t.useRef(a?.onPublishInProgress),v=t.useRef(a?.onPublished);t.useEffect(()=>{j.current=a?.onCollabDisabled,O.current=a?.onPublishRequested,A.current=a?.onSaveVersionRequested,D.current=a?.onPublishInProgress,v.current=a?.onPublished},[a?.onCollabDisabled,a?.onPublishRequested,a?.onSaveVersionRequested,a?.onPublishInProgress,a?.onPublished]);const S="__HEADROOM_COLLAB_WS_URL__",L=Jt(),B=L&&!!c&&d==="connected";t.useEffect(()=>{if(!L||!S||!l||!r)return;const w=new Ga;P.current=w;const $=`${i}/${s}`,u=async()=>{const Y=Mt();if(!Y)throw new Error("No access token");const ue="__HEADROOM_API_URL__".replace(/\/+$/,""),z=await fetch(`${ue}/v1/admin/sites/${i}/content/${s}/collab/ticket`,{method:"POST",headers:{Authorization:`Bearer ${Y}`,"Content-Type":"application/json"},body:JSON.stringify({room:$})});if(!z.ok)throw new Error(`Ticket request failed: ${z.status}`);return(await z.json()).ticket};let m=!1,H=null;return u().then(Y=>{if(m)return;const ue=Ds(l.sub)%it.length;H=new zt({wsUrl:S,room:$,ticket:Y,getTicket:u,doc:w,user:{sub:l.sub,name:l.name||l.email,color:it[ue]}}),H.onStatus(p),H.onPresence(z=>{y(z.connections.filter(te=>te.connectionId!==z.youAre).map(te=>({sub:te.adminSub,name:te.adminName,color:te.color})));const pe=z.connections.find(te=>te.connectionId===z.youAre);_(pe?.isLeader??!1)}),H.onCollabDisabled(()=>{j.current?.()}),H.onPublishRequested(()=>O.current?.()),H.onSaveVersionRequested(()=>A.current?.()),H.onPublishInProgress(()=>D.current?.()),H.onPublished(z=>v.current?.({contentId:z.contentId,version:z.version})),f(H)}).catch(()=>{m||p("disconnected")}),()=>{m=!0,H?.destroy(),w.destroy(),f(null),p("disconnected")}},[i,s,l?.sub,r,S]);const q=t.useCallback(w=>{if(!c||!l||!P.current)return;const $=P.current.getXmlFragment(`document-store-${w}`),u=Ds(l.sub)%it.length;return{provider:c,fragment:$,user:{name:l.email,color:it[u]}}},[c,l]);t.useEffect(()=>{if(!c){R({});return}const w=()=>{const $={};c.awareness.getStates().forEach(m=>{const H=m?.user?.sub;if(!H)return;const Y=m.activeField??null;$[H]=Y}),R($)};return w(),c.awareness.on("change",w),()=>{c.awareness.off("change",w)}},[c]);const U=t.useMemo(()=>o.map(w=>({...w,activeField:x[w.sub]??null})),[o,x]),X=t.useCallback(w=>{c&&c.awareness.setLocalStateField("activeField",w)},[c]),T=t.useRef(new Set),E=t.useCallback(w=>(T.current.add(w),()=>{T.current.delete(w)}),[]);t.useEffect(()=>{if(c)return c.onFieldUpdate(w=>{T.current.forEach($=>$(w.field,w.value))})},[c]);const ne=t.useCallback((w,$)=>{c?.sendFieldUpdate(w,$)},[c]),ae=t.useCallback(()=>{c?.sendDisableCollab()},[c]),se=t.useCallback(()=>{c?.sendRequestPublish()},[c]),M=t.useCallback(()=>{c?.sendRequestSaveVersion()},[c]),re=t.useCallback(()=>{c?.sendPublishInProgress()},[c]),G=t.useCallback(w=>{c?.sendPublished(w)},[c]),[Z,_]=t.useState(!1);return t.useEffect(()=>{if(c)return c.onLeaderChange(w=>{_(w.leaderSub===l?.sub)})},[c,l]),{active:B,status:d,editors:U,isLeader:Z,getBlockNoteCollab:q,updateField:ne,onRemoteFieldChange:E,setActiveField:X,sendDisableCollab:ae,sendRequestPublish:se,sendRequestSaveVersion:M,sendPublishInProgress:re,sendPublished:G}}function Ds(i){let s=0;for(let r=0;r<i.length;r++)s=(s<<5)-s+i.charCodeAt(r)|0;return Math.abs(s)}function xr({status:i,editors:s}){return s.length===0&&i==="connected"?null:e.jsxs("div",{className:"flex items-center gap-2 px-3 py-1.5 bg-muted/50 rounded-md text-sm","data-testid":"collaboration-bar",children:[e.jsxs("div",{className:"flex items-center gap-1.5","aria-label":i,children:[e.jsx("span",{"data-testid":"collaboration-bar-status-dot","data-status":i,className:mt("h-2 w-2 rounded-full",i==="connected"&&"bg-green-500",i==="connecting"&&"bg-yellow-500 animate-pulse",i==="disconnected"&&"bg-red-500")}),e.jsx("span",{className:"text-muted-foreground text-xs",children:i==="connected"?"Live":i==="connecting"?"Connecting...":"Offline"})]}),s.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(Us,{orientation:"vertical",className:"h-4"}),e.jsx("div",{className:"flex -space-x-1.5",children:s.map(r=>e.jsxs(Fs,{children:[e.jsx(Os,{asChild:!0,children:e.jsx(Ia,{className:"h-6 w-6 border-2",style:{borderColor:r.color},"aria-label":r.name,children:e.jsx(Ua,{className:"text-[10px]",style:{backgroundColor:r.color+"20"},children:Fa(r.name)})})}),e.jsx(Bs,{children:r.name})]},r.sub))}),e.jsxs("span",{className:"text-muted-foreground text-xs",children:[s.length," other ",s.length===1?"editor":"editors"]})]})]})}function vr({host:i,contentId:s,collaborationEnabled:r,hasConnectedPeers:a,isLockHolder:l,sessionId:c,onChange:f,onBeforeDisable:d}){const[p,o]=t.useState(!1),y=ft();if(!Jt()||!l)return null;const x=async()=>{const A=!r;o(!0);try{if(!A)try{d?.()}catch{}await y.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock/collaboration`,{method:"POST",body:JSON.stringify({collaborationEnabled:A,sessionId:c})}),f(A)}catch{J.error("Failed to update collaboration setting")}finally{o(!1)}},R=r&&a,P=p||R,j=R?"Cannot stop sharing while other editors are connected":null,O=e.jsxs(F,{variant:r?"default":"outline",size:"sm",disabled:P,onClick:x,"aria-pressed":r,children:[r?e.jsx(aa,{className:"h-4 w-4"}):e.jsx(ra,{className:"h-4 w-4"}),r?"Collaborating":"Collaborate"]});return j?e.jsxs(Fs,{children:[e.jsx(Os,{asChild:!0,children:O}),e.jsx(Bs,{children:j})]}):O}function yr(i,s,r,a,l){const c=t.useRef(new Set),f=ft();t.useEffect(()=>{const d=new Set(a.map(p=>p.sub));for(const p of Array.from(c.current))d.has(p)||c.current.delete(p)},[a]),t.useEffect(()=>{for(const d of a){if(c.current.has(d.sub))continue;c.current.add(d.sub);const p=d.name||d.email||"Someone";J(`${p} wants to collaborate`,{action:{label:"Allow",onClick:()=>{f.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock/collaboration`,{method:"POST",body:JSON.stringify({collaborationEnabled:!0,sessionId:r})}).then(()=>l()).catch(()=>J.error("Failed to enable collaboration"))}},cancel:{label:"Decline",onClick:()=>{f.apiFetch(`/v1/admin/sites/${i}/content/${s}/edit-lock/access-requests/${d.sub}?sessionId=${r}`,{method:"DELETE"}).catch(()=>J.error("Failed to decline request"))}},duration:1/0})}},[a,i,s,r,l,f])}function ti(){const{host:i,collection:s,id:r}=qn(),{data:a,isLoading:l}=Jn(i,r);return l?e.jsxs("div",{className:"space-y-4",children:[e.jsx(ve,{className:"h-8 w-64"}),e.jsx(ve,{className:"h-64 w-full"})]}):a?.content?e.jsx(kr,{host:i,collection:s,contentId:r,content:a.content,draft:a.draft,publishedBlockId:a.publishedBlockId}):e.jsx("p",{className:"text-muted-foreground",children:"Content not found."})}function kr({host:i,collection:s,contentId:r,content:a,draft:l,publishedBlockId:c}){const f=_n(),d=ft(),p=Vt(),{collections:o}=ia(),y=zn(i,r),x=Kn(i,r),R=Yn(i,r),P=Qn(i,r),j=Wn(i,r),O=Gn(i,r),A=l?{title:l.title??a.title,slug:l.slug??a.slug??"",snippet:l.snippet??a.snippet??"",tags:l.tags??a.tags??[],cover:l.cover??a.cover??null,body:l.body??{},relationships:l.relationships??{}}:void 0,{user:D}=Ht(),{data:v}=la(),S=D?(v?.superAdminIds??[]).includes(D.sub):!1,L=t.useRef(null),B=t.useCallback(async()=>{const n=L.current;return n?n():{ok:!0}},[]),q=typeof l?.updatedAt=="number"?l.updatedAt:0,[U,X]=t.useState(q),T=t.useRef(q),E=t.useCallback(n=>{T.current=n,X(n)},[]),ne=t.useCallback(()=>T.current,[]),ae=t.useRef(()=>{}),se=t.useRef(()=>{}),[M,re]=t.useState(!1),G=t.useRef(!1),Z=t.useRef(!1),_=t.useRef(()=>!1),w=t.useRef(()=>!1),$=t.useRef(null),u=lr(i,r,{getIsDirty:()=>_.current()||G.current,getIsSaving:()=>Z.current,getIsSavingSync:()=>w.current(),onIdleRelease:()=>$.current?.(),onLockAcquired:n=>{typeof n=="number"&&n>0&&E(n)}}),m=br(i,r,u.collaborationEnabled,{onCollabDisabled:()=>u.setCollaborationEnabled(!1),onPublishRequested:()=>ae.current(),onSaveVersionRequested:()=>se.current(),onPublishInProgress:()=>re(!0),onPublished:()=>{re(!1),J.success("Content published")}}),[H,Y]=t.useState(null),ue=m.active?1e4:void 0,z=dr(),pe=t.useCallback(n=>{const g=n,W=(g?.accessRequests??[]).filter(xe=>xe.sub!==D?.sub);u.setAccessRequests(W),typeof g?.updatedAt=="number"&&(E(g.updatedAt),jt(!1)),z.onSaveSuccess()},[u,D?.sub,E,z]),te=t.useRef(null),Oe=t.useCallback(()=>{te.current?.()},[]),Ae=t.useRef(null),Be=t.useCallback(()=>Ae.current?.()??{},[]),b=tr(i,r,A,()=>{Y("This slug is already in use by another item in this collection")},n=>{u.onAutosaveConflict({lockHolder:n.body?.lockHolder??void 0,takeoverReason:n.body?.takeoverReason??"expired"})},ue,pe,{onBeforeFirstSave:B,onStaleBaseConflict:Oe,getCurrentParams:Be,getBaseUpdatedAt:ne,onNetworkError:z.onNetworkError});L.current=u.tryAcquireForEdit,G.current=b.isDirty,Z.current=b.isSaving,_.current=b.getHasPending,w.current=b.getIsSavingSync,$.current=b.markLockReleased;const N=u.bumpIdleTimer;t.useEffect(()=>{b.lastSavedAt!=null&&N()},[b.lastSavedAt,N]);const k=(u.status==="blocked-edit"||u.status==="read-only-explicit"||u.status==="stale-reload-pending"||u.status==="poll-ceiling")&&!u.collaborationEnabled;yr(i,r,u.sessionId,u.accessRequests,()=>u.setCollaborationEnabled(!0));const{data:K}=Ea(i),ce=K?.map(n=>n.tag),Q=o.find(n=>n.name===s),h=t.useMemo(()=>Q?.fields??[],[Q?.fields]),I=t.useMemo(()=>Q?.relationships??[],[Q?.relationships]),C=Q?.singleton??!1,he=ca(),[ee,De]=t.useState(l?.title??a.title),[fe,Ee]=t.useState(l?.slug??a.slug??""),[me,Pe]=t.useState(l?.snippet??a.snippet??""),Kt=l?.autoSnippet??"",[ye,Le]=t.useState(l?.tags??a.tags??[]),[oe,Te]=t.useState(l?.cover??a.cover??null),[ke,Ie]=t.useState(l?.body??{}),[je,Ue]=t.useState(l?.relationships??{}),[Zs,pt]=t.useState(0),[en,tn]=t.useState(!1),[sn,He]=t.useState(!1),[nn,qe]=t.useState(!1),[an,Je]=t.useState(null),[gt,ze]=t.useState(!1),[rn,Ke]=t.useState(!1),[ln,Ye]=t.useState(!1),[Qe,Yt]=t.useState(""),[cn,bt]=t.useState(!1),[xt,Qt]=t.useState(""),Wt=Xn(i,r),ie=t.useCallback(()=>({title:ee,slug:fe,snippet:me,tags:ye,cover:oe,body:ke,relationships:je,...u.sessionId?{sessionId:u.sessionId}:{}}),[ee,fe,me,ye,oe,ke,je,u.sessionId]);t.useEffect(()=>{Ae.current=ie},[ie]);const on=m.active?n=>{De(n),m.updateField("title",n)}:n=>{De(n),b.schedule({...ie(),title:n})},dn=m.active?n=>{Ee(n),Y(null),m.updateField("slug",n)}:n=>{Ee(n),Y(null),b.schedule({...ie(),slug:n})},un=m.active?n=>{Pe(n),m.updateField("snippet",n)}:n=>{Pe(n),b.schedule({...ie(),snippet:n})},hn=m.active?n=>{Le(n),m.updateField("tags",n)}:n=>{Le(n),b.schedule({...ie(),tags:n})},Gt=m.active?n=>{Te(n),m.updateField("cover",n)}:n=>{Te(n),b.schedule({...ie(),cover:n})},fn=m.active?n=>{Ie(n),m.updateField("body",n)}:n=>{Ie(n),b.schedule({...ie(),body:n})},mn=m.active?n=>{Ue(n),m.updateField("relationships",n)}:n=>{Ue(n),b.schedule({...ie(),relationships:n})},We=m.active,Ge=m.setActiveField,vt=t.useCallback(n=>{We&&Ge(n)},[We,Ge]),yt=t.useCallback(()=>{We&&Ge(null)},[We,Ge]);t.useEffect(()=>{if(m.active)return m.onRemoteFieldChange((n,g)=>{switch(n){case"title":De(g);break;case"slug":Ee(g);break;case"snippet":Pe(g);break;case"tags":Le(g);break;case"cover":Te(g);break;case"body":Ie(g);break;case"relationships":Ue(g);break}m.isLeader&&b.schedule(ie())})},[m.active,m.onRemoteFieldChange,m.isLeader]);const Xt=m.active?m.isLeader:!0;t.useEffect(()=>{if(!m.active||!Xt)return;b.schedule(ie());const n=window.setInterval(()=>{b.schedule(ie())},1e4);return()=>window.clearInterval(n)},[Xt,m.active]);const Zt=b.lastSavedBlockId??l?.blockId,Re=t.useCallback(n=>{const g=n.draft,V=n.content;if(!g&&!V)return;const W={title:g?.title??V?.title??"",slug:g?.slug??V?.slug??"",snippet:g?.snippet??V?.snippet??"",tags:g?.tags??V?.tags??[],cover:g?.cover??V?.cover??null,body:g?.body??{},relationships:g?.relationships??{}};De(W.title),Ee(W.slug),Pe(W.snippet),Le(W.tags),Te(W.cover),Ie(W.body),Ue(W.relationships);const xe=g?.updatedAt??0;E(xe),b.resetBaseline(W),pt(Ct=>Ct+1)},[b,E]),[le,kt]=t.useState(null),pn=t.useMemo(()=>le?.updatedBy?[le.updatedBy]:[],[le?.updatedBy]),{resolve:es}=Ys(pn),gn=t.useMemo(()=>{const n=le?.updatedBy??"";if(!n)return"another admin";const g=es(n);return!g||g===n?"another admin":g},[le?.updatedBy,es]),[bn,jt]=t.useState(!1),Xe=t.useRef(null),ts=u.setStaleReloadPending,Ze=t.useCallback((n,g)=>{b.pause(),Xe.current={title:ee,slug:fe,snippet:me,tags:ye,cover:oe,body:ke,relationships:je};const V=n.draft?.updatedAt??0,W=n.draft?.updatedBy??"";kt({trigger:g,updatedBy:W,updatedAt:V,latest:n}),ts()},[b,ts,ee,fe,me,ye,oe,ke,je]),et=u.endEditing,xn=t.useCallback(()=>{const n=le;n&&Re(n.latest),Xe.current=null,kt(null),jt(!1),b.resume(),et()},[le,Re,b,et]),ss=u.resumeEditingAfterStale,vn=t.useCallback(()=>{const n=Xe.current,g=le;if(n&&(De(n.title),Ee(n.slug),Pe(n.snippet),Le(n.tags),Te(n.cover),Ie(n.body),Ue(n.relationships),pt(V=>V+1),b.resetBaseline(n),Xe.current=null),g?.trigger==="save-conflict"&&g.latest){const V=g.latest.draft,W=V?.updatedAt,xe=V?.blockId;typeof W=="number"&&W>0&&E(W),typeof xe=="string"&&xe!==""&&b.adoptServerBlockId(xe)}kt(null),jt(!0),b.resume(),ss()},[b,ss,le,E]),Fe=t.useCallback(async()=>(await p.invalidateQueries({queryKey:["sites",i,"content-detail",r]}),p.getQueryData(["sites",i,"content-detail",r])??null),[p,i,r]),yn=t.useCallback(async()=>{b.cancel();const n=await Fe();n&&Re(n),et()},[b,Fe,Re,et]),ns=u.setReadOnlyExplicit,kn=t.useCallback(async()=>{b.cancel();const n=await Fe();n&&Re(n),ns()},[b,Fe,Re,ns]),as=t.useCallback(async()=>{const n=await Fe();n&&Ze(n,"save-conflict")},[Fe,Ze]);t.useEffect(()=>{te.current=()=>void as()},[as]);const jn=t.useCallback(()=>{b.pause()},[b]),Sn=t.useCallback(()=>{b.resume()},[b]),wn=t.useCallback(n=>{Ze(n,"tab-refocus")},[Ze]);cr({host:i,contentId:r,isDirty:b.isDirty,serverBlockId:Zt,serverUpdatedAt:U,onSilentReload:Re,onStaleWithDirty:wn,onTabHidden:jn,onTabVisibleResume:Sn});const ge=qa(a.publishedAt,a.lastPublishedAt,c,Zt,a.scheduledAt,a.scheduledFailed),tt=_a(ge),st=$a(ge),{data:Se}=Es(i,r,!!a.publishedAt),be=t.useMemo(()=>{if(!gt||!Se)return null;const n=C?void 0:{title:Se.title,slug:Se.slug,snippet:Se.snippet,tags:Se.tags},g=I.map(de=>({name:de.name,label:de.label})),V=Se.relationships,W=g.length>0?{defs:g,values:V??{}}:void 0,xe=Me(h,Se.fields??{},n,W),Ct=C?void 0:{title:ee,slug:fe,snippet:me,tags:ye},In=g.length>0?{defs:g,values:je}:void 0,Un=Me(h,ke,Ct,In),Fn=ka(xe,Un,{comparator:(de,Rt)=>de.text===Rt.text&&de.indent===Rt.indent&&de.type===Rt.type});let ls=0,cs=0;for(const de of Fn)de.added?ls+=de.count??0:de.removed&&(cs+=de.count??0);return{added:ls,removed:cs}},[gt,Se,h,I,C,ee,fe,me,ye,ke,je]),[Cn]=$n(),Rn=Cn.get("from")==="recent"?`/sites/${i}/content`:`/sites/${i}/content/${s}`;va({title:C?Q?.label??s:ee||"Untitled",showBack:!C,backTo:C?void 0:Rn,badge:{label:tt.label,variant:tt.variant}});function nt(){if(m.active&&!m.isLeader){m.sendRequestPublish();return}if(a.publishedAt&&a.slug&&fe!==a.slug){Ke(!0);return}ge==="published-changes"?ze(!0):St()}async function St(){m.active&&m.isLeader&&m.sendPublishInProgress();try{await b.flush({createVersion:!0});const g=(await y.mutateAsync(void 0))?.updatedAt;typeof g=="number"&&g>0&&E(g),b.discard(),u.endEditing(),J.success("Content published"),m.active&&m.isLeader&&m.sendPublished({contentId:r})}catch(n){if(n instanceof Ce&&n.code==="SLUG_TAKEN"){Y("This slug is already in use by another item in this collection"),J.error("Slug already in use",{description:"Please choose a different slug before publishing."});return}J.error("Failed to publish",{description:n instanceof Error?n.message:void 0})}finally{}}function Nn(){if(m.active&&!m.isLeader){m.sendRequestSaveVersion();return}b.flush({createVersion:!0})}t.useEffect(()=>{ae.current=nt,se.current=()=>{b.flush({createVersion:!0})}});async function An(){try{const g=(await x.mutateAsync())?.updatedAt;typeof g=="number"&&g>0&&E(g),qe(!1),u.endEditing(),J.success("Content unpublished")}catch(n){J.error("Failed to unpublish",{description:n instanceof Error?n.message:void 0})}}async function Dn(){try{b.discard();const n=await d.apiFetch(`/v1/admin/sites/${i}/content/${r}/published`);await Wt.mutateAsync();const g={title:n.title??"",slug:n.slug??"",snippet:n.snippet??"",tags:n.tags??[],cover:n.cover??null,body:n.fields??{},relationships:n.relationships??{}};De(g.title),Ee(g.slug),Pe(g.snippet),Le(g.tags),Te(g.cover),Ie(g.body),Ue(g.relationships),pt(V=>V+1),b.resetBaseline(g),J.success("Changes discarded")}catch(n){J.error("Failed to discard changes",{description:n instanceof Error?n.message:void 0})}}async function En(){try{await R.mutateAsync(),u.endEditing(),J.success("Content deleted"),f(`/sites/${i}/content/${s}`)}catch(n){J.error("Failed to delete",{description:n instanceof Error?n.message:void 0})}}async function Pn(){if(Qe)try{await b.flush({createVersion:!0});const n=new Date(Qe).getTime(),V=(await j.mutateAsync(n))?.updatedAt;typeof V=="number"&&V>0&&E(V),Ye(!1),Yt(""),u.endEditing(),J.success("Content scheduled for publishing")}catch(n){J.error("Failed to schedule",{description:n instanceof Error?n.message:void 0})}}async function Ln(){try{const g=(await O.mutateAsync())?.updatedAt;typeof g=="number"&&g>0&&E(g),u.endEditing(),J.success("Schedule cancelled")}catch(n){J.error("Failed to cancel schedule",{description:n instanceof Error?n.message:void 0})}}async function Tn(){if(xt)try{const n=new Date(xt).getTime();await P.mutateAsync(n),bt(!1),J.success("Publish date updated")}catch(n){J.error("Failed to update publish date",{description:n instanceof Error?n.message:void 0})}}function wt(n){const g=new Date(n),V=g.getTimezoneOffset();return new Date(g.getTime()-V*6e4).toISOString().slice(0,16)}const rs=e.jsx("div",{className:`space-y-6 ${k?"pointer-events-none opacity-60 select-none":""}`,"aria-readonly":k||void 0,children:h.length>0?e.jsx(Oa,{fields:h,values:ke,onChange:fn},Zs):e.jsx($e,{children:e.jsx(Ve,{className:"py-8 text-center",children:e.jsxs("p",{className:"text-sm text-muted-foreground",children:["No fields defined for this collection."," ",e.jsx(Vn,{to:`/sites/${i}/settings/collections/${s}`,className:"underline",children:"Configure fields"})]})})})}),is=e.jsxs("div",{className:`space-y-6 ${k?"pointer-events-none opacity-60 select-none":""}`,"aria-readonly":k||void 0,children:[!C&&e.jsx($e,{children:e.jsxs(Ve,{className:"space-y-4 pt-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(at,{htmlFor:"title",className:"flex items-center",children:["Title",e.jsx(rt,{field:"title",editors:m.editors})]}),e.jsx(ds,{id:"title",value:ee,onChange:n=>on(n.target.value),onFocus:()=>vt("title"),onBlur:yt})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(at,{htmlFor:"slug",className:"flex items-center",children:["Slug",e.jsx(rt,{field:"slug",editors:m.editors})]}),e.jsx(ds,{id:"slug",value:fe,onChange:n=>dn(n.target.value),onFocus:()=>vt("slug"),onBlur:yt,className:H?"border-destructive":""}),H&&e.jsx("p",{className:"text-sm text-destructive",children:H})]}),e.jsxs(Qs,{defaultOpen:!!me,children:[e.jsxs(Ws,{className:"flex w-full items-center gap-2 text-sm font-medium",children:[e.jsx(qs,{className:"h-4 w-4 transition-transform [[data-state=open]>&]:rotate-90"}),"Snippet",e.jsx("span",{className:"text-xs text-muted-foreground",children:"(auto-generated if empty)"}),e.jsx(rt,{field:"snippet",editors:m.editors})]}),e.jsxs(Gs,{className:"mt-2 space-y-2",children:[e.jsx(Da,{id:"snippet",value:me,onChange:n=>un(n.target.value),onFocus:()=>vt("snippet"),onBlur:yt,rows:3,placeholder:"Brief summary of this content..."}),!me&&Kt&&e.jsxs("p",{className:"text-xs italic text-muted-foreground",children:["Auto-generated: ",Kt]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(at,{children:"Cover Image"}),oe?e.jsxs("div",{className:"flex items-center gap-3 rounded-md border p-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>He(!0),children:[e.jsx("img",{src:La(oe.url),alt:oe.alt??oe.filename??"",className:"h-10 w-10 rounded object-cover bg-muted"}),e.jsx("span",{className:"flex-1 truncate text-sm",children:oe.filename??oe.alt??oe.id}),e.jsx(F,{type:"button",variant:"ghost",size:"sm",onClick:n=>{n.stopPropagation(),Gt(null)},children:e.jsx(us,{className:"h-3 w-3"})})]}):e.jsxs(F,{type:"button",variant:"outline",className:"w-full",onClick:()=>He(!0),children:[e.jsx(oa,{className:"mr-2 h-4 w-4"}),"Select Image"]}),e.jsx(Pa,{open:sn,onClose:()=>He(!1),onSelect:n=>{Gt({id:n.mediaId,url:n.url,width:n.width??0,height:n.height??0,alt:n.alt,caption:n.caption,filename:n.filename}),He(!1)},allowedTypes:["image/*"]})]})]})}),!C&&e.jsxs($e,{children:[e.jsx(bs,{children:e.jsxs(xs,{className:"flex items-center",children:["Tags",e.jsx(rt,{field:"tags",editors:m.editors})]})}),e.jsx(Ve,{children:e.jsx(xa,{tags:ye,onChange:hn,suggestions:ce})})]}),I.length>0&&e.jsx(Ta,{relationships:I,values:je,onChange:mn,host:i}),e.jsxs($e,{children:[e.jsx(bs,{children:e.jsx(xs,{children:"Info"})}),e.jsxs(Ve,{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Collection"}),e.jsx("span",{children:a.collection})]}),e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"ID"}),e.jsx("span",{className:"font-mono text-xs",children:a.contentId})]}),a.publishedAt?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("span",{className:"text-muted-foreground",children:"Published"}),cn?e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("input",{type:"datetime-local",value:xt,onChange:n=>Qt(n.target.value),className:"text-xs border rounded px-1 py-0.5",max:wt(Date.now())}),e.jsx(F,{variant:"ghost",size:"sm",className:"h-6 w-6 p-0",onClick:Tn,disabled:P.isPending,children:e.jsx(hs,{className:"h-3 w-3"})}),e.jsx(F,{variant:"ghost",size:"sm",className:"h-6 w-6 p-0",onClick:()=>bt(!1),children:e.jsx(us,{className:"h-3 w-3"})})]}):e.jsxs("span",{className:"cursor-pointer hover:underline",title:Ne(a.publishedAt),onClick:()=>{Qt(wt(a.publishedAt)),bt(!0)},children:[ct(a.publishedAt),e.jsx(da,{className:"inline ml-1 h-3 w-3 text-muted-foreground"})]})]}),a.lastPublishedAt&&a.lastPublishedAt!==a.publishedAt&&e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Last published"}),e.jsx("span",{title:Ne(a.lastPublishedAt),children:ct(a.lastPublishedAt)})]})]}):a.lastPublishedAt?e.jsxs("div",{className:"flex justify-between",children:[e.jsx("span",{className:"text-muted-foreground",children:"Last published"}),e.jsx("span",{title:Ne(a.lastPublishedAt),children:ct(a.lastPublishedAt)})]}):null,ge==="scheduled"&&a.scheduledAt&&e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("span",{className:"text-muted-foreground",children:"Scheduled for"}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(fs,{className:"h-3 w-3"}),Ne(a.scheduledAt)]})]}),ge==="schedule-failed"&&e.jsx("div",{className:"text-destructive text-xs",children:"Scheduled publishing failed after multiple attempts."}),a.publishedAt&&e.jsxs(F,{variant:"outline",size:"sm",className:"w-full mt-2",onClick:()=>{Je({kind:"published"}),qe(!0)},children:[e.jsx(ua,{className:"mr-2 h-4 w-4"}),"View published"]})]})]}),e.jsx(wr,{host:i,contentId:r,onViewVersion:n=>{Je({kind:"history",blockId:n.blockId,createdAt:n.createdAt,title:n.title}),qe(!0)}}),!C&&e.jsx(Sr,{deleteOpen:en,setDeleteOpen:tn,onDelete:En,host:i,contentId:r})]});return e.jsx(Ba.Provider,{value:m.active?m:null,children:e.jsxs("div",{className:"mx-auto max-w-6xl",children:[u.collaborationEnabled&&e.jsx("div",{className:"mb-3",children:e.jsx(xr,{status:m.status,editors:m.editors})}),e.jsx(or,{status:z.status}),u.status==="poll-ceiling"&&e.jsx(ks,{variant:"poll-ceiling"}),(u.status==="blocked-edit"||u.status==="read-only-explicit")&&u.lockHolder&&e.jsx(ks,{variant:u.status,lockHolder:u.lockHolder,onRequestCollaboration:()=>u.requestCollaboration.mutate(),isRequesting:u.requestCollaboration.isPending,requestSent:u.requestCollaboration.isSuccess,onDiscardPending:u.status==="blocked-edit"?()=>void yn():void 0,onViewReadOnly:u.status==="blocked-edit"?()=>void kn():void 0,onResumeEditing:u.status==="read-only-explicit"?()=>u.exitReadOnly():void 0,onForceTakeover:u.status==="blocked-edit"&&S?()=>void u.forceTakeover():void 0}),u.status==="read-only-explicit"&&!u.lockHolder&&e.jsxs("div",{className:"bg-emerald-50 border border-emerald-200 rounded-lg p-4 mb-4 flex items-center justify-between gap-3","data-testid":"lock-available-banner",children:[e.jsx("p",{className:"text-sm text-emerald-900",children:"Lock available — you can take over editing now."}),e.jsx(F,{size:"sm",onClick:()=>void u.takeEditing(),"data-testid":"take-editing-btn",children:"Take editing"})]}),!he&&e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2 md:mb-6 md:flex-nowrap md:gap-3 md:justify-between",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2 md:gap-3",children:[e.jsx("h1",{className:"truncate text-xl font-semibold md:text-2xl",children:C?Q?.label??s:ee||"Untitled"}),e.jsx(ha,{variant:tt.variant,children:tt.label}),b.isSaving&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(we,{className:"h-3 w-3 animate-spin"}),"Saving..."]}),!b.isSaving&&b.lastSavedAt&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-muted-foreground",children:[e.jsx(hs,{className:"h-3 w-3"}),"Saved"]}),bn&&e.jsxs("span",{className:"flex items-center gap-1 text-xs text-amber-700",title:"Your edits are based on an older version. The next save may be rejected.","data-testid":"stale-base-indicator",children:[e.jsx("span",{className:"inline-block h-2 w-2 rounded-full bg-amber-500"}),"Older version"]})]}),e.jsxs("div",{className:"flex gap-2 ml-auto",children:[e.jsx(vr,{host:i,contentId:r,collaborationEnabled:u.collaborationEnabled,hasConnectedPeers:m.editors.length>0,isLockHolder:u.status==="editing",sessionId:u.sessionId,onChange:n=>u.setCollaborationEnabled(n),onBeforeDisable:m.sendDisableCollab}),e.jsxs(F,{variant:"outline",size:"sm",onClick:Nn,disabled:b.isSaving||k,className:"px-3",children:[b.isSaving&&e.jsx(we,{className:"mr-2 h-4 w-4 animate-spin"}),"Save Draft"]}),ge==="scheduled"&&e.jsxs(e.Fragment,{children:[e.jsxs(F,{variant:"outline",size:"sm",onClick:Ln,disabled:O.isPending||k,className:"px-3",children:[O.isPending&&e.jsx(we,{className:"mr-2 h-4 w-4 animate-spin"}),"Cancel Schedule"]}),e.jsxs(F,{size:"sm",onClick:nt,disabled:y.isPending||M||k,className:"px-3",children:[(y.isPending||M)&&e.jsx(we,{className:"mr-2 h-4 w-4 animate-spin"}),"Publish Now"]})]}),ge!=="scheduled"&&st&&e.jsxs("div",{className:"flex",children:[e.jsxs(F,{size:"sm",onClick:nt,disabled:y.isPending||M||k,className:mt("px-3",!a.publishedAt&&"rounded-r-none"),children:[(y.isPending||M)&&e.jsx(we,{className:"mr-2 h-4 w-4 animate-spin"}),st]}),!a.publishedAt&&e.jsxs(ms,{children:[e.jsx(ps,{asChild:!0,children:e.jsx(F,{size:"sm",className:"rounded-l-none border-l px-2",disabled:y.isPending||M||k,children:e.jsx(fa,{className:"h-4 w-4"})})}),e.jsx(gs,{align:"end",children:e.jsxs(At,{onClick:()=>Ye(!0),disabled:k,children:[e.jsx(fs,{className:"mr-2 h-4 w-4"}),"Schedule for later"]})})]})]}),a.publishedAt&&e.jsxs(ms,{children:[e.jsx(ps,{asChild:!0,children:e.jsx(F,{variant:"outline",size:"sm",className:"size-8 p-0",disabled:k,children:e.jsx(ma,{className:"h-4 w-4"})})}),e.jsxs(gs,{align:"end",children:[ge==="published-changes"&&e.jsxs(At,{onClick:Dn,disabled:Wt.isPending||k,children:[e.jsx(pa,{className:"mr-2 h-4 w-4"}),"Discard Changes"]}),e.jsx(At,{onClick:An,className:"text-destructive focus:text-destructive",disabled:k,children:"Unpublish"})]})]})]})]}),he?e.jsxs(Ts,{defaultValue:"content",children:[e.jsxs("div",{className:"mb-2 flex items-center",children:[e.jsxs(Is,{variant:"line",children:[e.jsx(ot,{value:"content",children:"Content"}),e.jsx(ot,{value:"info",children:"Info"})]}),e.jsxs("div",{className:"ml-auto flex gap-2",children:[e.jsxs(F,{variant:"outline",size:"sm",onClick:()=>b.flush({createVersion:!0}),disabled:b.isSaving||k,children:[b.isSaving&&e.jsx(we,{className:"mr-1 h-3 w-3 animate-spin"}),"Save"]}),ge!=="scheduled"&&st&&e.jsxs(F,{size:"sm",onClick:nt,disabled:y.isPending||k,children:[y.isPending&&e.jsx(we,{className:"mr-1 h-3 w-3 animate-spin"}),st]})]})]}),e.jsx(dt,{value:"content",className:"mt-0",children:rs}),e.jsx(dt,{value:"info",className:"mt-0",children:is})]}):e.jsxs("div",{className:"grid gap-6 lg:grid-cols-3",children:[e.jsx("div",{className:"lg:col-span-2",children:rs}),e.jsx("div",{children:is})]}),e.jsx(fr,{open:nn,onOpenChange:n=>{qe(n),n||Je(null)},host:i,contentId:r,collectionFields:h,isSingleton:C,isPublished:!!a.publishedAt,draftBody:ke,draftMetadata:C?void 0:{title:ee,slug:fe,snippet:me,tags:ye},initialVersion:an,collectionRelationships:I,draftRelationships:je}),e.jsx(ur,{open:!!le,trigger:le?.trigger??"tab-refocus",updatedBy:gn,updatedAt:le?.updatedAt??0,onReload:xn,onCancel:vn}),e.jsx(_s,{open:gt,onOpenChange:ze,children:e.jsxs($s,{children:[e.jsxs(Vs,{children:[e.jsx(Ms,{children:"Publish changes?"}),e.jsx(Hs,{children:be?e.jsxs(e.Fragment,{children:[be.added>0&&e.jsxs("span",{className:"text-green-600",children:["+",be.added," added"]}),be.added>0&&be.removed>0&&", ",be.removed>0&&e.jsxs("span",{className:"text-red-600",children:["-",be.removed," removed"]}),be.added===0&&be.removed===0&&e.jsx("span",{children:"No visible changes detected."})]}):"This will update the published version with your current changes."})]}),e.jsx("div",{className:"mb-2",children:e.jsx(F,{variant:"link",className:"p-0 h-auto text-sm",onClick:()=>{ze(!1),Je({kind:"draft"}),qe(!0)},children:"View full diff"})}),e.jsxs(Js,{children:[e.jsx(zs,{children:"Cancel"}),e.jsx(Ks,{onClick:()=>{ze(!1),St()},children:"Publish Update"})]})]})}),e.jsx(Ut,{open:rn,onOpenChange:Ke,children:e.jsxs(Ft,{children:[e.jsxs(Ot,{children:[e.jsx(Bt,{children:"Slug change detected"}),e.jsxs(qt,{children:["You are changing the slug from “",a.slug,"” to “",fe,"”. This may break external bookmarks and SEO links."]})]}),e.jsx(jr,{host:i,contentId:r}),e.jsxs(_t,{children:[e.jsx(F,{variant:"outline",onClick:()=>Ke(!1),children:"Cancel"}),e.jsx(F,{onClick:()=>{Ke(!1),St()},children:"Publish Anyway"})]})]})}),e.jsx(Ut,{open:ln,onOpenChange:Ye,children:e.jsxs(Ft,{children:[e.jsxs(Ot,{children:[e.jsx(Bt,{children:"Schedule publishing"}),e.jsx(qt,{children:"Choose a date and time to automatically publish this content. Times are rounded to the nearest 15-minute interval."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(at,{htmlFor:"schedule-date",children:"Publish at"}),e.jsx("input",{id:"schedule-date",type:"datetime-local",value:Qe,onChange:n=>Yt(n.target.value),min:wt(Date.now()+1200*1e3),className:"w-full rounded-md border px-3 py-2 text-sm",step:"900"})]}),e.jsxs(_t,{children:[e.jsx(F,{variant:"outline",onClick:()=>Ye(!1),children:"Cancel"}),e.jsxs(F,{onClick:Pn,disabled:!Qe||j.isPending,children:[j.isPending&&e.jsx(we,{className:"mr-2 h-4 w-4 animate-spin"}),"Schedule"]})]})]})})]})})}function jr({host:i,contentId:s}){const{data:r}=Ls(i,s,!0);return!r||r.count===0?null:e.jsxs("div",{className:"rounded-md border border-yellow-500/50 bg-yellow-50 p-3 text-sm dark:bg-yellow-950/30",children:[e.jsxs("p",{className:"font-medium text-yellow-800 dark:text-yellow-200",children:["This content is referenced by ",r.count," other"," ",r.count===1?"item":"items",":"]}),e.jsxs("ul",{className:"mt-1 list-disc pl-5 text-yellow-700 dark:text-yellow-300",children:[r.items.slice(0,5).map(a=>e.jsxs("li",{children:[a.title," (",a.collection,")"]},`${a.contentId}-${a.fieldName}`)),r.items.length>5&&e.jsxs("li",{children:["and ",r.items.length-5," more..."]})]})]})}function Sr({deleteOpen:i,setDeleteOpen:s,onDelete:r,host:a,contentId:l}){const{data:c}=Ls(a,l,i);return e.jsxs(e.Fragment,{children:[e.jsx(Us,{}),e.jsxs(Ut,{open:i,onOpenChange:s,children:[e.jsx(ga,{asChild:!0,children:e.jsxs(F,{variant:"destructive",className:"w-full",children:[e.jsx(ba,{className:"mr-2 h-4 w-4"}),"Delete"]})}),e.jsxs(Ft,{children:[e.jsxs(Ot,{children:[e.jsx(Bt,{children:"Delete content?"}),e.jsx(qt,{children:"This action cannot be undone. The content will be permanently deleted."})]}),c&&c.count>0&&e.jsxs("div",{className:"rounded-md border border-yellow-500/50 bg-yellow-50 p-3 text-sm dark:bg-yellow-950/30",children:[e.jsxs("p",{className:"font-medium text-yellow-800 dark:text-yellow-200",children:["This content is referenced by ",c.count," other"," ",c.count===1?"item":"items",":"]}),e.jsxs("ul",{className:"mt-1 list-disc pl-5 text-yellow-700 dark:text-yellow-300",children:[c.items.slice(0,5).map(f=>e.jsxs("li",{children:[f.title," (",f.collection,")"]},`${f.contentId}-${f.fieldName}`)),c.items.length>5&&e.jsxs("li",{children:["and ",c.items.length-5," more..."]})]})]}),e.jsxs(_t,{children:[e.jsx(F,{variant:"outline",onClick:()=>s(!1),children:"Cancel"}),e.jsx(F,{variant:"destructive",onClick:r,children:"Delete"})]})]})]})]})}function wr({host:i,contentId:s,onViewVersion:r}){const{data:a}=Ps(i,s),[l,c]=t.useState(!1),f=a?.items??[],d=f.map(o=>o.createdBy).filter(Boolean),{resolve:p}=Ys(d);return f.length===0?null:e.jsx($e,{children:e.jsx(Ve,{className:"pt-4",children:e.jsxs(Qs,{open:l,onOpenChange:c,children:[e.jsxs(Ws,{className:"flex w-full items-center gap-2 text-sm font-medium",children:[e.jsx(qs,{className:mt("h-4 w-4 transition",l&&"rotate-90")}),"Version History (",f.length,")"]}),e.jsx(Gs,{className:"mt-2",children:e.jsx("div",{className:"space-y-1",children:f.map((o,y)=>e.jsxs("button",{className:"py-1 text-sm hover:bg-muted rounded px-1 -mx-1 transition-colors w-full text-left",onClick:()=>r(o),children:[e.jsx("span",{children:Ne(o.createdAt)}),o.createdBy&&e.jsx("span",{className:"ml-2 text-muted-foreground",children:p(o.createdBy)}),o.title&&e.jsx("span",{className:"ml-2 text-muted-foreground",children:o.title})]},`${o.createdAt}-${y}`))})})]})})})}export{ti as ContentEditPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./tanstack-Bs3zYPPV.js";import{u as Ae,f as Pe,r as j}from"./react-vendor-C2CvUxFh.js";import{w as Te,x as _e,B as R,P as oe,v as w,z as ue,I as he,X as L,A as Ie,L as z,j as T,S as $e,a as Fe,y as Ve}from"./index-DC1UyCW2.js";import{d as Be,e as De,a as Le,b as Me,c as Ue}from"./useContent-Bp4f9qe0.js";import{u as qe}from"./useTags-DJlXwDyc.js";import{u as Re}from"./useContentSearch-DbiA8aG-.js";import{u as ze}from"./usePageTitle-DOEFrHbj.js";import{u as Oe}from"./useFilterParams-DYdEuWPE.js";import{m as xe}from"./media-url-DdCoIedP.js";import{u as Ee,F as He,g as me}from"./listCellValue-CBqXAwce.js";import{C as We,c as Xe}from"./card-DlfsF8lU.js";import{C as Q}from"./checkbox-BX8EcGFf.js";import{P as Ze,a as Ge,b as Qe}from"./popover-BA-47SRI.js";import{S as C,a as k,b as y,c as A,d as u}from"./select-waaVyoQ5.js";import{T as Je,a as Ke,b as ge,c as I,d as Ye,e as $}from"./table-Br-QgtTL.js";import{a as F,f as pe}from"./format-BRcflvs9.js";import{g as fe,a as je}from"./contentStatus-WXGfd7vX.js";import{B as es}from"./BulkActionBar-BWysX7Wo.js";import{P as ss}from"./Pagination-Dx8h11Rn.js";import"./radix-C5ZmWuuL.js";import"./command-DaTsImUa.js";const O=3,ve=[{value:"updated_desc",label:"Last updated"},{value:"updated_asc",label:"Oldest updated"},{value:"title_asc",label:"Title A–Z",requiresCollection:!0},{value:"title_desc",label:"Title Z–A",requiresCollection:!0},{value:"created_desc",label:"Newest created"},{value:"created_asc",label:"Oldest created"}],J=[{value:"all",label:"All statuses"},{value:"draft",label:"Draft"},{value:"published",label:"Published"},{value:"changed",label:"Changed"},{value:"unpublished",label:"Unpublished"},{value:"scheduled",label:"Scheduled"}];function ws(){const{host:i,collection:c}=Ae(),_=Pe(),{collections:be}=Te(),[d,a]=Oe([{key:"q",defaultValue:""},{key:"search",defaultValue:"prefix"},{key:"tag",defaultValue:""},{key:"status",defaultValue:""},{key:"sort",defaultValue:"updated_desc"},{key:"relatedTo",defaultValue:""},{key:"relField",defaultValue:""},{key:"page",defaultValue:"1"},{key:"perPage",defaultValue:"20"},{key:"after",defaultValue:""}]),V=d.search,g=d.tag||void 0,p=d.status||void 0,f=d.sort,v=d.relatedTo,b=d.relField,N=Number(d.page)||1,E=Number(d.perPage)||20,K=j.useMemo(()=>{const e=d.after;return e?e.split(","):[]},[d.after]),[B,D]=j.useState(d.q),[h,t]=j.useState(new Set),H=_e(),x=be.find(e=>e.name===c),M=x?.relationships??[],{data:Y}=Ee(i,v||void 0),ee=j.useMemo(()=>{if(!v||!b)return null;const e=M.find(r=>r.name===b);return{type:"relationship",relName:b,relLabel:e?.label??b,contentId:v,contentTitle:Y??"Loading..."}},[v,b,M,Y]);ze({title:x?.label??c??"",actions:x?.singleton?void 0:s.jsx(R,{size:"sm",onClick:()=>_(`/sites/${i}/content/${c}/new`),children:s.jsx(oe,{className:"h-4 w-4"})})});const m=Re(B,300);j.useEffect(()=>{m!==d.q&&a({q:m})},[m,d.q,a]);const S=j.useCallback(()=>{a({page:"1",after:""}),t(new Set)},[a]),Ne=j.useMemo(()=>{const e={};return m&&(e.q=m,e.search=V),g&&(e.tag=g),p&&(e.status=p),f!=="updated_desc"&&(e.sort=f),v&&(e.relatedTo=v),b&&(e.relField=b),e.limit=E,e},[m,V,g,p,f,v,b,E]),Se=N>1?K[N-2]:void 0,{data:P,isLoading:we}=Be(i,c,Ne,Se),W=De(i),se=Le(i),ae=Me(i),te=Ue(i),{data:le}=qe(i),U=j.useMemo(()=>le?.map(e=>e.tag)??[],[le]),X=x?.fields,Z=j.useMemo(()=>X?X.filter(e=>(e.options??{}).listColumn===!0):[],[X]);if(x?.singleton&&P?.items.length===1)return _(`/sites/${i}/content/${c}/${P.items[0].contentId}`,{replace:!0}),null;const q=P?.items,G=q?.map(e=>e.contentId)??[],ne=G.length>0&&G.every(e=>h.has(e));function re(e){t(r=>{const l=new Set(r);return l.has(e)?l.delete(e):l.add(e),l})}function Ce(){t(ne?new Set:new Set(G))}const ce=!!(m||g||p||v),ie=!!m,de=[V!=="prefix"?1:0,g?1:0,p?1:0,f!=="updated_desc"?1:0].reduce((e,r)=>e+r,0),ke=se.isPending||ae.isPending||te.isPending;async function ye(){try{const e=await W.mutateAsync({collection:c,title:x?.label??c});w.success("Singleton content recreated"),_(`/sites/${i}/content/${c}/${e.contentId}`)}catch(e){w.error("Failed to recreate singleton",{description:e instanceof Error?e.message:void 0})}}return s.jsxs("div",{children:[!H&&s.jsxs("div",{className:"mb-6 flex items-center justify-between",children:[s.jsx("h1",{className:"text-2xl font-semibold",children:x?.label??c}),!x?.singleton&&s.jsxs(R,{onClick:()=>_(`/sites/${i}/content/${c}/new`),children:[s.jsx(oe,{className:"mr-2 h-4 w-4"}),"New"]})]}),h.size>0?s.jsx(es,{selectedCount:h.size,onPublish:async()=>{const e=[...h],l=(await se.mutateAsync(e)).filter(o=>o.status==="rejected").length;l?w.error(`${l} of ${e.length} failed to publish`):w.success(`${e.length} item(s) published`),S()},onUnpublish:async()=>{const e=[...h],l=(await ae.mutateAsync(e)).filter(o=>o.status==="rejected").length;l?w.error(`${l} of ${e.length} failed to unpublish`):w.success(`${e.length} item(s) unpublished`),S()},onDelete:async()=>{const e=[...h],l=(await te.mutateAsync(e)).filter(o=>o.status==="rejected").length;l?w.error(`${l} of ${e.length} failed to delete`):w.success(`${e.length} item(s) deleted`),S()},onClear:()=>t(new Set),isPending:ke}):H?s.jsxs("div",{className:"mb-4 flex items-center gap-2",children:[s.jsxs("div",{className:"relative flex-1",children:[s.jsx(ue,{className:"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground"}),s.jsx(he,{placeholder:"Search...",value:B,onChange:e=>{D(e.target.value),S()},className:"pl-8 pr-8"}),B&&s.jsx("button",{onClick:()=>{D(""),S()},className:"absolute right-2 top-2.5 text-muted-foreground hover:text-foreground",children:s.jsx(L,{className:"h-4 w-4"})})]}),s.jsxs(Ze,{children:[s.jsx(Ge,{asChild:!0,children:s.jsxs(R,{variant:"outline",size:"icon",className:"relative shrink-0","aria-label":"Filters",children:[s.jsx(Ie,{className:"h-4 w-4"}),de>0&&s.jsx("span",{className:"absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full bg-primary text-[10px] text-primary-foreground",children:de})]})}),s.jsxs(Qe,{className:"w-64 space-y-3",align:"end",children:[s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Search Mode"}),s.jsxs(C,{value:V,onValueChange:e=>{a({search:e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsxs(A,{children:[s.jsx(u,{value:"prefix",children:"Starts with"}),s.jsx(u,{value:"full",children:"Contains"})]})]})]}),U.length>0&&s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Tag"}),s.jsxs(C,{value:g??"__all__",onValueChange:e=>{a({tag:e==="__all__"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsxs(A,{children:[s.jsx(u,{value:"__all__",children:"All tags"}),U.map(e=>s.jsx(u,{value:e,children:e},e))]})]})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Status"}),s.jsxs(C,{value:p??"all",onValueChange:e=>{a({status:e==="all"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsx(A,{children:J.map(e=>s.jsx(u,{value:e.value??"all",children:e.label},e.value??"all"))})]})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(z,{className:"text-xs font-medium",children:"Sort"}),s.jsxs(C,{value:f,onValueChange:e=>{a({sort:e,page:"1",after:""}),t(new Set)},disabled:ie,children:[s.jsx(k,{children:s.jsx(y,{})}),s.jsx(A,{children:ve.map(e=>s.jsx(u,{value:e.value,disabled:e.requiresCollection&&!c,children:e.label},e.value))})]})]})]})]})]}):s.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2",children:[s.jsxs("div",{className:"relative flex items-center",children:[s.jsx(ue,{className:"absolute left-2.5 h-4 w-4 text-muted-foreground"}),s.jsx(he,{placeholder:"Search titles...",value:B,onChange:e=>{D(e.target.value),S()},className:"w-56 pl-8 pr-8"}),B&&s.jsx("button",{onClick:()=>{D(""),S()},className:"absolute right-2 text-muted-foreground hover:text-foreground",children:s.jsx(L,{className:"h-4 w-4"})})]}),s.jsxs(C,{value:V,onValueChange:e=>{a({search:e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{className:"w-[130px]",children:s.jsx(y,{})}),s.jsxs(A,{children:[s.jsx(u,{value:"prefix",children:"Starts with"}),s.jsx(u,{value:"full",children:"Contains"})]})]}),U.length>0&&s.jsxs(C,{value:g??"__all__",onValueChange:e=>{a({tag:e==="__all__"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{className:"w-[140px]",children:s.jsx(y,{placeholder:"Tag"})}),s.jsxs(A,{children:[s.jsx(u,{value:"__all__",children:"All tags"}),U.map(e=>s.jsx(u,{value:e,children:e},e))]})]}),s.jsxs(C,{value:p??"all",onValueChange:e=>{a({status:e==="all"?"":e,page:"1",after:""}),t(new Set)},children:[s.jsx(k,{className:"w-[150px]",children:s.jsx(y,{})}),s.jsx(A,{children:J.map(e=>s.jsx(u,{value:e.value??"all",children:e.label},e.value??"all"))})]}),s.jsx("div",{className:"ml-auto",children:s.jsxs(C,{value:f,onValueChange:e=>{a({sort:e,page:"1",after:""}),t(new Set)},disabled:ie,children:[s.jsx(k,{className:"w-[170px]",children:s.jsx(y,{})}),s.jsx(A,{children:ve.map(e=>s.jsx(u,{value:e.value,disabled:e.requiresCollection&&!c,children:e.label},e.value))})]})})]}),M.length>0&&s.jsx("div",{className:"mb-3",children:s.jsx(He,{relationships:M,activeFilters:ee?[ee]:[],onFilterAdd:e=>{a({relatedTo:e.contentId,relField:e.relName,page:"1",after:""}),t(new Set)},onFilterRemove:()=>{a({relatedTo:"",relField:"",page:"1",after:""}),t(new Set)}})}),ce&&h.size===0&&s.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-1.5",children:[m&&s.jsxs(T,{variant:"secondary",className:"gap-1",children:["Search: ",m,s.jsx("button",{onClick:()=>{D(""),S()},children:s.jsx(L,{className:"h-3 w-3"})})]}),g&&s.jsxs(T,{variant:"secondary",className:"gap-1",children:["Tag: ",g,s.jsx("button",{onClick:()=>{a({tag:"",page:"1",after:""}),t(new Set)},children:s.jsx(L,{className:"h-3 w-3"})})]}),p&&s.jsxs(T,{variant:"secondary",className:"gap-1",children:["Status: ",J.find(e=>e.value===p)?.label,s.jsx("button",{onClick:()=>{a({status:"",page:"1",after:""}),t(new Set)},children:s.jsx(L,{className:"h-3 w-3"})})]})]}),we?s.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((e,r)=>s.jsx($e,{className:"h-12 w-full"},r))}):q?.length?s.jsxs(s.Fragment,{children:[H?s.jsx("div",{className:"grid gap-3 sm:grid-cols-2","data-testid":"content-card-view",children:q.map(e=>{const r=fe(e.publishedAt,e.lastPublishedAt,e.publishedBlockId,e.lastDraftBlockId,e.scheduledAt,e.scheduledFailed),l=je(r),o=e.tags??[];return s.jsx(We,{className:Ve("cursor-pointer gap-0 overflow-hidden py-0 transition-shadow hover:shadow-md",h.has(e.contentId)&&"ring-2 ring-primary"),onClick:()=>_(`/sites/${i}/content/${c}/${e.contentId}`),children:s.jsxs(Xe,{className:"p-3",children:[s.jsxs("div",{className:"flex items-start gap-3 min-w-0",children:[e.cover?.url&&s.jsx("img",{src:xe(e.cover.url),alt:e.cover.alt??"",className:"h-12 w-12 rounded object-cover flex-shrink-0"}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[s.jsx("span",{className:"font-medium truncate",children:e.draftTitle||e.title||"Untitled"}),s.jsx(T,{variant:l.variant,className:"shrink-0",children:l.label})]}),(e.draftSlug||e.slug)&&s.jsxs("p",{className:"text-xs text-muted-foreground truncate mt-0.5",children:["/",e.draftSlug||e.slug]}),Z.filter(n=>n.type!=="media").slice(0,3).map(n=>s.jsx("p",{className:"text-xs text-muted-foreground truncate mt-0.5",children:me(e,n)},n.name)),s.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:f.startsWith("created")?e.createdAt?F(e.createdAt):"—":e.lastDraftAt?F(e.lastDraftAt):"—"})]}),s.jsx(Q,{checked:h.has(e.contentId),onCheckedChange:()=>re(e.contentId),onClick:n=>n.stopPropagation(),className:"mt-1"})]}),o.length>0&&s.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:o.slice(0,O).map(n=>s.jsx(T,{variant:"outline",className:"text-[10px] px-1.5 py-0",children:n},n))})]})},e.contentId)})}):s.jsx("div",{className:"overflow-x-auto",children:s.jsxs(Je,{children:[s.jsx(Ke,{children:s.jsxs(ge,{children:[s.jsx(I,{className:"w-10",children:s.jsx(Q,{checked:ne,onCheckedChange:Ce,"aria-label":"Select all"})}),s.jsx(I,{children:"Title"}),s.jsx(I,{children:"Slug"}),Z.map(e=>s.jsx(I,{children:e.label||e.name},e.name)),s.jsx(I,{children:"Status"}),s.jsx(I,{children:f.startsWith("created")?"Created":"Updated"})]})}),s.jsx(Ye,{children:q.map(e=>{const r=fe(e.publishedAt,e.lastPublishedAt,e.publishedBlockId,e.lastDraftBlockId),l=je(r),o=e.tags??[];return s.jsxs(ge,{className:"cursor-pointer",onClick:()=>_(`/sites/${i}/content/${c}/${e.contentId}`),children:[s.jsx($,{onClick:n=>n.stopPropagation(),children:s.jsx(Q,{checked:h.has(e.contentId),onCheckedChange:()=>re(e.contentId),"aria-label":`Select ${e.draftTitle||e.title||"Untitled"}`})}),s.jsx($,{className:"font-medium",children:s.jsxs("div",{className:"flex items-center gap-3",children:[e.cover?.url&&s.jsx("img",{src:xe(e.cover.url),alt:e.cover.alt??"",className:"h-8 w-8 rounded object-cover flex-shrink-0"}),s.jsxs("div",{className:"min-w-0",children:[s.jsx("span",{children:e.draftTitle||e.title||"Untitled"}),o.length>0&&s.jsxs("div",{className:"mt-0.5 flex flex-wrap gap-1",children:[o.slice(0,O).map(n=>s.jsx(T,{variant:"outline",className:"text-[10px] px-1.5 py-0 font-normal text-muted-foreground",children:n},n)),o.length>O&&s.jsxs("span",{className:"text-[10px] text-muted-foreground",children:["+",o.length-O," more"]})]})]})]})}),s.jsx($,{className:"text-muted-foreground text-sm",children:e.draftSlug||e.slug||"—"}),Z.map(n=>s.jsx($,{className:"text-muted-foreground text-sm",children:me(e,n)},n.name)),s.jsx($,{children:s.jsx(T,{variant:l.variant,children:l.label})}),s.jsx($,{className:"text-muted-foreground",children:f.startsWith("created")?e.createdAt?F(e.createdAt):"—":e.scheduledAt&&!e.publishedAt?s.jsxs("span",{title:pe(e.scheduledAt),children:["Scheduled ",F(e.scheduledAt)]}):e.publishedAt?s.jsx("span",{title:pe(e.publishedAt),children:F(e.publishedAt)}):e.lastDraftAt?F(e.lastDraftAt):"—"})]},e.contentId)})})]})}),s.jsx(ss,{page:N,hasNext:!!P?.hasMore,hasPrevious:N>1,onNext:()=>{if(P?.items.length){const e=P.items[P.items.length-1].contentId,r=[...K.slice(0,N-1),e];a({page:String(N+1),after:r.join(",")})}else a({page:String(N+1)});t(new Set)},onPrevious:()=>{const e=N-1;a(e<=1?{page:"1",after:""}:{page:String(e)}),t(new Set)},perPage:E,onPerPageChange:e=>{a({perPage:String(e),page:"1",after:""}),t(new Set)}})]}):x?.singleton?s.jsxs("div",{className:"space-y-4",children:[s.jsx("p",{className:"text-muted-foreground",children:"Singleton content is missing. Click below to recreate it."}),s.jsxs(R,{onClick:ye,disabled:W.isPending,children:[W.isPending&&s.jsx(Fe,{className:"mr-2 h-4 w-4 animate-spin"}),"Recreate ",x.label]})]}):s.jsx("p",{className:"text-muted-foreground",children:ce?"No content matches the current filters.":"No content yet."})]})}export{ws as ContentListPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./tanstack-Bs3zYPPV.js";import{u as F,f as B,r as L,L as C}from"./react-vendor-C2CvUxFh.js";import{j as S,m as O}from"./useContent-Bp4f9qe0.js";import{x as E,w as P,S as b,B as r,bb as M,a5 as U,Z as z,D as H,i as V,T as Y,k as Z,l as _,m as q,n as G,o as J,aj as K,j as Q,v as g}from"./index-DC1UyCW2.js";import{u as W}from"./usePageTitle-DOEFrHbj.js";import{C as y,a as v,b as D,c as w}from"./card-DlfsF8lU.js";import{f as X}from"./format-BRcflvs9.js";import{a as ss}from"./MediaField-C3qFf3g5.js";import"./radix-C5ZmWuuL.js";import"./FileTypeIcon-CNHtffHC.js";import"./select-waaVyoQ5.js";import"./table-Br-QgtTL.js";import"./media-url-DdCoIedP.js";function es({host:i,ref:t}){const c=!t.title&&!!t.contentId,{data:o}=S(i,c?t.contentId:""),d=c&&o?.content?o.content:null,u=t.title||d?.title||t.contentId,a=t.collection||d?.collection||"";return s.jsxs(C,{to:`/sites/${i}/content/${a}/${t.contentId}`,className:"flex items-center gap-3 rounded-md border p-2 transition-colors hover:bg-muted",children:[s.jsx(K,{className:"h-4 w-4 shrink-0 text-muted-foreground"}),s.jsx("span",{className:"flex-1 truncate text-sm",children:u}),a&&s.jsx(Q,{variant:"secondary",children:a})]})}function js(){const{host:i,collection:t,id:c}=F(),o=B(),d=E(),{collections:u}=P(),{data:a,isLoading:$}=S(i,c),k=O(i,c),[T,p]=L.useState(!1),m=u.find(e=>e.name===t),f=m?.relationships??[];if(W({title:"Submission Detail",showBack:!0,backTo:`/sites/${i}/submissions/${t}`}),$)return s.jsxs("div",{className:"space-y-4",children:[s.jsx(b,{className:"h-8 w-64"}),s.jsx(b,{className:"h-64 w-full"})]});if(!a?.content)return s.jsx("p",{className:"text-muted-foreground",children:"Submission not found."});const l=a.content,x=a.body??l.body,h=l.siteUser,j=l.relationships;function I(e,n){return n==null?"—":typeof n=="boolean"?n?"Yes":"No":Array.isArray(n)?n.join(", "):String(n)}async function R(){try{await k.mutateAsync(),g.success("Submission deleted"),o(`/sites/${i}/submissions/${t}`)}catch(e){g.error("Failed to delete",{description:e instanceof Error?e.message:void 0})}}const A=f.length>0&&j&&Object.keys(j).length>0;return s.jsxs("div",{className:"mx-auto max-w-2xl",children:[!d&&s.jsxs("div",{className:"mb-6 flex items-center gap-4",children:[s.jsxs(r,{variant:"ghost",size:"sm",onClick:()=>o(`/sites/${i}/submissions/${t}`),children:[s.jsx(M,{className:"mr-1.5 h-4 w-4"}),"Back"]}),s.jsx("h1",{className:"text-2xl font-semibold",children:"Submission Detail"}),s.jsx("div",{className:"ml-auto",children:s.jsxs(r,{variant:"outline",size:"sm",onClick:()=>o(`/sites/${i}/submissions/${t}/${c}/edit`),children:[s.jsx(U,{className:"mr-1.5 h-4 w-4"}),"Edit"]})})]}),s.jsxs(y,{children:[s.jsx(v,{children:s.jsx(D,{children:l.title||"Untitled"})}),s.jsxs(w,{className:"space-y-4",children:[s.jsxs("div",{className:"space-y-2 text-sm",children:[s.jsxs("div",{className:"flex justify-between",children:[s.jsx("span",{className:"text-muted-foreground",children:"ID"}),s.jsx("span",{className:"font-mono text-xs",children:l.contentId})]}),!!l.publishedAt&&s.jsxs("div",{className:"flex justify-between",children:[s.jsx("span",{className:"text-muted-foreground",children:"Submitted"}),s.jsx("span",{children:X(l.publishedAt)})]}),h&&s.jsxs("div",{className:"flex justify-between",children:[s.jsx("span",{className:"text-muted-foreground",children:"Submitted by"}),s.jsx(C,{to:`/sites/${i}/settings/site-users/${h.userId}`,className:"text-primary hover:underline",children:h.name||h.email})]})]}),s.jsx(z,{}),s.jsxs("div",{className:"space-y-3",children:[m?.fields?.map(e=>s.jsxs("div",{className:"space-y-1",children:[s.jsx("p",{className:"text-sm font-medium text-muted-foreground",children:e.label||e.name}),e.type==="media"?s.jsx(ss,{field:e,value:x?.[e.name],onChange:()=>{},disabled:!0}):s.jsx("p",{className:"text-sm whitespace-pre-wrap",children:I(e,x?.[e.name])})]},e.name)),(!m?.fields||m.fields.length===0)&&x&&s.jsx("div",{className:"space-y-3",children:Object.entries(x).map(([e,n])=>s.jsxs("div",{className:"space-y-1",children:[s.jsx("p",{className:"text-sm font-medium text-muted-foreground",children:e}),s.jsx("p",{className:"text-sm whitespace-pre-wrap",children:n==null?"—":String(n)})]},e))})]})]})]}),A&&s.jsxs(y,{className:"mt-6",children:[s.jsx(v,{children:s.jsx(D,{children:"Relationships"})}),s.jsx(w,{className:"space-y-4",children:f.map(e=>{const n=j?.[e.name]??[];return n.length===0?null:s.jsxs("div",{className:"space-y-2",children:[s.jsx("p",{className:"text-sm font-medium",children:e.label}),s.jsx("div",{className:"space-y-2",children:n.map(N=>s.jsx(es,{host:i,ref:N},N.contentId))})]},e.name)})})]}),s.jsx("div",{className:"mt-6",children:s.jsxs(H,{open:T,onOpenChange:p,children:[s.jsx(V,{asChild:!0,children:s.jsxs(r,{variant:"destructive",children:[s.jsx(Y,{className:"mr-2 h-4 w-4"}),"Delete Submission"]})}),s.jsxs(Z,{children:[s.jsxs(_,{children:[s.jsx(q,{children:"Delete submission?"}),s.jsx(G,{children:"This will permanently delete this submission."})]}),s.jsxs(J,{children:[s.jsx(r,{variant:"outline",onClick:()=>p(!1),children:"Cancel"}),s.jsx(r,{variant:"destructive",onClick:R,children:"Delete"})]})]})]})})]})}export{js as SubmissionDetailPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as s}from"./tanstack-Bs3zYPPV.js";import{u as H,f as G,r as x}from"./react-vendor-C2CvUxFh.js";import{u as J}from"./useFilterParams-DYdEuWPE.js";import{w as K,x as Q,B as M,P as W,T as X,v as U,S as Y,y as Z}from"./index-DC1UyCW2.js";import{d as ee,c as se}from"./useContent-Bp4f9qe0.js";import{u as te}from"./usePageTitle-DOEFrHbj.js";import{u as ae,F as le,g as ne}from"./listCellValue-CBqXAwce.js";import{C as re,c as ie}from"./card-DlfsF8lU.js";import{C as I}from"./checkbox-BX8EcGFf.js";import{S as oe,a as ce,b as de,c as ue,d as me}from"./select-waaVyoQ5.js";import{T as he,a as xe,b as L,c as S,d as pe,e as N}from"./table-Br-QgtTL.js";import{a as R,f as fe}from"./format-BRcflvs9.js";import{P as ge}from"./Pagination-Dx8h11Rn.js";import"./radix-C5ZmWuuL.js";import"./popover-BA-47SRI.js";import"./command-DaTsImUa.js";import"./useContentSearch-DbiA8aG-.js";import"./media-url-DdCoIedP.js";const be=[{value:"created_desc",label:"Newest first"},{value:"created_asc",label:"Oldest first"}];function Re(){const{host:m,collection:i}=H(),v=G(),{collections:_}=K(),[o,l]=J([{key:"sort",defaultValue:"created_desc"},{key:"relatedTo",defaultValue:""},{key:"relField",defaultValue:""},{key:"page",defaultValue:"1"},{key:"perPage",defaultValue:"20"},{key:"after",defaultValue:""}]),f=o.sort,c=o.relatedTo,n=o.relField,r=Number(o.page)||1,w=Number(o.perPage)||20,k=x.useMemo(()=>{const e=o.after;return e?e.split(","):[]},[o.after]),[d,a]=x.useState(new Set),T=Q(),h=_.find(e=>e.name===i),g=h?.relationships??[];te({title:h?.label??i??""});const{data:y}=ae(m,c||void 0),P=x.useMemo(()=>{if(!c||!n)return null;const e=g.find(t=>t.name===n);return{type:"relationship",relName:n,relLabel:e?.label??n,contentId:c,contentTitle:y??"Loading..."}},[c,n,g,y]),B=x.useCallback(()=>{l({page:"1",after:""}),a(new Set)},[l]),D=x.useMemo(()=>{const e={};return f!=="created_desc"&&(e.sort=f),c&&(e.relatedTo=c),n&&(e.relField=n),e.limit=w,e},[f,c,n,w]),O=r>1?k[r-2]:void 0,{data:p,isLoading:z}=ee(m,i,D,O),F=se(m),b=p?.items,j=h?.fields,A=x.useMemo(()=>{if(!j)return[];const e=j.filter(t=>(t.options??{}).listColumn===!0);return e.length>0?e:j.filter(t=>["text","number","boolean","select"].includes(t.type)).slice(0,4)},[j]),C=b?.map(e=>e.contentId)??[],$=C.length>0&&C.every(e=>d.has(e));function V(e){a(t=>{const u=new Set(t);return u.has(e)?u.delete(e):u.add(e),u})}function q(){a($?new Set:new Set(C))}return s.jsxs("div",{children:[!T&&s.jsxs("div",{className:"mb-6 flex items-center justify-between",children:[s.jsx("h1",{className:"text-2xl font-semibold",children:h?.label??i}),s.jsxs(M,{onClick:()=>v(`/sites/${m}/submissions/${i}/new`),children:[s.jsx(W,{className:"mr-1.5 h-4 w-4"}),"New Submission"]})]}),s.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2",children:[g.length>0&&s.jsx(le,{relationships:g,activeFilters:P?[P]:[],onFilterAdd:e=>{l({relatedTo:e.contentId,relField:e.relName,page:"1",after:""}),a(new Set)},onFilterRemove:()=>{l({relatedTo:"",relField:"",page:"1",after:""}),a(new Set)}}),s.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[d.size>0&&s.jsxs(M,{variant:"destructive",size:"sm",onClick:async()=>{const e=[...d],u=(await F.mutateAsync(e)).filter(E=>E.status==="rejected").length;u?U.error(`${u} of ${e.length} failed to delete`):U.success(`${e.length} submission(s) deleted`),B()},disabled:F.isPending,children:[s.jsx(X,{className:"mr-1.5 h-3.5 w-3.5"}),"Delete (",d.size,")"]}),s.jsxs(oe,{value:f,onValueChange:e=>{l({sort:e,page:"1",after:""}),a(new Set)},children:[s.jsx(ce,{className:"w-[150px]",children:s.jsx(de,{})}),s.jsx(ue,{children:be.map(e=>s.jsx(me,{value:e.value,children:e.label},e.value))})]})]})]}),z?s.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((e,t)=>s.jsx(Y,{className:"h-12 w-full"},t))}):b?.length?s.jsxs(s.Fragment,{children:[T?s.jsx("div",{className:"grid gap-3","data-testid":"submission-card-view",children:b.map(e=>s.jsx(re,{className:Z("cursor-pointer gap-0 overflow-hidden py-0 transition-shadow hover:shadow-md",d.has(e.contentId)&&"ring-2 ring-primary"),onClick:()=>v(`/sites/${m}/submissions/${i}/${e.contentId}`),children:s.jsx(ie,{className:"p-3",children:s.jsxs("div",{className:"flex items-start gap-3 min-w-0",children:[s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsxs("span",{className:"font-medium truncate",children:["Submission ",e.contentId.slice(-6)]}),s.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:e.publishedAt?R(e.publishedAt):"—"}),e.siteUser&&s.jsxs("p",{className:"text-xs text-muted-foreground",children:["by ",e.siteUser.name||e.siteUser.userId]})]}),s.jsx(I,{checked:d.has(e.contentId),onCheckedChange:()=>V(e.contentId),onClick:t=>t.stopPropagation(),className:"mt-1"})]})})},e.contentId))}):s.jsx("div",{className:"overflow-x-auto",children:s.jsxs(he,{children:[s.jsx(xe,{children:s.jsxs(L,{children:[s.jsx(S,{className:"w-10",children:s.jsx(I,{checked:$,onCheckedChange:q,"aria-label":"Select all"})}),A.map(e=>s.jsx(S,{children:e.label||e.name},e.name)),h?.requireAuth&&s.jsx(S,{children:"Submitted by"}),s.jsx(S,{children:"Submitted"})]})}),s.jsx(pe,{children:b.map(e=>s.jsxs(L,{className:"cursor-pointer",onClick:()=>v(`/sites/${m}/submissions/${i}/${e.contentId}`),children:[s.jsx(N,{onClick:t=>t.stopPropagation(),children:s.jsx(I,{checked:d.has(e.contentId),onCheckedChange:()=>V(e.contentId),"aria-label":`Select submission ${e.contentId.slice(-6)}`})}),A.map(t=>s.jsx(N,{className:"text-muted-foreground text-sm",children:ne(e,t)},t.name)),h?.requireAuth&&s.jsx(N,{className:"text-muted-foreground text-sm",children:e.siteUser?e.siteUser.name||e.siteUser.userId:"—"}),s.jsx(N,{className:"text-muted-foreground",children:e.publishedAt?s.jsx("span",{title:fe(e.publishedAt),children:R(e.publishedAt)}):"—"})]},e.contentId))})]})}),s.jsx(ge,{page:r,hasNext:!!p?.hasMore,hasPrevious:r>1,onNext:()=>{if(p?.items.length){const e=p.items[p.items.length-1].contentId,t=[...k.slice(0,r-1),e];l({page:String(r+1),after:t.join(",")})}else l({page:String(r+1)});a(new Set)},onPrevious:()=>{const e=r-1;l(e<=1?{page:"1",after:""}:{page:String(e)}),a(new Set)},perPage:w,onPerPageChange:e=>{l({perPage:String(e),page:"1",after:""}),a(new Set)}})]}):s.jsx("p",{className:"text-muted-foreground",children:"No submissions yet."})]})}export{Re as SubmissionListPage};
|