headroom-cms 0.1.7 → 0.1.8

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.
Files changed (73) hide show
  1. package/README.md +9 -82
  2. package/admin/assets/{AdminsPage-BqfhR4Zc.js → AdminsPage-Bt_ekZen.js} +1 -1
  3. package/admin/assets/AllContentPage-CFqEMAl9.js +1 -0
  4. package/admin/assets/{ApiKeysPage-DJjOSLoR.js → ApiKeysPage-BfWCxGhC.js} +1 -1
  5. package/admin/assets/AuditPage-BE0XIUl2.js +1 -0
  6. package/admin/assets/{BlockEditor-DDsml97y.js → BlockEditor-6wqsThJ7.js} +40 -40
  7. package/admin/assets/{BlockTypeEditPage-Cg7BifaZ.js → BlockTypeEditPage-CuNJfZw0.js} +1 -1
  8. package/admin/assets/{BlockTypesPage-BDFj8TSL.js → BlockTypesPage-BIMBVxBs.js} +1 -1
  9. package/admin/assets/{BulkActionBar-CastJGEP.js → BulkActionBar-TRiXXLQd.js} +1 -1
  10. package/admin/assets/{CollectionEditPage-DGW4iMfo.js → CollectionEditPage-BqX_0cC2.js} +1 -1
  11. package/admin/assets/{CollectionsPage-C8XNxRda.js → CollectionsPage-ClplrxNn.js} +1 -1
  12. package/admin/assets/{ContentCreatePage-CX4aOzTR.js → ContentCreatePage-DfYcEH1u.js} +1 -1
  13. package/admin/assets/ContentEditPage-D3Rvlktk.js +2 -0
  14. package/admin/assets/ContentListPage-zmO8Is4d.js +1 -0
  15. package/admin/assets/{CustomBlockPreview-DfDOcbmR.js → CustomBlockPreview-C6HqS4xv.js} +1 -1
  16. package/admin/assets/{FieldBuilder-8VVLG_j0.js → FieldBuilder-36tfpSyM.js} +1 -1
  17. package/admin/assets/{FilterBar-JCp03kkK.js → FilterBar-DhRwTqFv.js} +1 -1
  18. package/admin/assets/{LoginPage-gPNC9XRN.js → LoginPage-DutieANA.js} +1 -1
  19. package/admin/assets/MediaField-J2TLG_fu.js +1 -0
  20. package/admin/assets/{MediaPage-D9763lEk.js → MediaPage-DZZKMGF4.js} +1 -1
  21. package/admin/assets/{RelationshipPicker-D7dFI43Q.js → RelationshipPicker-CDFs4TMW.js} +1 -1
  22. package/admin/assets/SiteSettingsPage-BtCC3RKc.js +1 -0
  23. package/admin/assets/SiteUserEditPage-ClHmp0T-.js +1 -0
  24. package/admin/assets/SiteUsersPage-AyJvcVM7.js +1 -0
  25. package/admin/assets/{SitesPage-BFIZ3Y5K.js → SitesPage-Bw_WBN6v.js} +1 -1
  26. package/admin/assets/SubmissionDetailPage-DS08LGxd.js +1 -0
  27. package/admin/assets/{SubmissionEditPage-PgowJuvq.js → SubmissionEditPage-Brf-DK2X.js} +1 -1
  28. package/admin/assets/{SubmissionListPage-HFDQxPhn.js → SubmissionListPage-DNMzQZHS.js} +1 -1
  29. package/admin/assets/{TagInput-CDkKZboX.js → TagInput-BILCaC9b.js} +1 -1
  30. package/admin/assets/{TagsPage-BW15-W4H.js → TagsPage-DdeZokow.js} +1 -1
  31. package/admin/assets/{UsersPage-C-zlDeTy.js → UsersPage-B0vLxjrg.js} +1 -1
  32. package/admin/assets/{WebhookEditPage-cPPALIbH.js → WebhookEditPage-SlJE4d3z.js} +1 -1
  33. package/admin/assets/{WebhooksPage-vkPC4m9a.js → WebhooksPage-C6lGZLpr.js} +1 -1
  34. package/admin/assets/{card-10FqkZPA.js → card-hXVtlM0q.js} +1 -1
  35. package/admin/assets/{checkbox-fC1QPb_4.js → checkbox-WGrS3sUr.js} +1 -1
  36. package/admin/assets/{command-BeacdV75.js → command-fvBFHye4.js} +1 -1
  37. package/admin/assets/{index-wYNPRVrc.js → index-Cir9tY_P.js} +5 -5
  38. package/admin/assets/index-DACBYsKM.css +1 -0
  39. package/admin/assets/{popover-BJDj8C6y.js → popover-D5_HjjUC.js} +1 -1
  40. package/admin/assets/{select-BV3jemT6.js → select-_uJYxzeZ.js} +1 -1
  41. package/admin/assets/serializeToText-DR_WnxiI.js +2 -0
  42. package/admin/assets/{table-WkEcC9MH.js → table-DLoIbCQ5.js} +1 -1
  43. package/admin/assets/{textarea-CHQ9tT69.js → textarea-vSXNxwTe.js} +1 -1
  44. package/admin/assets/useAdminResolver-D-LlmquD.js +1 -0
  45. package/admin/assets/useContent-e8beBIuq.js +1 -0
  46. package/admin/assets/{useContentSearch-B-_p0_QX.js → useContentSearch-DOjveB9t.js} +1 -1
  47. package/admin/assets/{useMedia-m6zKB__r.js → useMedia-e3sqWm_t.js} +1 -1
  48. package/admin/assets/{usePageTitle-Bwf-MpTD.js → usePageTitle-BNSba9_L.js} +1 -1
  49. package/admin/assets/useSiteUsers-BdnvuM2E.js +1 -0
  50. package/admin/assets/{useTags-CLPWVUB3.js → useTags-f7AVSLuj.js} +1 -1
  51. package/admin/assets/{useWebhooks-no0l3-mF.js → useWebhooks-BH_r8-Mo.js} +1 -1
  52. package/admin/index.html +2 -2
  53. package/admin/sw.js +1 -1
  54. package/dist/cdn.d.ts.map +1 -1
  55. package/dist/cdn.js +179 -19
  56. package/dist/cdn.js.map +1 -1
  57. package/lambda/api/bootstrap +0 -0
  58. package/lambda/webhook-worker/bootstrap +0 -0
  59. package/package.json +1 -1
  60. package/src/cdn.ts +184 -19
  61. package/admin/assets/AllContentPage-C11eeRMt.js +0 -1
  62. package/admin/assets/AuditPage-DJNk7IaW.js +0 -1
  63. package/admin/assets/ContentEditPage-Dj3RK2BF.js +0 -2
  64. package/admin/assets/ContentListPage-CoDanHrR.js +0 -1
  65. package/admin/assets/MediaField-Du7_gRse.js +0 -1
  66. package/admin/assets/SiteSettingsPage-Tfiex2yn.js +0 -1
  67. package/admin/assets/SiteUsersPage-CSV8syR3.js +0 -1
  68. package/admin/assets/SubmissionDetailPage-8vtUQsLd.js +0 -1
  69. package/admin/assets/index-Do_SK4Zl.css +0 -1
  70. package/admin/assets/serializeToText-BJy0Ms5I.js +0 -2
  71. package/admin/assets/useAdminResolver-CpZj93vH.js +0 -1
  72. package/admin/assets/useContent-D8yDRTTy.js +0 -1
  73. package/admin/assets/useSiteUsers-QbiItSH1.js +0 -1
package/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # Headroom CMS
2
2
 
3
- Serverless headless CMS for AWS, deployed with [SST](https://sst.dev).
3
+ Serverless headless CMS for AWS, deployed with [SST v4](https://sst.dev).
4
4
 
5
5
  Headroom provisions a complete CMS stack — DynamoDB, S3, Lambda, CloudFront, Cognito, and an admin UI — from a single SST component. No Go toolchain or build step required; pre-compiled binaries and a pre-built admin UI are included in the package.
6
6
 
7
+ > **Beta**: Headroom is in active development and currently in beta. Expect breaking changes to the configuration interface, infrastructure, and APIs between minor versions. Not yet recommended for production workloads without pinning to an exact version.
8
+
7
9
  ## Quick Start
8
10
 
9
11
  ```bash
@@ -25,7 +27,7 @@ Open the Admin URL and sign in with the credentials you just created.
25
27
 
26
28
  - **Node.js 22+** and **pnpm** (or npm)
27
29
  - **AWS credentials** configured (`aws configure` or environment variables)
28
- - **SST v3** (installed automatically as a dev dependency)
30
+ - **SST v4** (installed automatically as a dev dependency)
29
31
  - **AWS CLI** (for the `create-admin.sh` and `get-token.sh` helper scripts)
30
32
  - **jq** (used by helper scripts to read SST outputs)
31
33
 
@@ -187,95 +189,20 @@ Both scripts read from `.sst/outputs.json`, so you must deploy before running th
187
189
 
188
190
  A single `HeadroomCMS` component creates:
189
191
 
190
- - **11 DynamoDB tables** (sites, content, collections, block types, media, API keys, tags, audit, relationships, webhooks, webhook deliveries)
192
+ - **13 DynamoDB tables** (sites, content, draft content, blocks, media, collections, block types, admin audit, relationships, site users, webhooks, webhook deliveries, scheduler lock)
191
193
  - **1 S3 bucket** (media files and content bodies)
192
194
  - **1 CloudFront KVS** (edge auth cache and site version tracking)
193
195
  - **1 Cognito User Pool + Client** (admin authentication)
194
196
  - **1 SES Email Identity** (admin invitations)
195
- - **4 Lambda functions** (API, webhook worker, image transform, custom message)
197
+ - **5 Lambda functions** (API, webhook worker, image transform, custom message, scheduler)
198
+ - **1 EventBridge schedule** (drives the scheduler Lambda)
196
199
  - **1 CloudFront Distribution** with 2 CloudFront Functions (edge auth, media URL rewrite)
197
200
  - **1 Admin UI** (static site on CloudFront)
198
201
  - **2 SQS queues** (webhook delivery + dead letter queue)
199
202
 
200
- ## Advanced: Forking
201
-
202
- If you need to modify Go API handlers, add custom admin UI pages, change DynamoDB schemas, or make other changes that the configuration options don't cover, you can eject to a full source checkout.
203
-
204
- This is a one-way migration: once ejected, updates come from merging upstream changes rather than `pnpm update`.
205
-
206
- ### When to Eject
207
-
208
- The packaged component covers most use cases. Eject only when you need to:
209
-
210
- - Add custom API endpoints or middleware in the Go Lambda
211
- - Add custom admin UI pages or block editor plugins
212
- - Change DynamoDB table schemas
213
- - Wire additional Lambda functions into the same infrastructure
214
- - Replace a subsystem entirely (e.g., swap Cognito for a different auth provider)
215
-
216
- ### Ejection Steps
217
-
218
- 1. **Clone at your current version:**
219
-
220
- ```bash
221
- git clone --branch v0.1.0 https://github.com/cykod/headroom.git my-cms-custom
222
- cd my-cms-custom
223
- pnpm install
224
- ```
225
-
226
- 2. **Copy your SST state** so SST recognizes existing AWS resources:
227
-
228
- ```bash
229
- cp -r ../my-cms/.sst ./
230
- ```
231
-
232
- 3. **Update `sst.config.ts`** to use local source with the `dev` option:
233
-
234
- ```typescript
235
- /// <reference path="./.sst/platform/config.d.ts" />
236
- import { HeadroomCMS } from "./packages/headroom-cms/src/index.js";
237
-
238
- export default $config({
239
- app(input) {
240
- return {
241
- name: "my-cms", // must match your previous app name
242
- removal: input?.stage === "production" ? "retain" : "remove",
243
- protect: input?.stage === "production",
244
- home: "aws",
245
- };
246
- },
247
- async run() {
248
- const cms = new HeadroomCMS("CMS", {
249
- senderEmail: "cms@mycompany.com",
250
- dev: {
251
- apiHandler: "packages/api",
252
- webhookWorkerHandler: "packages/webhook-worker",
253
- customMessageHandler: "packages/functions/custom-message.handler",
254
- imageLambdaHandler: "packages/image-lambda/index.handler",
255
- adminPath: "packages/admin",
256
- },
257
- });
258
-
259
- return cms.outputs;
260
- },
261
- });
262
- ```
263
-
264
- 4. **Deploy to verify** the state transfer (should be a no-op if config matches):
265
-
266
- ```bash
267
- npx sst deploy --stage production
268
- ```
269
-
270
- 5. **Start customizing.** Key directories:
203
+ ## Advanced: Ejecting
271
204
 
272
- | Directory | What it is |
273
- |-----------|-----------|
274
- | `packages/api/` | Go Lambda API — add routes in `main.go`, handlers in `internal/handler/` |
275
- | `packages/admin/` | React admin UI — add pages in `src/pages/`, components in `src/components/` |
276
- | `packages/headroom-cms/src/` | SST infrastructure component — modify DynamoDB schemas, add resources |
277
- | `packages/image-lambda/` | Sharp image transform Lambda |
278
- | `packages/webhook-worker/` | Webhook delivery worker |
205
+ Ejection to a full source checkout — for customizing Go API handlers, adding admin UI pages, changing DynamoDB schemas, or swapping out subsystems — will be supported in a future release. For now, the packaged component is the only supported entry point; track the changelog for updates.
279
206
 
280
207
  ## License
281
208
 
@@ -1 +1 @@
1
- import{j as e}from"./tanstack-Bs3zYPPV.js";import{u as B,r as x}from"./react-vendor-C2CvUxFh.js";import{u as L,aF as M,aG as q,p as z,aH as G,aI as V,x as J,S as b,D as _,i as $,B as l,aJ as K,k as Q,l as W,m as X,n as Y,I as Z,o as ee,P as se,T as ae,v as i}from"./index-wYNPRVrc.js";import{u as ie}from"./useAdminResolver-CpZj93vH.js";import{T as te,a as ne,b as y,c as p,d as re,e as j}from"./table-WkEcC9MH.js";import{P as oe,a as le,b as de}from"./popover-BJDj8C6y.js";import{C as ce,a as me,b as ue,c as he,d as xe,e as pe}from"./command-BeacdV75.js";import{S as je,a as ve,b as ge,c as fe,d as A}from"./select-BV3jemT6.js";import{u as be}from"./usePageTitle-Bwf-MpTD.js";import"./radix-C1kb_NqW.js";function De(){const{host:d}=B(),{user:C}=L(),S=M(),{data:N,isLoading:I}=q(d),{data:T}=z(),c=G(d),m=V(d),n=N?.admins??[],E=T?.items??[],r=S==="admin",v=n.map(s=>s.id),{resolve:w}=ie(v),[P,g]=x.useState(!1),[D,f]=x.useState(!1),[u,h]=x.useState(""),R=J();if(be({title:"Admins"}),I)return e.jsxs("div",{className:"space-y-2",children:[e.jsx(b,{className:"h-8 w-64"}),Array.from({length:3}).map((s,a)=>e.jsx(b,{className:"h-12 w-full"},a))]});const U=E.filter(s=>!v.includes(s.sub));async function F(s){try{await c.mutateAsync({admins:[...n,{id:s,role:"editor"}]}),i.success("Admin added"),g(!1)}catch(a){i.error("Failed to add admin",{description:a instanceof Error?a.message:void 0})}}async function O(s){if(s.preventDefault(),!!u.trim())try{const a=await m.mutateAsync({email:u.trim()});a.existed?i.success("Existing user added to site"):i.success("Invite email sent",{description:`An invite has been sent to ${a.email}`}),h(""),f(!1)}catch(a){i.error("Failed to invite user",{description:a instanceof Error?a.message:void 0})}}async function H(s){try{await c.mutateAsync({admins:n.filter(a=>a.id!==s)}),i.success("Admin removed")}catch(a){i.error("Failed to remove admin",{description:a instanceof Error?a.message:void 0})}}async function k(s,a){const o=n.map(t=>t.id===s?{...t,role:a}:t);if(!o.some(t=>t.role==="admin")){i.error("At least one admin role is required");return}try{await c.mutateAsync({admins:o}),i.success("Role updated")}catch(t){i.error("Failed to update role",{description:t instanceof Error?t.message:void 0})}}return e.jsxs("div",{children:[!R&&e.jsx("h1",{className:"mb-6 text-2xl font-semibold",children:"Admins"}),r&&e.jsxs("div",{className:"mb-6 flex gap-2",children:[e.jsxs(_,{open:D,onOpenChange:s=>{f(s),s||h("")},children:[e.jsx($,{asChild:!0,children:e.jsxs(l,{children:[e.jsx(K,{className:"mr-2 h-4 w-4"}),"Invite by email"]})}),e.jsxs(Q,{children:[e.jsxs(W,{children:[e.jsx(X,{children:"Invite User to Site"}),e.jsx(Y,{className:"sr-only",children:"Send an invite email to add a user to this site"})]}),e.jsxs("form",{onSubmit:O,className:"space-y-4",children:[e.jsx("p",{className:"text-muted-foreground text-sm",children:"Enter an email address. If the user doesn't have an account yet, they'll receive an invite email."}),e.jsx(Z,{type:"email",value:u,onChange:s=>h(s.target.value),placeholder:"email@example.com",required:!0}),e.jsx(ee,{children:e.jsx(l,{type:"submit",disabled:m.isPending,children:m.isPending?"Inviting...":"Send Invite"})})]})]})]}),e.jsxs(oe,{open:P,onOpenChange:g,children:[e.jsx(le,{asChild:!0,children:e.jsxs(l,{variant:"outline",children:[e.jsx(se,{className:"mr-2 h-4 w-4"}),"Add existing user"]})}),e.jsx(de,{className:"w-72 p-0",align:"start",children:e.jsxs(ce,{children:[e.jsx(me,{placeholder:"Search users..."}),e.jsxs(ue,{children:[e.jsx(he,{children:"No users found."}),e.jsx(xe,{children:U.map(s=>e.jsx(pe,{value:s.email,onSelect:()=>F(s.sub),children:s.email},s.sub))})]})]})})]})]}),n.length===0?e.jsx("p",{className:"text-muted-foreground",children:"No admins configured."}):e.jsxs(te,{children:[e.jsx(ne,{children:e.jsxs(y,{children:[e.jsx(p,{children:"Email"}),e.jsx(p,{children:"Role"}),r&&e.jsx(p,{})]})}),e.jsx(re,{children:n.map(s=>{const a=s.id===C?.sub;return e.jsxs(y,{children:[e.jsxs(j,{className:"text-sm",children:[w(s.id),a&&e.jsx("span",{className:"ml-2 text-muted-foreground",children:"(you)"})]}),e.jsx(j,{children:r&&!a?e.jsxs(je,{value:s.role,onValueChange:o=>k(s.id,o),children:[e.jsx(ve,{className:"w-28",children:e.jsx(ge,{})}),e.jsxs(fe,{children:[e.jsx(A,{value:"admin",children:"Admin"}),e.jsx(A,{value:"editor",children:"Editor"})]})]}):e.jsx("span",{className:"text-sm capitalize",children:s.role})}),r&&e.jsx(j,{className:"text-right",children:!a&&e.jsx(l,{variant:"ghost",size:"sm",onClick:()=>H(s.id),title:"Remove from site",children:e.jsx(ae,{className:"h-4 w-4"})})})]},s.id)})})]})]})}export{De as AdminsPage};
1
+ import{j as e}from"./tanstack-Bs3zYPPV.js";import{u as B,r as x}from"./react-vendor-C2CvUxFh.js";import{u as L,aF as M,aG as q,p as z,aH as G,aI as V,x as J,S as b,D as _,i as $,B as l,aJ as K,k as Q,l as W,m as X,n as Y,I as Z,o as ee,P as se,T as ae,v as i}from"./index-Cir9tY_P.js";import{u as ie}from"./useAdminResolver-D-LlmquD.js";import{T as te,a as ne,b as y,c as p,d as re,e as j}from"./table-DLoIbCQ5.js";import{P as oe,a as le,b as de}from"./popover-D5_HjjUC.js";import{C as ce,a as me,b as ue,c as he,d as xe,e as pe}from"./command-fvBFHye4.js";import{S as je,a as ve,b as ge,c as fe,d as A}from"./select-_uJYxzeZ.js";import{u as be}from"./usePageTitle-BNSba9_L.js";import"./radix-C1kb_NqW.js";function De(){const{host:d}=B(),{user:C}=L(),S=M(),{data:N,isLoading:I}=q(d),{data:T}=z(),c=G(d),m=V(d),n=N?.admins??[],E=T?.items??[],r=S==="admin",v=n.map(s=>s.id),{resolve:w}=ie(v),[P,g]=x.useState(!1),[D,f]=x.useState(!1),[u,h]=x.useState(""),R=J();if(be({title:"Admins"}),I)return e.jsxs("div",{className:"space-y-2",children:[e.jsx(b,{className:"h-8 w-64"}),Array.from({length:3}).map((s,a)=>e.jsx(b,{className:"h-12 w-full"},a))]});const U=E.filter(s=>!v.includes(s.sub));async function F(s){try{await c.mutateAsync({admins:[...n,{id:s,role:"editor"}]}),i.success("Admin added"),g(!1)}catch(a){i.error("Failed to add admin",{description:a instanceof Error?a.message:void 0})}}async function O(s){if(s.preventDefault(),!!u.trim())try{const a=await m.mutateAsync({email:u.trim()});a.existed?i.success("Existing user added to site"):i.success("Invite email sent",{description:`An invite has been sent to ${a.email}`}),h(""),f(!1)}catch(a){i.error("Failed to invite user",{description:a instanceof Error?a.message:void 0})}}async function H(s){try{await c.mutateAsync({admins:n.filter(a=>a.id!==s)}),i.success("Admin removed")}catch(a){i.error("Failed to remove admin",{description:a instanceof Error?a.message:void 0})}}async function k(s,a){const o=n.map(t=>t.id===s?{...t,role:a}:t);if(!o.some(t=>t.role==="admin")){i.error("At least one admin role is required");return}try{await c.mutateAsync({admins:o}),i.success("Role updated")}catch(t){i.error("Failed to update role",{description:t instanceof Error?t.message:void 0})}}return e.jsxs("div",{children:[!R&&e.jsx("h1",{className:"mb-6 text-2xl font-semibold",children:"Admins"}),r&&e.jsxs("div",{className:"mb-6 flex gap-2",children:[e.jsxs(_,{open:D,onOpenChange:s=>{f(s),s||h("")},children:[e.jsx($,{asChild:!0,children:e.jsxs(l,{children:[e.jsx(K,{className:"mr-2 h-4 w-4"}),"Invite by email"]})}),e.jsxs(Q,{children:[e.jsxs(W,{children:[e.jsx(X,{children:"Invite User to Site"}),e.jsx(Y,{className:"sr-only",children:"Send an invite email to add a user to this site"})]}),e.jsxs("form",{onSubmit:O,className:"space-y-4",children:[e.jsx("p",{className:"text-muted-foreground text-sm",children:"Enter an email address. If the user doesn't have an account yet, they'll receive an invite email."}),e.jsx(Z,{type:"email",value:u,onChange:s=>h(s.target.value),placeholder:"email@example.com",required:!0}),e.jsx(ee,{children:e.jsx(l,{type:"submit",disabled:m.isPending,children:m.isPending?"Inviting...":"Send Invite"})})]})]})]}),e.jsxs(oe,{open:P,onOpenChange:g,children:[e.jsx(le,{asChild:!0,children:e.jsxs(l,{variant:"outline",children:[e.jsx(se,{className:"mr-2 h-4 w-4"}),"Add existing user"]})}),e.jsx(de,{className:"w-72 p-0",align:"start",children:e.jsxs(ce,{children:[e.jsx(me,{placeholder:"Search users..."}),e.jsxs(ue,{children:[e.jsx(he,{children:"No users found."}),e.jsx(xe,{children:U.map(s=>e.jsx(pe,{value:s.email,onSelect:()=>F(s.sub),children:s.email},s.sub))})]})]})})]})]}),n.length===0?e.jsx("p",{className:"text-muted-foreground",children:"No admins configured."}):e.jsxs(te,{children:[e.jsx(ne,{children:e.jsxs(y,{children:[e.jsx(p,{children:"Email"}),e.jsx(p,{children:"Role"}),r&&e.jsx(p,{})]})}),e.jsx(re,{children:n.map(s=>{const a=s.id===C?.sub;return e.jsxs(y,{children:[e.jsxs(j,{className:"text-sm",children:[w(s.id),a&&e.jsx("span",{className:"ml-2 text-muted-foreground",children:"(you)"})]}),e.jsx(j,{children:r&&!a?e.jsxs(je,{value:s.role,onValueChange:o=>k(s.id,o),children:[e.jsx(ve,{className:"w-28",children:e.jsx(ge,{})}),e.jsxs(fe,{children:[e.jsx(A,{value:"admin",children:"Admin"}),e.jsx(A,{value:"editor",children:"Editor"})]})]}):e.jsx("span",{className:"text-sm capitalize",children:s.role})}),r&&e.jsx(j,{className:"text-right",children:!a&&e.jsx(l,{variant:"ghost",size:"sm",onClick:()=>H(s.id),title:"Remove from site",children:e.jsx(ae,{className:"h-4 w-4"})})})]},s.id)})})]})]})}export{De as AdminsPage};
@@ -0,0 +1 @@
1
+ import{j as s}from"./tanstack-Bs3zYPPV.js";import{u as U,f as D,r as w}from"./react-vendor-C2CvUxFh.js";import{u as M,a as R,b as L,c as z}from"./useContent-e8beBIuq.js";import{m as k}from"./media-url-DIg_vSyf.js";import{w as E,x as H,v as r,S as F,j as h,y as V,B as _}from"./index-Cir9tY_P.js";import{u as q}from"./usePageTitle-BNSba9_L.js";import{C as G,c as J}from"./card-hXVtlM0q.js";import{C as m}from"./checkbox-WGrS3sUr.js";import{T as K,a as O,b as S,c as i,d as Q,e as d}from"./table-DLoIbCQ5.js";import{f as y}from"./format-C88SDH8g.js";import{B as W}from"./BulkActionBar-TRiXXLQd.js";import"./radix-C1kb_NqW.js";function ie(){const{host:c}=U(),p=D(),{collections:A}=E(),f=H();q({title:"Recent"});const[$,P]=w.useState(),[n,a]=w.useState(new Set),{data:o,isLoading:I}=M(c,$),j=R(c),g=L(c),b=z(c),N=new Map(A.map(e=>[e.name,e.label])),x=o?.items.map(e=>e.contentId)??[],v=x.length>0&&x.every(e=>n.has(e));function C(e){a(t=>{const l=new Set(t);return l.has(e)?l.delete(e):l.add(e),l})}function B(){a(v?new Set:new Set(x))}const T=j.isPending||g.isPending||b.isPending;return s.jsxs("div",{children:[!f&&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."})]}),n.size>0&&s.jsx(W,{selectedCount:n.size,onPublish:async()=>{const e=[...n],l=(await j.mutateAsync(e)).filter(u=>u.status==="rejected").length;l?r.error(`${l} of ${e.length} failed to publish`):r.success(`${e.length} item(s) published`),a(new Set)},onUnpublish:async()=>{const e=[...n],l=(await g.mutateAsync(e)).filter(u=>u.status==="rejected").length;l?r.error(`${l} of ${e.length} failed to unpublish`):r.success(`${e.length} item(s) unpublished`),a(new Set)},onDelete:async()=>{const e=[...n],l=(await b.mutateAsync(e)).filter(u=>u.status==="rejected").length;l?r.error(`${l} of ${e.length} failed to delete`):r.success(`${e.length} item(s) deleted`),a(new Set)},onClear:()=>a(new Set),isPending:T}),I?s.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((e,t)=>s.jsx(F,{className:"h-12 w-full"},t))}):o?.items.length?s.jsxs(s.Fragment,{children:[f?s.jsx("div",{className:"grid gap-3","data-testid":"all-content-card-view",children:o.items.map(e=>{const t=e.cover;return s.jsx(G,{className:V("cursor-pointer gap-0 overflow-hidden py-0 transition-shadow hover:shadow-md",n.has(e.contentId)&&"ring-2 ring-primary"),onClick:()=>p(`/sites/${c}/content/${e.collection}/${e.contentId}?from=recent`),children:s.jsx(J,{className:"p-3",children:s.jsxs("div",{className:"flex items-start gap-3 min-w-0",children:[t?.url&&s.jsx("img",{src:k(t.url),alt:t.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(h,{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(h,{variant:"outline",className:"text-[10px] px-1.5 py-0",children:N.get(e.collection)??e.collection}),s.jsx("span",{className:"text-xs text-muted-foreground",children:e.publishedAt?y(e.publishedAt):"—"})]})]}),s.jsx(m,{checked:n.has(e.contentId),onCheckedChange:()=>C(e.contentId),onClick:l=>l.stopPropagation(),className:"mt-1"})]})})},e.contentId)})}):s.jsxs(K,{children:[s.jsx(O,{children:s.jsxs(S,{children:[s.jsx(i,{className:"w-10",children:s.jsx(m,{checked:v,onCheckedChange:B,"aria-label":"Select all"})}),s.jsx(i,{children:"Title"}),s.jsx(i,{children:"Slug"}),s.jsx(i,{children:"Collection"}),s.jsx(i,{children:"Status"}),s.jsx(i,{children:"Updated"})]})}),s.jsx(Q,{children:o.items.map(e=>s.jsxs(S,{className:"cursor-pointer",onClick:()=>p(`/sites/${c}/content/${e.collection}/${e.contentId}?from=recent`),children:[s.jsx(d,{onClick:t=>t.stopPropagation(),children:s.jsx(m,{checked:n.has(e.contentId),onCheckedChange:()=>C(e.contentId),"aria-label":`Select ${e.title||"Untitled"}`})}),s.jsx(d,{className:"font-medium",children:s.jsxs("div",{className:"flex items-center gap-3",children:[(()=>{const t=e.cover;return t?.url?s.jsx("img",{src:k(t.url),alt:t.alt??"",className:"h-8 w-8 rounded object-cover flex-shrink-0"}):null})(),s.jsx("span",{children:e.title||"Untitled"})]})}),s.jsx(d,{className:"text-muted-foreground text-sm",children:e.slug||"—"}),s.jsx(d,{children:s.jsx(h,{variant:"outline",children:N.get(e.collection)??e.collection})}),s.jsx(d,{children:s.jsx(h,{variant:e.publishedAt?"default":"secondary",children:e.publishedAt?"Published":"Draft"})}),s.jsx(d,{className:"text-muted-foreground",children:e.publishedAt?y(e.publishedAt):"—"})]},e.contentId))})]}),o.hasMore&&s.jsx("div",{className:"mt-4 flex justify-center",children:s.jsx(_,{variant:"outline",onClick:()=>P(o.cursor??void 0),children:"Load More"})})]}):s.jsx("p",{className:"text-muted-foreground",children:"No content yet."})]})}export{ie as AllContentPage};
@@ -1 +1 @@
1
- import{u as E,a as A,b as K,j as e}from"./tanstack-Bs3zYPPV.js";import{u as O,r as m}from"./react-vendor-C2CvUxFh.js";import{e as f,x as G,B as i,P as g,S as Q,T as R,D,k as I,l as w,m as P,n as T,I as k,af as $,o as p,L as z,v as x}from"./index-wYNPRVrc.js";import{T as B,a as H,b as C,c as d,d as M,e as u}from"./table-WkEcC9MH.js";import{f as N}from"./format-C88SDH8g.js";import{u as U}from"./usePageTitle-Bwf-MpTD.js";import"./radix-C1kb_NqW.js";function J(s){const t=f();return E({queryKey:["sites",s,"api-keys"],queryFn:async()=>({items:(await t.apiFetch(`/v1/admin/sites/${s}/api-keys`)).keys}),enabled:!!s})}function Y(s){const t=f(),n=A();return K({mutationFn:l=>t.apiFetch(`/v1/admin/sites/${s}/api-keys`,{method:"POST",body:JSON.stringify(l)}),onSuccess:()=>n.invalidateQueries({queryKey:["sites",s,"api-keys"]})})}function _(s,t){const n=f(),l=A();return K({mutationFn:()=>n.apiFetch(`/v1/admin/sites/${s}/api-keys/${t}`,{method:"DELETE"}),onSuccess:()=>l.invalidateQueries({queryKey:["sites",s,"api-keys"]})})}function ne(){const{host:s}=O(),{data:t,isLoading:n}=J(s),l=Y(s),[h,r]=m.useState(!1),[b,y]=m.useState(""),[o,j]=m.useState(null),[F,v]=m.useState(null),S=G();U({title:"API Keys",actions:e.jsx(i,{size:"sm",onClick:()=>r(!0),children:e.jsx(g,{className:"h-4 w-4"})})});async function L(a){a.preventDefault();try{const c=await l.mutateAsync({label:b});j(c.key),y("")}catch(c){x.error("Failed to create API key",{description:c instanceof Error?c.message:void 0})}}function q(){o&&(navigator.clipboard.writeText(o),x.success("Copied to clipboard"))}return e.jsxs("div",{children:[!S&&e.jsxs("div",{className:"mb-6 flex items-center justify-between",children:[e.jsx("h1",{className:"text-2xl font-semibold",children:"API Keys"}),e.jsxs(i,{onClick:()=>r(!0),children:[e.jsx(g,{className:"mr-2 h-4 w-4"}),"Generate Key"]})]}),n?e.jsx("div",{className:"space-y-2",children:Array.from({length:3}).map((a,c)=>e.jsx(Q,{className:"h-12 w-full"},c))}):t?.items.length?e.jsxs(B,{children:[e.jsx(H,{children:e.jsxs(C,{children:[e.jsx(d,{children:"Label"}),e.jsx(d,{children:"Key ID"}),e.jsx(d,{children:"Created"}),e.jsx(d,{children:"Last Used"}),e.jsx(d,{})]})}),e.jsx(M,{children:t.items.map(a=>e.jsxs(C,{children:[e.jsx(u,{className:"font-medium",children:a.label}),e.jsx(u,{className:"font-mono text-xs",children:a.keyId}),e.jsx(u,{className:"text-muted-foreground",children:N(a.createdAt)}),e.jsx(u,{className:"text-muted-foreground",children:a.lastUsedAt?N(a.lastUsedAt):"Never"}),e.jsx(u,{children:e.jsx(i,{variant:"ghost",size:"sm",onClick:()=>v(a.keyId),children:e.jsx(R,{className:"h-4 w-4"})})})]},a.keyId))})]}):e.jsx("p",{className:"text-muted-foreground",children:"No API keys."}),e.jsx(D,{open:h,onOpenChange:a=>{r(a),a||(j(null),y(""))},children:e.jsxs(I,{children:[e.jsxs(w,{children:[e.jsx(P,{children:o?"API Key Generated":"Generate API Key"}),e.jsx(T,{className:"sr-only",children:"Create a new API key for site access"})]}),o?e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Copy this key now. You won't be able to see it again."}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(k,{value:o,readOnly:!0,className:"font-mono text-xs"}),e.jsx(i,{variant:"outline",size:"icon",onClick:q,children:e.jsx($,{className:"h-4 w-4"})})]}),e.jsx(p,{children:e.jsx(i,{onClick:()=>{r(!1),j(null)},children:"Done"})})]}):e.jsxs("form",{onSubmit:L,className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(z,{htmlFor:"key-label",children:"Label"}),e.jsx(k,{id:"key-label",value:b,onChange:a=>y(a.target.value),required:!0,autoFocus:!0})]}),e.jsxs(p,{children:[e.jsx(i,{variant:"outline",onClick:()=>r(!1),children:"Cancel"}),e.jsx(i,{type:"submit",disabled:l.isPending,children:"Generate"})]})]})]})}),e.jsx(V,{host:s,keyId:F,onClose:()=>v(null)})]})}function V({host:s,keyId:t,onClose:n}){const l=_(s,t??"");async function h(){try{await l.mutateAsync(),x.success("API key revoked"),n()}catch(r){x.error("Failed to revoke",{description:r instanceof Error?r.message:void 0})}}return e.jsx(D,{open:!!t,onOpenChange:()=>n(),children:e.jsxs(I,{children:[e.jsxs(w,{children:[e.jsx(P,{children:"Revoke API key?"}),e.jsx(T,{children:"This action cannot be undone. Any applications using this key will lose access."})]}),e.jsxs(p,{children:[e.jsx(i,{variant:"outline",onClick:n,children:"Cancel"}),e.jsx(i,{variant:"destructive",onClick:h,children:"Revoke"})]})]})})}export{ne as ApiKeysPage};
1
+ import{u as E,a as A,b as K,j as e}from"./tanstack-Bs3zYPPV.js";import{u as O,r as m}from"./react-vendor-C2CvUxFh.js";import{e as f,x as G,B as i,P as g,S as Q,T as R,D,k as I,l as w,m as P,n as T,I as k,af as $,o as p,L as z,v as x}from"./index-Cir9tY_P.js";import{T as B,a as H,b as C,c as d,d as M,e as u}from"./table-DLoIbCQ5.js";import{f as N}from"./format-C88SDH8g.js";import{u as U}from"./usePageTitle-BNSba9_L.js";import"./radix-C1kb_NqW.js";function J(s){const t=f();return E({queryKey:["sites",s,"api-keys"],queryFn:async()=>({items:(await t.apiFetch(`/v1/admin/sites/${s}/api-keys`)).keys}),enabled:!!s})}function Y(s){const t=f(),n=A();return K({mutationFn:l=>t.apiFetch(`/v1/admin/sites/${s}/api-keys`,{method:"POST",body:JSON.stringify(l)}),onSuccess:()=>n.invalidateQueries({queryKey:["sites",s,"api-keys"]})})}function _(s,t){const n=f(),l=A();return K({mutationFn:()=>n.apiFetch(`/v1/admin/sites/${s}/api-keys/${t}`,{method:"DELETE"}),onSuccess:()=>l.invalidateQueries({queryKey:["sites",s,"api-keys"]})})}function ne(){const{host:s}=O(),{data:t,isLoading:n}=J(s),l=Y(s),[h,r]=m.useState(!1),[b,y]=m.useState(""),[o,j]=m.useState(null),[F,v]=m.useState(null),S=G();U({title:"API Keys",actions:e.jsx(i,{size:"sm",onClick:()=>r(!0),children:e.jsx(g,{className:"h-4 w-4"})})});async function L(a){a.preventDefault();try{const c=await l.mutateAsync({label:b});j(c.key),y("")}catch(c){x.error("Failed to create API key",{description:c instanceof Error?c.message:void 0})}}function q(){o&&(navigator.clipboard.writeText(o),x.success("Copied to clipboard"))}return e.jsxs("div",{children:[!S&&e.jsxs("div",{className:"mb-6 flex items-center justify-between",children:[e.jsx("h1",{className:"text-2xl font-semibold",children:"API Keys"}),e.jsxs(i,{onClick:()=>r(!0),children:[e.jsx(g,{className:"mr-2 h-4 w-4"}),"Generate Key"]})]}),n?e.jsx("div",{className:"space-y-2",children:Array.from({length:3}).map((a,c)=>e.jsx(Q,{className:"h-12 w-full"},c))}):t?.items.length?e.jsxs(B,{children:[e.jsx(H,{children:e.jsxs(C,{children:[e.jsx(d,{children:"Label"}),e.jsx(d,{children:"Key ID"}),e.jsx(d,{children:"Created"}),e.jsx(d,{children:"Last Used"}),e.jsx(d,{})]})}),e.jsx(M,{children:t.items.map(a=>e.jsxs(C,{children:[e.jsx(u,{className:"font-medium",children:a.label}),e.jsx(u,{className:"font-mono text-xs",children:a.keyId}),e.jsx(u,{className:"text-muted-foreground",children:N(a.createdAt)}),e.jsx(u,{className:"text-muted-foreground",children:a.lastUsedAt?N(a.lastUsedAt):"Never"}),e.jsx(u,{children:e.jsx(i,{variant:"ghost",size:"sm",onClick:()=>v(a.keyId),children:e.jsx(R,{className:"h-4 w-4"})})})]},a.keyId))})]}):e.jsx("p",{className:"text-muted-foreground",children:"No API keys."}),e.jsx(D,{open:h,onOpenChange:a=>{r(a),a||(j(null),y(""))},children:e.jsxs(I,{children:[e.jsxs(w,{children:[e.jsx(P,{children:o?"API Key Generated":"Generate API Key"}),e.jsx(T,{className:"sr-only",children:"Create a new API key for site access"})]}),o?e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Copy this key now. You won't be able to see it again."}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(k,{value:o,readOnly:!0,className:"font-mono text-xs"}),e.jsx(i,{variant:"outline",size:"icon",onClick:q,children:e.jsx($,{className:"h-4 w-4"})})]}),e.jsx(p,{children:e.jsx(i,{onClick:()=>{r(!1),j(null)},children:"Done"})})]}):e.jsxs("form",{onSubmit:L,className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(z,{htmlFor:"key-label",children:"Label"}),e.jsx(k,{id:"key-label",value:b,onChange:a=>y(a.target.value),required:!0,autoFocus:!0})]}),e.jsxs(p,{children:[e.jsx(i,{variant:"outline",onClick:()=>r(!1),children:"Cancel"}),e.jsx(i,{type:"submit",disabled:l.isPending,children:"Generate"})]})]})]})}),e.jsx(V,{host:s,keyId:F,onClose:()=>v(null)})]})}function V({host:s,keyId:t,onClose:n}){const l=_(s,t??"");async function h(){try{await l.mutateAsync(),x.success("API key revoked"),n()}catch(r){x.error("Failed to revoke",{description:r instanceof Error?r.message:void 0})}}return e.jsx(D,{open:!!t,onOpenChange:()=>n(),children:e.jsxs(I,{children:[e.jsxs(w,{children:[e.jsx(P,{children:"Revoke API key?"}),e.jsx(T,{children:"This action cannot be undone. Any applications using this key will lose access."})]}),e.jsxs(p,{children:[e.jsx(i,{variant:"outline",onClick:n,children:"Cancel"}),e.jsx(i,{variant:"destructive",onClick:h,children:"Revoke"})]})]})})}export{ne as ApiKeysPage};
@@ -0,0 +1 @@
1
+ import{u as F,j as e}from"./tanstack-Bs3zYPPV.js";import{L,r as i,u as E}from"./react-vendor-C2CvUxFh.js";import{e as O,F as K,G as V,J as W,K as q,B as R,au as H,S as y,x as J,aK as z,aJ as v,aL as G,aM as Q,aN as X,aO as Y,aP as Z,aQ as ee,aR as te,aS as se,al as S,aT as ae,T as x,$ as m,aE as le,P as A,aU as U,ai as re,aV as de,aW as ne,aX as oe,a4 as ce,aY as ie,aZ as ue}from"./index-Cir9tY_P.js";import{u as me}from"./useAdminResolver-D-LlmquD.js";import{s as _,T as he}from"./serializeToText-DR_WnxiI.js";import{h as T}from"./useContent-e8beBIuq.js";import{f as P,a as xe}from"./format-C88SDH8g.js";import{S as be,a as pe,b as fe,c as ge,d as je}from"./select-_uJYxzeZ.js";import{T as ke,a as Ie,b as D,c as p,d as ye,e as f}from"./table-DLoIbCQ5.js";import{u as Ce}from"./usePageTitle-BNSba9_L.js";import"./radix-C1kb_NqW.js";function we(t,a){const l=O(),d=new URLSearchParams;a?.action&&d.set("action",a.action),a?.before&&d.set("before",String(a.before));const o=d.toString();return F({queryKey:["sites",t,"audit",a?.action??"",a?.before??""],queryFn:()=>l.apiFetch(`/v1/admin/sites/${t}/audit${o?`?${o}`:""}`),enabled:!!t})}const Ne={"content.create":"Content Created","content.update":"Content Updated","content.publish":"Content Published","content.unpublish":"Content Unpublished","content.delete":"Content Deleted","content.schedule":"Content Scheduled","content.unschedule":"Content Unscheduled","content.update_publish_date":"Publish Date Changed","content.discard":"Draft Discarded","media.create":"Media Uploaded","media.update":"Media Updated","media.delete":"Media Deleted","media.bulk":"Bulk Media Operation","media.folder.create":"Folder Created","media.folder.update":"Folder Renamed","media.folder.delete":"Folder Deleted","collection.create":"Collection Created","collection.update":"Collection Updated","collection.delete":"Collection Deleted","blocktype.create":"Block Type Created","blocktype.update":"Block Type Updated","blocktype.delete":"Block Type Deleted","webhook.create":"Webhook Created","webhook.update":"Webhook Updated","webhook.delete":"Webhook Deleted","webhook.rotate_secret":"Webhook Secret Rotated","webhook.retry_delivery":"Delivery Retried","apikey.create":"API Key Created","apikey.revoke":"API Key Revoked","site.archived":"Site Archived","site.unarchived":"Site Unarchived","site.purged":"Site Purged","site_user.create":"User Created","site_user.update":"User Updated","site_user.delete":"User Deleted","site_user.change_email":"User Email Changed","site_user.self_register":"User Self-Registered","site_user.self_update":"User Updated Profile"};function ve(t){return!!t?.blockId&&!!t?.prevBlockId&&!!t?.resourceId}function Se({host:t,details:a}){const l=a.resourceId,d=a.collection??"",{data:o}=H(t,d),{data:s,isLoading:b}=T(t,l,a.blockId??null),{data:n,isLoading:u}=T(t,l,a.prevBlockId??null),c=i.useMemo(()=>o?.fields??[],[o?.fields]),g=i.useMemo(()=>{if(!s)return[];const h={title:s.title,slug:s.slug,snippet:s.snippet,tags:s.tags};return _(c,s.body??{},h)},[s,c]),j=i.useMemo(()=>{if(!n)return[];const h={title:n.title,slug:n.slug,snippet:n.snippet,tags:n.tags};return _(c,n.body??{},h)},[n,c]);return b||u?e.jsxs("div",{className:"space-y-2","data-testid":"diff-loading",children:[e.jsx(y,{className:"h-6 w-24"}),e.jsx(y,{className:"h-40 w-full"})]}):!s||!n?e.jsx("p",{className:"text-muted-foreground text-sm","data-testid":"diff-unavailable",children:"Version data unavailable."}):e.jsxs("div",{"data-testid":"diff-view",children:[e.jsx("h3",{className:"mb-2 text-sm font-medium",children:"Changes"}),e.jsx(he,{left:j,right:g,leftLabel:"Before",rightLabel:"After"})]})}function Ae({open:t,onOpenChange:a,event:l,host:d,resolveAdmin:o}){if(!l)return null;const s=l.details,b=Ne[l.action]??l.action,n=ve(s),u=s?.resourceType==="content"&&s?.resourceId&&s?.collection?`/sites/${d}/content/${s.collection}/${s.resourceId}`:null;return e.jsx(K,{open:t,onOpenChange:a,children:e.jsxs(V,{className:"w-full overflow-y-auto px-6 sm:max-w-lg","data-testid":"audit-drawer",children:[e.jsx(W,{children:e.jsx(q,{children:b})}),e.jsxs("div",{className:"mt-4 space-y-4",children:[e.jsxs("dl",{className:"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm",children:[s?.title&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-muted-foreground",children:"Resource"}),e.jsx("dd",{className:"font-medium","data-testid":"drawer-resource",children:s.title})]}),s?.collection&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-muted-foreground",children:"Collection"}),e.jsx("dd",{children:s.collection})]}),e.jsx("dt",{className:"text-muted-foreground",children:"Admin"}),e.jsx("dd",{children:o(l.adminId)}),e.jsx("dt",{className:"text-muted-foreground",children:"Time"}),e.jsx("dd",{children:P(l.createdAt)}),e.jsx("dt",{className:"text-muted-foreground",children:"Status"}),e.jsx("dd",{children:e.jsx("span",{className:l.status==="success"?"text-green-600":l.status==="failed"?"text-red-600":"text-yellow-600",children:l.status})}),s?.ipAddress&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-muted-foreground",children:"IP Address"}),e.jsx("dd",{className:"font-mono text-xs",children:s.ipAddress})]}),s?.extra&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-muted-foreground",children:"Details"}),e.jsx("dd",{className:"text-muted-foreground",children:s.extra})]})]}),s&&e.jsxs("details",{className:"text-sm","data-testid":"drawer-json",children:[e.jsx("summary",{className:"text-muted-foreground cursor-pointer select-none",children:"Raw details"}),e.jsx("pre",{className:"bg-muted mt-2 overflow-x-auto rounded p-3 text-xs",children:JSON.stringify(s,null,2)})]}),l.errorMsg&&e.jsx("div",{className:"rounded border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-900 dark:bg-red-950 dark:text-red-300","data-testid":"drawer-error",children:l.errorMsg}),u&&e.jsx(R,{variant:"outline",size:"sm",asChild:!0,children:e.jsx(L,{to:u,children:"View content"})}),n&&s&&e.jsx("div",{className:"border-t pt-4",children:e.jsx(Se,{host:d,details:s})}),!n&&s?.resourceType==="content"&&e.jsx("p",{className:"text-muted-foreground text-sm","data-testid":"no-changes",children:"No change comparison available for this event."})]})]})})}const Ue={"content.create":{label:"Created content",Icon:A},"content.update":{label:"Updated content",Icon:m},"content.publish":{label:"Published content",Icon:ue},"content.unpublish":{label:"Unpublished content",Icon:ie},"content.delete":{label:"Deleted content",Icon:x},"content.schedule":{label:"Scheduled content",Icon:ce},"content.unschedule":{label:"Unscheduled content",Icon:oe},"content.update_publish_date":{label:"Changed publish date",Icon:ne},"content.discard":{label:"Discarded draft",Icon:de},"media.create":{label:"Uploaded media",Icon:re},"media.update":{label:"Updated media",Icon:m},"media.delete":{label:"Deleted media",Icon:x},"media.bulk":{label:"Bulk media operation",Icon:S},"media.folder.create":{label:"Created folder",Icon:U},"media.folder.update":{label:"Renamed folder",Icon:m},"media.folder.delete":{label:"Deleted folder",Icon:x},"collection.create":{label:"Created collection",Icon:U},"collection.update":{label:"Updated collection",Icon:m},"collection.delete":{label:"Deleted collection",Icon:x},"blocktype.create":{label:"Created block type",Icon:A},"blocktype.update":{label:"Updated block type",Icon:m},"blocktype.delete":{label:"Deleted block type",Icon:x},"webhook.create":{label:"Created webhook",Icon:le},"webhook.update":{label:"Updated webhook",Icon:m},"webhook.delete":{label:"Deleted webhook",Icon:x},"webhook.rotate_secret":{label:"Rotated webhook secret",Icon:ae},"webhook.retry_delivery":{label:"Retried delivery",Icon:S},"apikey.create":{label:"Created API key",Icon:se},"apikey.revoke":{label:"Revoked API key",Icon:te},"site.archived":{label:"Archived site",Icon:ee},"site.unarchived":{label:"Unarchived site",Icon:Z},"site.purged":{label:"Purged site",Icon:Y},"site_user.create":{label:"Created user",Icon:v},"site_user.update":{label:"Updated user",Icon:X},"site_user.delete":{label:"Deleted user",Icon:Q},"site_user.change_email":{label:"Changed user email",Icon:G},"site_user.self_register":{label:"User registered",Icon:v},"site_user.self_update":{label:"User updated profile",Icon:z}},_e=[{label:"All",value:"all"},{label:"Content",value:"content."},{label:"Media",value:"media."},{label:"Collections",value:"collection."},{label:"Block Types",value:"blocktype."},{label:"Webhooks",value:"webhook."},{label:"API Keys",value:"apikey."},{label:"Sites",value:"site."},{label:"Site Users",value:"site_user."}];function Te(t){return Ue[t]??{label:t,Icon:m}}function De(t,a){const l=a.resourceType??a.details?.resourceType,d=a.resourceId??a.details?.resourceId;if(!l||!d)return null;switch(l){case"content":{const o=a.details?.collection;return o?`/sites/${t}/content/${o}/${d}`:`/sites/${t}/content`}case"media":return`/sites/${t}/media`;case"collection":return`/sites/${t}/settings/collections`;case"webhook":return`/sites/${t}/settings/webhooks`;case"site_user":return`/sites/${t}/settings/site-users/${d}`;default:return null}}function Le({status:t}){const a=t==="success"?"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400":t==="failed"?"bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400":"bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400";return e.jsx("span",{className:`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${a}`,children:t})}function qe(){const{host:t}=E(),[a,l]=i.useState(),[d,o]=i.useState("all"),[s,b]=i.useState(null),[n,u]=i.useState(!1),{data:c,isLoading:g}=we(t,{before:a}),j=c?.items.map(r=>r.adminId)??[],{resolve:h}=me(j),$=J(),B=i.useCallback(r=>{b(r),u(!0)},[]);Ce({title:"Audit Log"});const C=d!=="all"?c?.items.filter(r=>r.action.startsWith(d)):c?.items;return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-6 flex items-center justify-between gap-4",children:[!$&&e.jsx("h1",{className:"text-2xl font-semibold",children:"Audit Log"}),e.jsxs(be,{value:d,onValueChange:o,children:[e.jsx(pe,{className:"w-[180px]","data-testid":"action-filter",children:e.jsx(fe,{placeholder:"Filter by type"})}),e.jsx(ge,{children:_e.map(r=>e.jsx(je,{value:r.value,children:r.label},r.value))})]})]}),g?e.jsx("div",{className:"space-y-2",children:Array.from({length:5}).map((r,k)=>e.jsx(y,{className:"h-12 w-full"},k))}):C?.length?e.jsxs(e.Fragment,{children:[e.jsxs(ke,{children:[e.jsx(Ie,{children:e.jsxs(D,{children:[e.jsx(p,{children:"Action"}),e.jsx(p,{children:"Resource"}),e.jsx(p,{children:"Admin"}),e.jsx(p,{children:"Status"}),e.jsx(p,{children:"Time"})]})}),e.jsx(ye,{children:C.map(r=>{const{label:k,Icon:M}=Te(r.action),I=r.details?.title,w=r.details?.collection,N=t?De(t,r):null;return e.jsxs(D,{"data-testid":"audit-row",className:"cursor-pointer",onClick:()=>B(r),children:[e.jsx(f,{children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(M,{className:"text-muted-foreground h-4 w-4 shrink-0"}),e.jsx("span",{className:"font-medium",children:k})]})}),e.jsx(f,{children:I?e.jsxs("div",{className:"flex items-center gap-2",children:[N?e.jsx(L,{to:N,className:"text-primary hover:underline",children:I}):e.jsx("span",{children:I}),w&&e.jsx("span",{className:"bg-muted text-muted-foreground rounded px-1.5 py-0.5 text-xs",children:w})]}):e.jsx("span",{className:"text-muted-foreground",children:"-"})}),e.jsx(f,{className:"text-sm",children:h(r.adminId)}),e.jsx(f,{children:e.jsx(Le,{status:r.status})}),e.jsx(f,{className:"text-muted-foreground",title:P(r.createdAt),children:xe(r.createdAt)})]},r.eventId)})})]}),c?.hasMore&&c.items.length>0&&e.jsx("div",{className:"mt-4 flex justify-center",children:e.jsx(R,{variant:"outline",onClick:()=>l(c.items[c.items.length-1].createdAt),children:"Load More"})})]}):e.jsx("p",{className:"text-muted-foreground",children:"No audit events."}),e.jsx(Ae,{open:n,onOpenChange:u,event:s,host:t,resolveAdmin:h})]})}export{qe as AuditPage};