@bobbykim/manguito-cms-admin 0.4.3 → 0.5.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/dist/assets/{ChangePasswordView-BILytTnH.js → ChangePasswordView-D-B7xv5c.js} +1 -1
- package/dist/assets/ContentFormView-Bfee-uVL.js +1 -0
- package/dist/assets/{ContentListView-CWHYBV23.js → ContentListView-BpgXHLa6.js} +1 -1
- package/dist/assets/{ContentSettingsView-B9BHm-xg.js → ContentSettingsView-CuuxtUQh.js} +1 -1
- package/dist/assets/{LoginView-8tF3SdN4.js → LoginView-BdqDyYJ6.js} +1 -1
- package/dist/assets/{MediaDetailView-HfRoV5W8.js → MediaDetailView-DmKNv8bW.js} +1 -1
- package/dist/assets/MediaLibraryView-OGPHji7F.js +1 -0
- package/dist/assets/MediaThumbnail-q7pxungQ.js +1 -0
- package/dist/assets/TaxonomyFormView-Dzaz47pa.js +1 -0
- package/dist/assets/{TaxonomyListView-DKnsY_ab.js → TaxonomyListView-kaf2LX5v.js} +1 -1
- package/dist/assets/{UserFormView-DhH0m-Vq.js → UserFormView-KlTIvn2s.js} +1 -1
- package/dist/assets/{UserListView-Dk3Jv2Z8.js → UserListView-_HSsX1vW.js} +1 -1
- package/dist/assets/{ComputedDisplay-Df_HvjzX.js → field-defaults-m6kJphku.js} +2 -2
- package/dist/assets/{index-ivedPYqQ.css → index-C4qBpxpk.css} +1 -1
- package/dist/assets/{index-C-iAN6wp.js → index-DHBhcS6-.js} +2 -2
- package/dist/assets/{useNotification-kY57Myug.js → useNotification-B8AtuEWL.js} +1 -1
- package/dist/codegen/index.cjs +7 -0
- package/dist/codegen/index.js +7 -0
- package/dist/index.html +2 -2
- package/package.json +3 -3
- package/src/components/fields/MediaUpload.vue +5 -19
- package/src/components/fields/ParagraphEmbed.vue +108 -45
- package/src/components/fields/ReferenceSelect.vue +2 -2
- package/src/components/fields/__tests__/ParagraphEmbed.test.ts +64 -0
- package/src/components/fields/__tests__/ReferenceSelect.test.ts +19 -0
- package/src/components/shared/MediaSelectModal.vue +4 -21
- package/src/components/shared/MediaThumbnail.vue +108 -0
- package/src/components/shared/__tests__/MediaThumbnail.test.ts +118 -0
- package/src/composables/__tests__/useFormValidation.test.ts +27 -0
- package/src/utils/__tests__/field-defaults.test.ts +26 -0
- package/src/utils/__tests__/file-kind.test.ts +102 -0
- package/src/utils/__tests__/taxonomy-form.test.ts +63 -0
- package/src/utils/field-defaults.ts +31 -0
- package/src/utils/file-kind.ts +83 -0
- package/src/utils/taxonomy-form.ts +28 -0
- package/src/views/content/ContentFormView.vue +1 -32
- package/src/views/media/MediaLibraryView.vue +7 -22
- package/src/views/taxonomy/TaxonomyFormView.vue +2 -27
- package/dist/assets/ContentFormView-BsTU-zzP.js +0 -1
- package/dist/assets/MediaLibraryView-COQmdQPB.js +0 -1
- package/dist/assets/TaxonomyFormView-BibZ2qjc.js +0 -1
- package/dist/assets/useTabIndicator-CvEsGBJh.js +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// What a non-image, non-video media file looks like as a thumbnail: a short
|
|
2
|
+
// type label and a colour for its badge. Derived from the MIME type stored with
|
|
3
|
+
// the media item; the URL's extension is the fallback for types not listed.
|
|
4
|
+
|
|
5
|
+
export type FileTone = 'red' | 'blue' | 'green' | 'orange' | 'gray'
|
|
6
|
+
|
|
7
|
+
export type FileKind = { label: string; tone: FileTone }
|
|
8
|
+
|
|
9
|
+
// Tailwind background class for each badge tone.
|
|
10
|
+
export const TONE_CLASS: Record<FileTone, string> = {
|
|
11
|
+
red: 'bg-red-600',
|
|
12
|
+
blue: 'bg-blue-600',
|
|
13
|
+
green: 'bg-green-600',
|
|
14
|
+
orange: 'bg-orange-500',
|
|
15
|
+
gray: 'bg-gray-500',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Checked in order; the first match wins. CSV sits before the generic text/*
|
|
19
|
+
// rule so it reads as a spreadsheet, not as plain text.
|
|
20
|
+
const RULES: Array<{ test: (mime: string) => boolean; kind: FileKind }> = [
|
|
21
|
+
{ test: (m) => m === 'application/pdf', kind: { label: 'PDF', tone: 'red' } },
|
|
22
|
+
{
|
|
23
|
+
test: (m) =>
|
|
24
|
+
m === 'application/msword' ||
|
|
25
|
+
m === 'application/rtf' ||
|
|
26
|
+
m.includes('wordprocessingml') ||
|
|
27
|
+
m === 'application/vnd.oasis.opendocument.text',
|
|
28
|
+
kind: { label: 'DOC', tone: 'blue' },
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
test: (m) =>
|
|
32
|
+
m === 'application/vnd.ms-excel' ||
|
|
33
|
+
m === 'text/csv' ||
|
|
34
|
+
m.includes('spreadsheetml') ||
|
|
35
|
+
m === 'application/vnd.oasis.opendocument.spreadsheet',
|
|
36
|
+
kind: { label: 'XLS', tone: 'green' },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
test: (m) =>
|
|
40
|
+
m === 'application/vnd.ms-powerpoint' ||
|
|
41
|
+
m.includes('presentationml') ||
|
|
42
|
+
m === 'application/vnd.oasis.opendocument.presentation',
|
|
43
|
+
kind: { label: 'PPT', tone: 'orange' },
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
test: (m) =>
|
|
47
|
+
m === 'application/zip' ||
|
|
48
|
+
m === 'application/x-zip-compressed' ||
|
|
49
|
+
m === 'application/gzip' ||
|
|
50
|
+
m === 'application/x-gzip' ||
|
|
51
|
+
m === 'application/x-tar' ||
|
|
52
|
+
m === 'application/x-7z-compressed' ||
|
|
53
|
+
m === 'application/x-rar-compressed' ||
|
|
54
|
+
m === 'application/vnd.rar',
|
|
55
|
+
kind: { label: 'ZIP', tone: 'gray' },
|
|
56
|
+
},
|
|
57
|
+
{ test: (m) => m.startsWith('text/'), kind: { label: 'TXT', tone: 'gray' } },
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
// The file name a media URL ends in, without its query string or fragment
|
|
61
|
+
// (signed storage URLs carry both). Falls back to the whole URL when the path
|
|
62
|
+
// has no last segment.
|
|
63
|
+
export function fileName(url: string): string {
|
|
64
|
+
const path = url.split(/[?#]/)[0] ?? ''
|
|
65
|
+
return path.split('/').pop() || url
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The URL's extension, upper-cased, or '' when it has none worth showing.
|
|
69
|
+
function extensionOf(url: string): string {
|
|
70
|
+
const name = fileName(url)
|
|
71
|
+
const dot = name.lastIndexOf('.')
|
|
72
|
+
if (dot <= 0) return ''
|
|
73
|
+
const ext = name.slice(dot + 1)
|
|
74
|
+
return /^[a-z0-9]{1,5}$/i.test(ext) ? ext.toUpperCase() : ''
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function fileKind(mimeType: string, url: string): FileKind {
|
|
78
|
+
// Stored MIME types can carry parameters ("text/csv; charset=utf-8").
|
|
79
|
+
const mime = (mimeType.split(';')[0] ?? '').trim().toLowerCase()
|
|
80
|
+
const rule = RULES.find((r) => r.test(mime))
|
|
81
|
+
if (rule) return rule.kind
|
|
82
|
+
return { label: extensionOf(url) || 'FILE', tone: 'gray' }
|
|
83
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ParsedField } from '@bobbykim/manguito-cms-core'
|
|
2
|
+
import { defaultForField } from './field-defaults'
|
|
3
|
+
|
|
4
|
+
// Whether the taxonomy read (GET /admin/api/taxonomy/{type}/:id) returns the
|
|
5
|
+
// field. It returns the item's own columns only: a paragraph field
|
|
6
|
+
// (db_column null) lives on the paragraph table and a many-to-many reference
|
|
7
|
+
// (db_column.junction) lives on its junction table, so neither comes back.
|
|
8
|
+
function isReadByTaxonomy(field: ParsedField): boolean {
|
|
9
|
+
if (field.field_type === 'programmatic') return false
|
|
10
|
+
return field.db_column !== null && !field.db_column.junction
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// The taxonomy form's starting state, which is also what Save sends. A field
|
|
14
|
+
// the read does not return stays out of it: sending it as null would fail the
|
|
15
|
+
// api's relation shape check for a "many" field and erase a one-to-one
|
|
16
|
+
// paragraph, while an absent field is left untouched by the api.
|
|
17
|
+
// Programmatic fields are computed at read time and never submitted.
|
|
18
|
+
export function initialTaxonomyForm(
|
|
19
|
+
fields: ParsedField[],
|
|
20
|
+
source?: Record<string, unknown>
|
|
21
|
+
): Record<string, unknown> {
|
|
22
|
+
const form: Record<string, unknown> = {}
|
|
23
|
+
for (const field of fields) {
|
|
24
|
+
if (!isReadByTaxonomy(field)) continue
|
|
25
|
+
form[field.name] = source?.[field.name] ?? defaultForField(field)
|
|
26
|
+
}
|
|
27
|
+
return form
|
|
28
|
+
}
|
|
@@ -11,6 +11,7 @@ import { useContentStore } from '../../stores/content'
|
|
|
11
11
|
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
|
12
12
|
import { useTabIndicator } from '../../composables/useTabIndicator'
|
|
13
13
|
import { componentFor, fieldExtraProps } from '../../components/fields/field-registry'
|
|
14
|
+
import { defaultForField } from '../../utils/field-defaults'
|
|
14
15
|
|
|
15
16
|
const route = useRoute()
|
|
16
17
|
const router = useRouter()
|
|
@@ -80,38 +81,6 @@ const slugChanged = computed(
|
|
|
80
81
|
|
|
81
82
|
// ── Form helpers ──────────────────────────────────────────────────────────────
|
|
82
83
|
|
|
83
|
-
function defaultForField(field: ParsedField): unknown {
|
|
84
|
-
switch (field.field_type) {
|
|
85
|
-
case 'text/plain':
|
|
86
|
-
case 'text/rich':
|
|
87
|
-
return ''
|
|
88
|
-
case 'integer':
|
|
89
|
-
case 'float':
|
|
90
|
-
return null
|
|
91
|
-
case 'boolean':
|
|
92
|
-
return false
|
|
93
|
-
case 'date':
|
|
94
|
-
return null
|
|
95
|
-
case 'image':
|
|
96
|
-
case 'video':
|
|
97
|
-
case 'file':
|
|
98
|
-
return null
|
|
99
|
-
case 'enum':
|
|
100
|
-
return ''
|
|
101
|
-
case 'reference': {
|
|
102
|
-
const rel =
|
|
103
|
-
field.ui_component.component === 'typeahead-select'
|
|
104
|
-
? field.ui_component.rel
|
|
105
|
-
: 'one-to-one'
|
|
106
|
-
return rel === 'one-to-one' ? null : []
|
|
107
|
-
}
|
|
108
|
-
case 'paragraph':
|
|
109
|
-
return []
|
|
110
|
-
default:
|
|
111
|
-
return null
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
84
|
function initForm(source?: Record<string, unknown>) {
|
|
116
85
|
const f: Record<string, unknown> = {}
|
|
117
86
|
if (!isSingleton.value) {
|
|
@@ -10,6 +10,8 @@ import { useMediaStore } from '../../stores/media'
|
|
|
10
10
|
import { useTabIndicator } from '../../composables/useTabIndicator'
|
|
11
11
|
import Pagination from '../../components/shared/Pagination.vue'
|
|
12
12
|
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
|
|
13
|
+
import MediaThumbnail from '../../components/shared/MediaThumbnail.vue'
|
|
14
|
+
import { fileName } from '../../utils/file-kind'
|
|
13
15
|
|
|
14
16
|
const router = useRouter()
|
|
15
17
|
const api = useApiClient()
|
|
@@ -442,31 +444,14 @@ function cancelUpload() {
|
|
|
442
444
|
<button
|
|
443
445
|
type="button"
|
|
444
446
|
class="h-full w-full overflow-hidden rounded-[14px] border border-card-border shadow-[0_1px_2px_rgba(24,24,48,0.04),0_8px_22px_rgba(24,24,48,0.05)] transition-all hover:-translate-y-[3px] hover:shadow-[0_12px_30px_rgba(24,24,48,0.12)] focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
|
445
|
-
:aria-label="`View ${item.alt ?? item.url
|
|
447
|
+
:aria-label="`View ${item.alt ?? fileName(item.url)}`"
|
|
446
448
|
@click="goToDetail(item.id)"
|
|
447
449
|
>
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
:
|
|
452
|
-
:alt="item.alt ?? ''"
|
|
453
|
-
class="h-full w-full object-cover"
|
|
454
|
-
loading="lazy"
|
|
450
|
+
<MediaThumbnail
|
|
451
|
+
:item="item"
|
|
452
|
+
:label="fileName(item.url)"
|
|
453
|
+
:detail="formatSize(item.file_size)"
|
|
455
454
|
/>
|
|
456
|
-
|
|
457
|
-
<!-- Video / file icon -->
|
|
458
|
-
<div
|
|
459
|
-
v-else
|
|
460
|
-
class="flex h-full w-full flex-col items-center justify-center gap-1 bg-gray-50 p-1 text-gray-400"
|
|
461
|
-
>
|
|
462
|
-
<span class="text-3xl" aria-hidden="true">
|
|
463
|
-
{{ item.type === 'video' ? '▶' : '📄' }}
|
|
464
|
-
</span>
|
|
465
|
-
<span class="max-w-full truncate text-center text-xs">
|
|
466
|
-
{{ item.url.split('/').pop() }}
|
|
467
|
-
</span>
|
|
468
|
-
<span class="text-xs text-gray-300">{{ formatSize(item.file_size) }}</span>
|
|
469
|
-
</div>
|
|
470
455
|
</button>
|
|
471
456
|
</div>
|
|
472
457
|
</div>
|
|
@@ -9,6 +9,7 @@ import { useFormValidation } from '../../composables/useFormValidation'
|
|
|
9
9
|
import { useNotification } from '../../composables/useNotification'
|
|
10
10
|
import { useSchemaStore } from '../../stores/schema'
|
|
11
11
|
import { useTaxonomyStore } from '../../stores/taxonomy'
|
|
12
|
+
import { initialTaxonomyForm } from '../../utils/taxonomy-form'
|
|
12
13
|
import TextInput from '../../components/fields/TextInput.vue'
|
|
13
14
|
import RichTextEditor from '../../components/fields/RichTextEditor.vue'
|
|
14
15
|
import NumberInput from '../../components/fields/NumberInput.vue'
|
|
@@ -67,34 +68,8 @@ function componentFor(field: ParsedField): Component {
|
|
|
67
68
|
|
|
68
69
|
// ── Form helpers ──────────────────────────────────────────────────────────────
|
|
69
70
|
|
|
70
|
-
function defaultForField(field: ParsedField): unknown {
|
|
71
|
-
switch (field.field_type) {
|
|
72
|
-
case 'text/plain':
|
|
73
|
-
case 'text/rich':
|
|
74
|
-
return ''
|
|
75
|
-
case 'integer':
|
|
76
|
-
case 'float':
|
|
77
|
-
return null
|
|
78
|
-
case 'boolean':
|
|
79
|
-
return false
|
|
80
|
-
case 'date':
|
|
81
|
-
return null
|
|
82
|
-
case 'enum':
|
|
83
|
-
return ''
|
|
84
|
-
default:
|
|
85
|
-
return null
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
71
|
function initForm(source?: Record<string, unknown>) {
|
|
90
|
-
|
|
91
|
-
for (const field of allFields.value) {
|
|
92
|
-
// Programmatic fields are computed at read time — never edited or submitted,
|
|
93
|
-
// so they stay out of the form state (and therefore the save payload).
|
|
94
|
-
if (field.field_type === 'programmatic') continue
|
|
95
|
-
f[field.name] = source?.[field.name] ?? defaultForField(field)
|
|
96
|
-
}
|
|
97
|
-
form.value = f
|
|
72
|
+
form.value = initialTaxonomyForm(allFields.value, source)
|
|
98
73
|
}
|
|
99
74
|
|
|
100
75
|
function updateField(name: string, value: unknown) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as e,B as t,E as n,L as r,O as i,P as a,W as o,a as s,c,ct as l,d as u,g as d,i as f,j as p,l as m,lt as h,m as g,s as _,t as v,u as y,ut as b,v as x,w as S,x as C}from"./schema-B-RKX_ep.js";import{a as w,c as T,d as E,n as D,r as O,s as k,t as ee,u as A}from"./index-C-iAN6wp.js";import{a as j,c as M,i as N,n as P,o as F,r as I,s as L,t as R}from"./ComputedDisplay-Df_HvjzX.js";import{t as te}from"./useNotification-kY57Myug.js";import{t as ne}from"./content--2XYr_UQ.js";import{t as re}from"./ConfirmDialog-B7nxdDge.js";import{t as ie}from"./useTabIndicator-CvEsGBJh.js";var z={class:`flex h-full max-h-144 w-full max-w-3xl flex-col overflow-hidden rounded-lg bg-white shadow-xl`},B={class:`flex items-center justify-between border-b border-gray-200 px-5 py-4`},V={key:0,class:`flex gap-1 border-b border-gray-200 px-5 pt-3`},H=[`onClick`],ae={key:1,class:`border-b border-gray-200 px-5 py-2 text-sm text-gray-500`},U={class:`font-medium text-gray-700`},W={class:`flex-1 overflow-y-auto p-5`},G={key:0,class:`flex items-center justify-center py-16`},K={key:1,class:`flex flex-col items-center justify-center py-16 text-gray-400`},oe={key:2,class:`grid grid-cols-3 gap-3 sm:grid-cols-4 md:grid-cols-5`},q=[`aria-pressed`,`aria-label`,`onClick`],J=[`src`,`alt`],Y={key:1,class:`flex h-full w-full flex-col items-center justify-center gap-1 bg-gray-50 text-gray-400`,"aria-hidden":`true`},X={class:`text-3xl`},Z={class:`max-w-full truncate px-1 text-xs`},se={key:2,class:`absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-indigo-600 text-xs text-white`,"aria-hidden":`true`},Q={key:2,class:`flex items-center justify-center gap-3 border-t border-gray-100 px-5 py-2`},ce=[`disabled`],le={class:`text-xs text-gray-500`},ue=[`disabled`],de={class:`flex justify-end gap-3 border-t border-gray-200 px-5 py-4`},fe=[`disabled`],pe=d({__name:`MediaSelectModal`,props:{acceptedType:{}},emits:[`select`,`close`],setup(e,{emit:r}){let a=e,o=r,d=ee(),h=[{label:`Images`,value:`image`},{label:`Videos`,value:`video`},{label:`PDFs`,value:`file`}],v=t(a.acceptedType??`all`),x=_(()=>!a.acceptedType);p(()=>a.acceptedType,e=>{e&&(v.value=e)});let C=t([]),w=t(!1),T=t(1),D=t(1),O=t(null);function k(e,t){let n=new URLSearchParams({page:String(t),per_page:`20`});return e!==`all`&&n.set(`type`,e),`/media?${n.toString()}`}async function A(){w.value=!0;let e=await d.get(k(v.value,T.value));w.value=!1,e.ok&&(C.value=e.data,D.value=e.meta?.total_pages??1)}p(v,()=>{T.value=1,O.value=null,A()}),p(T,()=>{A()}),S(()=>{A()});function j(){O.value&&o(`select`,O.value)}return(t,r)=>(n(),m(s,{to:`body`},[c(`div`,{class:`fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4`,role:`dialog`,"aria-modal":`true`,"aria-label":`Select media`,onClick:r[5]||=E(e=>t.$emit(`close`),[`self`])},[c(`div`,z,[c(`div`,B,[r[6]||=c(`h2`,{class:`text-base font-semibold text-gray-900`},`Select Media`,-1),c(`button`,{type:`button`,class:`text-xl leading-none text-gray-400 hover:text-gray-600`,"aria-label":`Close`,onClick:r[0]||=e=>t.$emit(`close`)},` × `)]),x.value?(n(),u(`div`,V,[c(`button`,{type:`button`,class:l([`rounded-t-md px-3 py-1.5 text-sm font-medium transition-colors`,v.value===`all`?`border-b-2 border-indigo-600 text-indigo-600`:`text-gray-500 hover:text-gray-800`]),onClick:r[1]||=e=>v.value=`all`},` All `,2),(n(),u(f,null,i(h,e=>c(`button`,{key:e.value,type:`button`,class:l([`rounded-t-md px-3 py-1.5 text-sm font-medium transition-colors`,v.value===e.value?`border-b-2 border-indigo-600 text-indigo-600`:`text-gray-500 hover:text-gray-800`]),onClick:t=>v.value=e.value},b(e.label),11,H)),64))])):(n(),u(`div`,ae,[r[7]||=g(` Showing: `,-1),c(`span`,U,b(h.find(t=>t.value===e.acceptedType)?.label??e.acceptedType),1)])),c(`div`,W,[w.value?(n(),u(`div`,G,[...r[8]||=[c(`span`,{class:`inline-block h-6 w-6 animate-spin rounded-full border-2 border-indigo-600 border-t-transparent`,"aria-hidden":`true`},null,-1)]])):C.value.length===0?(n(),u(`div`,K,[...r[9]||=[c(`span`,{class:`text-4xl`,"aria-hidden":`true`},`🖼`,-1),c(`p`,{class:`mt-2 text-sm`},`No media found`,-1)]])):(n(),u(`div`,oe,[(n(!0),u(f,null,i(C.value,e=>(n(),u(`button`,{key:e.id,type:`button`,class:l([`group relative aspect-square overflow-hidden rounded-md border-2 transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-1`,O.value?.id===e.id?`border-indigo-500`:`border-transparent hover:border-gray-300`]),"aria-pressed":O.value?.id===e.id,"aria-label":`Select ${e.alt??e.url.split(`/`).pop()}`,onClick:t=>O.value=e},[e.type===`image`?(n(),u(`img`,{key:0,src:e.url,alt:e.alt??``,class:`h-full w-full object-cover`,loading:`lazy`},null,8,J)):(n(),u(`div`,Y,[c(`span`,X,b(e.type===`video`?`▶`:`📄`),1),c(`span`,Z,b(e.url.split(`/`).pop()),1)])),O.value?.id===e.id?(n(),u(`div`,se,` ✓ `)):y(``,!0)],10,q))),128))]))]),D.value>1?(n(),u(`div`,Q,[c(`button`,{type:`button`,disabled:T.value===1,class:`rounded px-2 py-1 text-sm text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40`,onClick:r[2]||=e=>T.value--},` ← Prev `,8,ce),c(`span`,le,b(T.value)+` / `+b(D.value),1),c(`button`,{type:`button`,disabled:T.value===D.value,class:`rounded px-2 py-1 text-sm text-gray-600 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40`,onClick:r[3]||=e=>T.value++},` Next → `,8,ue)])):y(``,!0),c(`div`,de,[c(`button`,{type:`button`,class:`rounded-md px-4 py-2 text-sm font-medium text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50`,onClick:r[4]||=e=>t.$emit(`close`)},` Cancel `),c(`button`,{type:`button`,disabled:!O.value,class:`rounded-md bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50`,onClick:j},` Select `,8,fe)])])])]))}}),me={class:`block text-[13px] font-semibold text-[#3D3D52]`},he={key:0,class:`ml-0.5 text-red-500`,"aria-hidden":`true`},ge={key:0,class:`mt-1 flex flex-col gap-2 rounded-md border border-gray-200 p-3`},_e={class:`flex items-center gap-3`},ve=[`src`,`alt`],$={key:1,class:`flex h-16 w-16 items-center justify-center rounded bg-gray-100 text-2xl text-gray-400`,"aria-hidden":`true`},ye={class:`min-w-0 flex-1`},be={class:`truncate text-sm font-medium text-gray-800`},xe={class:`text-xs text-gray-500`},Se={key:0},Ce=[`for`],we=[`id`],Te={key:1,class:`mt-1 rounded-md border border-gray-200 p-3`},Ee={class:`flex items-center gap-2`},De={class:`h-2 flex-1 overflow-hidden rounded-full bg-gray-100`},Oe={class:`w-8 shrink-0 text-right text-xs text-gray-500`},ke={key:2,class:`mt-1 rounded-md border border-gray-200 p-3`},Ae={class:`mb-2 truncate text-[13px] font-semibold text-[#3D3D52]`},je=[`for`],Me=[`id`],Ne={class:`mt-3 flex justify-end gap-2`},Pe=[`disabled`],Fe={key:3,class:`mt-1 flex gap-2`},Ie=[`accept`],Le=[`disabled`],Re=[`disabled`],ze={key:4,class:`mt-1 text-sm text-red-600`,role:`alert`},Be={key:5,class:`mt-1 text-sm text-red-600`,role:`alert`},Ve=d({__name:`MediaUpload`,props:{field:{},modelValue:{},error:{},disabled:{type:Boolean}},emits:[`update:modelValue`],setup(e,{emit:r}){let i=e,o=r,s=O(),l=_(()=>{let e=i.field.ui_component;return e.component===`file-upload`?e.accepted_mime_types.join(`,`):``}),d=_(()=>{let e=i.field.field_type;return e===`image`||e===`video`||e===`file`?e:`file`}),f=_(()=>d.value!==`image`),p=t(`idle`),v=t(0),x=t(``),C=t(null),w=t(``),T=t(null),E=t(!1),D=t(null);function k(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${(e/1e3).toFixed(0)} KB`:`${e} B`}function ee(e){return e.split(`/`).pop()??e}function j(e,t){return new Promise((n,r)=>{let i=new FormData;i.append(`file`,e),t&&i.append(`alt`,t);let a=new XMLHttpRequest;a.withCredentials=!0,a.open(`POST`,`/admin/api/media/${d.value}`),a.upload.onprogress=e=>{e.lengthComputable&&(v.value=Math.round(e.loaded/e.total*100))},a.onload=()=>{try{let e=JSON.parse(a.responseText);e.ok&&e.data?n(e.data):r(Error(e.error?.message??`Upload failed`))}catch{r(Error(`Invalid server response`))}},a.onerror=()=>r(Error(`Network error`)),a.send(i)})}async function M(e,t){let n=new URLSearchParams({type:d.value,filename:e.name,mime_type:e.type}),r=await(await fetch(`/admin/api/media/presigned-url?${n.toString()}`,{credentials:`include`})).json();if(!r.ok||!r.data)throw Error(r.error?.message??`Failed to get upload URL`);let{upload_url:i,media_id:a,method:o,fields:s}=r.data;await new Promise((t,n)=>{let r=new XMLHttpRequest;if(r.upload.onprogress=e=>{e.lengthComputable&&(v.value=Math.round(e.loaded/e.total*100))},r.onload=()=>{r.status>=200&&r.status<300?t():n(Error(`Storage upload failed (${r.status})`))},r.onerror=()=>n(Error(`Network error during upload`)),o===`POST`&&s){let t=new FormData;for(let[e,n]of Object.entries(s))t.append(e,n);t.append(`file`,e),r.open(`POST`,i),r.send(t)}else r.open(`PUT`,i),r.send(e)});let c=await(await fetch(`/admin/api/media/confirm/${a}`,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`},body:JSON.stringify({alt:t})})).json();if(!c.ok||!c.data)throw Error(c.error?.message??`Upload confirmation failed`);return c.data}async function N(e){p.value=`uploading`,v.value=0,x.value=``;try{let t=w.value.trim(),n=s.presignedUploads?await M(e,t):await j(e,t);T.value=n,w.value=n.alt??``,o(`update:modelValue`,n.id)}catch(e){x.value=e instanceof Error?e.message:`Upload failed`}finally{p.value=`idle`,C.value=null}}async function P(){let e=T.value;if(!e)return;let t=new XMLHttpRequest;t.withCredentials=!0,t.open(`PATCH`,`/admin/api/media/${e.id}`),t.setRequestHeader(`Content-Type`,`application/json`),t.onload=()=>{try{let e=JSON.parse(t.responseText);e.ok&&e.data&&(T.value=e.data)}catch{}},t.send(JSON.stringify({alt:w.value.trim()}))}function F(e){let t=e.target.files?.[0];t&&(C.value=t,w.value=``,e.target.value=``,f.value?p.value=`alt-collect`:N(t))}function I(){C.value&&(f.value&&!w.value.trim()||N(C.value))}function L(){C.value=null,w.value=``,p.value=`idle`,x.value=``}function R(){T.value=null,w.value=``,o(`update:modelValue`,null)}function te(e){T.value=e,w.value=e.alt??``,E.value=!1,o(`update:modelValue`,e.id)}return S(async()=>{if(typeof i.modelValue!=`string`||!i.modelValue)return;let e=await fetch(`/admin/api/media/${i.modelValue}`,{credentials:`include`});if(!e.ok)return;let t=await e.json();t.ok&&t.data&&(T.value=t.data,w.value=t.data.alt??``)}),(t,r)=>(n(),u(`div`,null,[c(`label`,me,[g(b(e.field.label)+` `,1),e.field.required?(n(),u(`span`,he,`*`)):y(``,!0)]),T.value?(n(),u(`div`,ge,[c(`div`,_e,[T.value.type===`image`?(n(),u(`img`,{key:0,src:T.value.url,alt:T.value.alt??``,class:`h-16 w-16 rounded object-cover`},null,8,ve)):(n(),u(`div`,$,b(T.value.type===`video`?`▶`:`📄`),1)),c(`div`,ye,[c(`p`,be,b(ee(T.value.url)),1),c(`p`,xe,b(k(T.value.file_size)),1)]),e.disabled?y(``,!0):(n(),u(`button`,{key:2,type:`button`,class:`shrink-0 text-lg leading-none text-gray-400 hover:text-red-500`,"aria-label":`Remove selected media`,onClick:R},` × `))]),T.value.type===`image`&&!e.disabled?(n(),u(`div`,Se,[c(`label`,{for:`${e.field.name}-alt`,class:`block text-xs text-gray-500`},[...r[5]||=[g(` Alt text `,-1),c(`span`,{class:`text-gray-400`},`(optional)`,-1)]],8,Ce),a(c(`input`,{id:`${e.field.name}-alt`,"onUpdate:modelValue":r[0]||=e=>w.value=e,type:`text`,placeholder:`Describe this image`,class:`mt-0.5 block w-full rounded-md border border-gray-300 px-2 py-1 text-sm shadow-sm focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-200`,onBlur:P},null,40,we),[[A,w.value]])])):y(``,!0)])):p.value===`uploading`?(n(),u(`div`,Te,[r[6]||=c(`p`,{class:`mb-1.5 text-xs text-gray-500`},`Uploading…`,-1),c(`div`,Ee,[c(`div`,De,[c(`div`,{class:`h-2 rounded-full bg-indigo-600 transition-all duration-150`,style:h({width:`${v.value}%`})},null,4)]),c(`span`,Oe,b(v.value)+`% `,1)])])):p.value===`alt-collect`?(n(),u(`div`,ke,[c(`p`,Ae,b(C.value?.name),1),c(`label`,{for:`${e.field.name}-alt-pre`,class:`block text-xs text-gray-600`},[...r[7]||=[g(` Alt text `,-1),c(`span`,{class:`text-red-500`,"aria-hidden":`true`},`*`,-1)]],8,je),a(c(`input`,{id:`${e.field.name}-alt-pre`,"onUpdate:modelValue":r[1]||=e=>w.value=e,type:`text`,placeholder:`Describe this file`,class:`mt-0.5 block w-full rounded-md border border-gray-300 px-2 py-1 text-sm shadow-sm focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-200`},null,8,Me),[[A,w.value]]),c(`div`,Ne,[c(`button`,{type:`button`,class:`rounded-md px-3 py-1.5 text-sm text-gray-600 ring-1 ring-inset ring-gray-300 hover:bg-gray-50`,onClick:L},` Cancel `),c(`button`,{type:`button`,disabled:!w.value.trim(),class:`rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50`,onClick:I},` Upload `,8,Pe)])])):(n(),u(`div`,Fe,[c(`input`,{ref_key:`fileInputRef`,ref:D,type:`file`,class:`hidden`,accept:l.value,onChange:F},null,40,Ie),c(`button`,{type:`button`,disabled:e.disabled,class:`rounded-md border border-gray-300 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50`,onClick:r[2]||=e=>D.value?.click()},` Upload `,8,Le),c(`button`,{type:`button`,disabled:e.disabled,class:`rounded-md border border-gray-300 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50`,onClick:r[3]||=e=>E.value=!0},` Select from library `,8,Re)])),x.value?(n(),u(`p`,ze,b(x.value),1)):y(``,!0),e.error?(n(),u(`p`,Be,b(e.error),1)):y(``,!0),E.value?(n(),m(pe,{key:6,"accepted-type":d.value,onSelect:te,onClose:r[4]||=e=>E.value=!1},null,8,[`accepted-type`])):y(``,!0)]))}}),He={class:`block text-[13px] font-semibold text-[#3D3D52]`},Ue={key:0,class:`ml-0.5 text-red-500`,"aria-hidden":`true`},We={key:0,class:`mt-1.5 flex flex-wrap gap-1.5`},Ge=[`disabled`,`aria-label`,`onClick`],Ke={key:1,class:`mt-1.5`},qe={class:`inline-flex items-center gap-1 rounded-full bg-indigo-100 px-2.5 py-0.5 text-xs font-medium text-indigo-800`},Je=[`disabled`],Ye={key:2,class:`mt-0.5 text-xs text-gray-500`},Xe={class:`relative mt-1`},Ze=[`id`,`value`,`disabled`,`placeholder`],Qe={key:0,role:`listbox`,class:`absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm shadow-lg ring-1 ring-black/5 focus:outline-none`},$e={key:0,class:`flex items-center gap-2 px-3 py-2 text-gray-400`},et={key:0,class:`px-3 py-2 text-gray-500`},tt=[`onClick`],nt={key:3,class:`mt-1 text-sm text-red-600`,role:`alert`},rt=d({__name:`ReferenceSelect`,props:{field:{},modelValue:{},error:{},disabled:{type:Boolean}},emits:[`update:modelValue`],setup(e,{emit:r}){let a=e,o=r,s=ee(),d=v(),p=_(()=>{let e=a.field.ui_component;return e.component===`typeahead-select`?e:null}),m=_(()=>p.value?.ref??``),h=_(()=>p.value?.rel??`one-to-one`),x=_(()=>a.field.validation.max_items??null),C=_(()=>h.value!==`one-to-one`),T=_(()=>!!d.contentTypes[m.value]),D=_(()=>(T.value?d.contentTypes[m.value]:d.taxonomyTypes[m.value])?.fields.find(e=>e.field_type===`text/plain`)?.name??`id`),O=_(()=>C.value?Array.isArray(a.modelValue)?a.modelValue.filter(e=>typeof e==`string`):[]:typeof a.modelValue==`string`?[a.modelValue]:[]),k=_(()=>x.value!==null&&O.value.length>=x.value),A=_(()=>O.value[0]??``),j=t({}),M=t(``),N=t(!1),P=t([]),F=t(!1);function I(){return T.value?`/content/${m.value}`:`/taxonomy/${m.value}`}function L(e){let t=new URLSearchParams({[`filters[${D.value}][like]`]:e,per_page:`10`});return`${I()}?${t.toString()}`}function R(e){return String(e[D.value]??e.id??``)}let te=w(async e=>{if(e.length<2){P.value=[],F.value=!1;return}N.value=!0,F.value=!0;let t=await s.get(L(e));N.value=!1,t.ok&&(P.value=t.data)},300);function ne(e){M.value=e.target.value,te(M.value)}function re(){setTimeout(()=>{F.value=!1},150)}function ie(){M.value.length>=2&&(F.value=!0)}function z(e){let t=String(e.id);if(j.value[t]=R(e),M.value=``,P.value=[],F.value=!1,C.value){let e=[...O.value];e.includes(t)||e.push(t),o(`update:modelValue`,e)}else o(`update:modelValue`,t)}function B(e){C.value?o(`update:modelValue`,O.value.filter(t=>t!==e)):o(`update:modelValue`,null)}return S(async()=>{for(let e of O.value){if(j.value[e])continue;let t=await s.get(`${I()}/${e}`);t.ok?j.value[e]=R(t.data):j.value[e]=e}}),(t,r)=>(n(),u(`div`,null,[c(`label`,He,[g(b(e.field.label)+` `,1),e.field.required?(n(),u(`span`,Ue,`*`)):y(``,!0)]),C.value&&O.value.length?(n(),u(`div`,We,[(n(!0),u(f,null,i(O.value,t=>(n(),u(`span`,{key:t,class:`inline-flex items-center gap-1 rounded-full bg-indigo-100 px-2.5 py-0.5 text-xs font-medium text-indigo-800`},[g(b(j.value[t]??t)+` `,1),c(`button`,{type:`button`,disabled:e.disabled,class:`ml-0.5 flex h-3.5 w-3.5 items-center justify-center rounded-full hover:bg-indigo-200 disabled:cursor-not-allowed`,"aria-label":`Remove ${j.value[t]??t}`,onClick:e=>B(t)},[...r[2]||=[c(`span`,{"aria-hidden":`true`},`×`,-1)]],8,Ge)]))),128))])):!C.value&&O.value.length?(n(),u(`div`,Ke,[c(`span`,qe,[g(b(j.value[A.value]??A.value)+` `,1),c(`button`,{type:`button`,disabled:e.disabled,class:`ml-0.5 flex h-3.5 w-3.5 items-center justify-center rounded-full hover:bg-indigo-200 disabled:cursor-not-allowed`,"aria-label":`Clear selection`,onClick:r[0]||=e=>B(A.value)},[...r[3]||=[c(`span`,{"aria-hidden":`true`},`×`,-1)]],8,Je)])])):y(``,!0),x.value===null?y(``,!0):(n(),u(`p`,Ye,b(O.value.length)+` / `+b(x.value)+` selected `,1)),c(`div`,Xe,[c(`input`,{id:e.field.name,type:`text`,value:M.value,disabled:e.disabled||k.value,placeholder:k.value?`Limit reached`:`Search ${e.field.label}…`,class:l([`block w-full rounded-[11px] border px-3.5 py-3 text-sm focus:outline-none focus:ring-[3px]`,e.error?`border-red-300 focus:border-red-400 focus:ring-red-200`:`border-[#E4E3EE] bg-[#FBFBFD] focus:border-indigo-400 focus:bg-white focus:ring-indigo-50`,(e.disabled||k.value)&&`cursor-not-allowed bg-gray-50 opacity-60`]),autocomplete:`off`,onInput:ne,onFocus:ie,onFocusout:re},null,42,Ze),F.value?(n(),u(`ul`,Qe,[N.value?(n(),u(`li`,$e,[...r[4]||=[c(`span`,{class:`inline-block h-3.5 w-3.5 animate-spin rounded-full border-2 border-indigo-500 border-t-transparent`,"aria-hidden":`true`},null,-1),g(` Searching… `,-1)]])):(n(),u(f,{key:1},[P.value.length===0?(n(),u(`li`,et,` No results found for "`+b(M.value)+`" `,1)):y(``,!0),(n(!0),u(f,null,i(P.value,e=>(n(),u(`li`,{key:String(e.id),role:`option`,class:`cursor-pointer px-3 py-2 hover:bg-indigo-50`,onMousedown:r[1]||=E(()=>{},[`prevent`]),onClick:t=>z(e)},b(R(e)),41,tt))),128))],64))])):y(``,!0)]),e.error?(n(),u(`p`,nt,b(e.error),1)):y(``,!0)]))}}),it={class:`block text-[13px] font-semibold text-[#3D3D52]`},at={key:0,class:`ml-0.5 text-red-500`,"aria-hidden":`true`},ot={class:`mt-1 space-y-2`},st=[`onDragstart`,`onDragover`,`onDrop`],ct={class:`flex items-center gap-2 border-b border-gray-100 px-3 py-2`},lt={class:`text-xs font-medium text-gray-500`},ut=[`aria-label`,`onClick`],dt={class:`p-3`},ft={key:1,class:`mt-1 text-sm text-red-600`,role:`alert`},pt=d({__name:`ParagraphEmbed`,props:{field:{},modelValue:{},error:{},disabled:{type:Boolean},formComponent:{}},emits:[`update:modelValue`],setup(r,{emit:a}){let o=r,s=a,d=_(()=>Array.isArray(o.modelValue)?o.modelValue:[]),p=t(null),h=t(null);function v(){let e=[...d.value];e.push({order:e.length}),s(`update:modelValue`,e)}function x(e){let t=[...d.value];t.splice(e,1),s(`update:modelValue`,t.map((e,t)=>({...e,order:t})))}function S(e,t){let n=[...d.value];n[e]={...t,order:e},s(`update:modelValue`,n)}function C(e){p.value=e}function w(e){h.value=e}function T(e){if(p.value===null||p.value===e){p.value=null,h.value=null;return}let t=[...d.value],[n]=t.splice(p.value,1);n!==void 0&&(t.splice(e,0,n),s(`update:modelValue`,t.map((e,t)=>({...e,order:t}))),p.value=null,h.value=null)}function D(){p.value=null,h.value=null}return(t,a)=>(n(),u(`div`,null,[c(`label`,it,[g(b(r.field.label)+` `,1),r.field.required?(n(),u(`span`,at,`*`)):y(``,!0)]),c(`div`,ot,[(n(!0),u(f,null,i(d.value,(t,i)=>(n(),u(`div`,{key:i,draggable:`true`,class:l([`rounded-md border bg-white transition-colors`,h.value===i&&p.value!==i?`border-indigo-400 ring-2 ring-indigo-200`:`border-gray-200`,r.disabled&&`opacity-60`]),onDragstart:e=>C(i),onDragover:E(e=>w(i),[`prevent`]),onDrop:E(e=>T(i),[`prevent`]),onDragend:D},[c(`div`,ct,[a[0]||=c(`span`,{class:`cursor-grab select-none text-gray-400`,title:`Drag to reorder`,"aria-hidden":`true`},` ⋮⋮ `,-1),c(`span`,lt,` Item `+b(i+1),1),r.disabled?y(``,!0):(n(),u(`button`,{key:0,type:`button`,class:`ml-auto text-xs text-red-500 hover:text-red-700`,"aria-label":`Remove item ${i+1}`,onClick:e=>x(i)},` Remove `,8,ut))]),c(`div`,dt,[(n(),m(e(r.formComponent),{"model-value":t,disabled:r.disabled,"onUpdate:modelValue":e=>S(i,e)},null,8,[`model-value`,`disabled`,`onUpdate:modelValue`]))])],42,st))),128))]),r.disabled?y(``,!0):(n(),u(`button`,{key:0,type:`button`,class:`mt-2 inline-flex items-center gap-1.5 rounded-md border border-dashed border-gray-300 px-3 py-2 text-sm text-gray-600 hover:border-indigo-400 hover:text-indigo-600`,onClick:v},[a[1]||=c(`span`,{"aria-hidden":`true`},`+`,-1),g(` Add `+b(r.field.label),1)])),r.error?(n(),u(`p`,ft,b(r.error),1)):y(``,!0)]))}}),mt={"text/plain":r(L),"text/rich":r(F),integer:r(j),float:r(j),boolean:r(N),date:r(I),image:r(Ve),video:r(Ve),file:r(Ve),enum:r(P),reference:r(rt),paragraph:r(pt),programmatic:r(R)};function ht(e){return mt[e.field_type]??mt[`text/plain`]}function gt(e){return e.ui_component.component===`paragraph-embed`?{formComponent:vt(e.ui_component.ref)}:{}}var _t=new Map;function vt(e){let t=_t.get(e);if(t)return t;let n=r(d({name:`ParagraphForm_${e}`,props:{modelValue:{type:Object,default:()=>({})},disabled:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(t,{emit:n}){let r=v(),i=_(()=>r.paragraphTypes[e]);function a(e,r){n(`update:modelValue`,{...t.modelValue,[e]:r})}return()=>i.value?x(`div`,{class:`space-y-3`},i.value.fields.map(e=>x(ht(e),{key:e.name,field:e,modelValue:(t.modelValue??{})[e.name],disabled:t.disabled,...gt(e),"onUpdate:modelValue":t=>a(e.name,t)}))):x(`div`,{class:`text-sm text-gray-400`},`Unknown paragraph type`)}}));return _t.set(e,n),n}var yt={key:0,class:`flex items-center justify-center py-20`},bt={key:1,class:`py-12 text-center text-sm text-gray-500`},xt={key:2},St={class:`mb-[22px] flex flex-wrap items-start justify-between gap-4`},Ct={class:`mb-1.5 text-[11px] font-bold uppercase tracking-[.06em] text-faint`},wt={class:`text-[25px] font-bold tracking-tight text-ink`},Tt={class:`flex shrink-0 flex-wrap items-center gap-[9px]`},Et=[`disabled`],Dt=[`disabled`],Ot=[`disabled`],kt=[`disabled`],At={key:0,class:`mb-[18px] rounded-2xl border border-card-border bg-white p-5 shadow-[0_1px_2px_rgba(24,24,48,0.04),0_8px_22px_rgba(24,24,48,0.04)]`},jt={class:`mt-2 flex flex-wrap items-center gap-[10px]`},Mt=[`disabled`],Nt={key:0,class:`mt-[9px] text-[12.5px] text-[#D9913C]`},Pt={key:1,class:`mt-1 text-sm text-red-600`,role:`alert`},Ft=[`data-tab`,`onClick`],It={class:`space-y-5`},Lt={key:2,class:`mt-4 text-sm text-red-600`,role:`alert`},Rt=d({__name:`ContentFormView`,setup(r){let s=k(),d=T(),x=ee(),{can:w}=D(),{errors:E,validate:O,mergeServerErrors:j,clearErrors:N,setError:P}=M(),F=te(),I=v(),L=ne(),R=_(()=>s.params.type),z=_(()=>s.params.id),B=_(()=>I.contentTypes[R.value]),V=_(()=>B.value?.fields??[]),H=_(()=>B.value?.ui.tabs??[]),ae=_(()=>B.value?.only_one===!0),U=_(()=>ae.value?`singleton`:z.value?`edit`:`create`),W=t(null),G=t({}),K=t(!1),oe=t(``),q=t(!1),J=t(!0),Y=t(!1),X=t(``),Z=t(!1),se=t(!1),Q=t(null),ce=t(0),le=_(()=>H.value[ce.value]?.name??``),ue=t(null),{left:de,width:fe}=ie(ue,le),pe=_(()=>{if(H.value.length===0)return V.value;let e=H.value[ce.value];return e?e.fields.map(e=>V.value.find(t=>t.name===e)).filter(e=>e!==void 0):V.value}),me=_(()=>U.value===`edit`&&K.value&&G.value.slug!==oe.value);function he(e){switch(e.field_type){case`text/plain`:case`text/rich`:return``;case`integer`:case`float`:return null;case`boolean`:return!1;case`date`:return null;case`image`:case`video`:case`file`:return null;case`enum`:return``;case`reference`:return(e.ui_component.component===`typeahead-select`?e.ui_component.rel:`one-to-one`)===`one-to-one`?null:[];case`paragraph`:return[];default:return null}}function ge(e){let t={};ae.value||(t.slug=e?.slug??``);for(let n of V.value)n.field_type!==`programmatic`&&(t[n.name]=e?.[n.name]??he(n));G.value=t,K.value=e?.published===!0,e?.slug&&(oe.value=String(e.slug))}function _e(e,t){G.value[e]=t}async function ve(e){let t=await x.get(`/content/${R.value}/${e}`);t.ok?(W.value=t.data,ge(t.data)):X.value=t.error.message}S(async()=>{if(!B.value){J.value=!1;return}U.value===`edit`&&z.value||U.value===`singleton`&&z.value?await ve(z.value):ge(),J.value=!1}),p(z,async(e,t)=>{e!==t&&(J.value=!0,q.value=!1,N(),e?await ve(e):(W.value=null,ge()),J.value=!1)});async function $(e){Y.value=!0,X.value=``;let t={...G.value};e!==void 0&&(t.published=e);let n;if(n=U.value===`create`?await x.post(`/content/${R.value}`,t):U.value===`singleton`?await x.put(`/content/${R.value}`,t):await x.patch(`/content/${R.value}/${z.value}`,t),Y.value=!1,!n.ok){let e=n.error;e.code===`PUBLISH_VALIDATION_ERROR`&&e.details?j(e.details):e.code===`SLUG_CONFLICT`?P(`slug`,`This slug is already taken.`):X.value=e.message;return}W.value=n.data,K.value=n.data.published===!0,oe.value=String(n.data.slug??``),q.value=!1,L.invalidate(R.value),F.success(`Saved.`),U.value===`create`&&d.replace({name:`content-edit`,params:{type:R.value,id:String(n.data.id)}})}function ye(){if(O(V.value,G.value)){if(me.value){Q.value=()=>$(),Z.value=!0;return}$()}}function be(){if(O(V.value,G.value,!0)){if(me.value){Q.value=()=>$(!0),Z.value=!0;return}$(!0)}}function xe(){$(!1)}function Se(){Z.value=!1,Q.value&&=(Q.value(),null)}function Ce(){Z.value=!1,Q.value=null}async function we(){se.value=!1,Y.value=!0;let e=await x.del(`/content/${R.value}/${z.value}`);if(Y.value=!1,!e.ok){X.value=e.error.message;return}L.invalidate(R.value),d.push({name:`content-list`,params:{type:R.value}})}let Te=_(()=>{if(U.value===`create`)return`New ${B.value?.label??``}`;if(U.value===`singleton`)return B.value?.label??``;let e=V.value.find(e=>e.field_type===`text/plain`);return(e?String(W.value?.[e.name]??``):``)||(B.value?.label??``)});return(t,r)=>J.value?(n(),u(`div`,yt,[...r[3]||=[c(`span`,{class:`inline-block h-6 w-6 animate-spin rounded-full border-2 border-indigo-600 border-t-transparent`,"aria-hidden":`true`},null,-1)]])):B.value?(n(),u(`div`,xt,[c(`div`,St,[c(`div`,null,[c(`p`,Ct,b(B.value.label),1),c(`h1`,wt,b(Te.value),1)]),c(`div`,Tt,[o(w)(`content:delete`)&&U.value===`edit`?(n(),u(`button`,{key:0,type:`button`,disabled:Y.value,class:`inline-flex items-center gap-1.5 rounded-[10px] border border-[#F3D2D7] bg-white px-[15px] py-2.5 text-[13px] font-semibold text-[#E1495B] transition-colors hover:bg-[#FDF2F4] disabled:cursor-not-allowed disabled:opacity-50`,onClick:r[0]||=e=>se.value=!0},` Delete `,8,Et)):y(``,!0),o(w)(`content:edit`)?(n(),u(f,{key:1},[K.value?(n(),u(`button`,{key:0,type:`button`,disabled:Y.value,class:`rounded-[10px] border border-[#E4E3EE] bg-white px-4 py-2.5 text-[13px] font-semibold text-[#3D3D52] transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-50`,onClick:xe},` Unpublish `,8,Dt)):(n(),u(`button`,{key:1,type:`button`,disabled:Y.value,class:`rounded-[10px] border border-[#E4E3EE] bg-white px-4 py-2.5 text-[13px] font-semibold text-[#3D3D52] transition-colors hover:bg-surface disabled:cursor-not-allowed disabled:opacity-50`,onClick:be},` Publish `,8,Ot)),c(`button`,{type:`button`,disabled:Y.value,class:`inline-flex items-center gap-1.5 rounded-[10px] bg-indigo-600 px-4 py-2.5 text-[13px] font-semibold text-white shadow-[0_3px_10px_rgba(91,87,232,0.3)] transition-all hover:bg-indigo-700 hover:shadow-[0_6px_18px_rgba(91,87,232,0.4)] disabled:cursor-not-allowed disabled:opacity-50`,onClick:ye},b(Y.value?`Saving…`:`Save draft`),9,kt)],64)):y(``,!0)])]),ae.value?y(``,!0):(n(),u(`div`,At,[r[4]||=c(`label`,{for:`slug-field`,class:`block text-[13px] font-semibold text-[#3D3D52]`},[g(` Slug `),c(`span`,{class:`ml-0.5 text-red-500`,"aria-hidden":`true`},`*`)],-1),c(`div`,jt,[a(c(`input`,{id:`slug-field`,"onUpdate:modelValue":r[1]||=e=>G.value.slug=e,type:`text`,disabled:Y.value||K.value&&!q.value,class:l([`block min-w-[180px] flex-1 rounded-[10px] border px-[13px] py-[11px] font-mono text-sm focus:outline-none focus:ring-2`,o(E).slug?`border-red-300 focus:border-red-400 focus:ring-red-200`:`border-[#E4E3EE] bg-surface focus:border-indigo-400 focus:ring-indigo-200`,(Y.value||K.value&&!q.value)&&`cursor-not-allowed bg-gray-100 opacity-70`]),placeholder:`url-slug`},null,10,Mt),[[A,G.value.slug]]),K.value&&!q.value?(n(),u(`button`,{key:0,type:`button`,class:`shrink-0 rounded-[10px] border border-[#E4E3EE] bg-white px-4 py-2.5 text-sm font-semibold text-[#3D3D52] transition-colors hover:bg-surface`,onClick:r[2]||=e=>q.value=!0},` Edit slug `)):y(``,!0)]),K.value?(n(),u(`p`,Nt,` Changing this slug will break existing links. `)):y(``,!0),o(E).slug?(n(),u(`p`,Pt,b(o(E).slug),1)):y(``,!0)])),H.value.length>1?(n(),u(`div`,{key:1,ref_key:`tabBarRef`,ref:ue,class:`relative mb-[22px] flex gap-0 overflow-x-auto border-b border-card-border`},[(n(!0),u(f,null,i(H.value,(e,t)=>(n(),u(`button`,{key:e.name,"data-tab":e.name,type:`button`,class:l([`mr-6 whitespace-nowrap bg-none px-0.5 py-[11px] text-sm transition-colors`,ce.value===t?`font-semibold text-indigo-600`:`font-medium text-faint hover:text-[#8A8A9E]`]),onClick:e=>ce.value=t},b(e.label),11,Ft))),128)),c(`div`,{class:`absolute -bottom-px h-0.5 rounded-full bg-indigo-600 transition-[left,width] duration-300`,style:h({left:`${o(de)}px`,width:`${o(fe)}px`})},null,4)],512)):y(``,!0),c(`div`,It,[(n(!0),u(f,null,i(pe.value,t=>(n(),m(e(o(ht)(t)),C({key:t.name,field:t,"model-value":G.value[t.name],error:o(E)[t.name],disabled:Y.value},{ref_for:!0},o(gt)(t),{"onUpdate:modelValue":e=>_e(t.name,e)}),null,16,[`field`,`model-value`,`error`,`disabled`,`onUpdate:modelValue`]))),128))]),X.value?(n(),u(`p`,Lt,b(X.value),1)):y(``,!0),Z.value?(n(),m(re,{key:3,message:`This item is published. Changing its slug will break existing links. Continue?`,"on-confirm":Se,"on-cancel":Ce})):y(``,!0),se.value?(n(),m(re,{key:4,message:`Are you sure you want to delete this item? This action cannot be undone.`,"on-confirm":we,"on-cancel":()=>se.value=!1},null,8,[`on-cancel`])):y(``,!0)])):(n(),u(`div`,bt,` Content type not found. `))}});export{Rt as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{B as e,E as t,O as n,P as r,W as i,c as a,ct as o,d as s,g as c,h as ee,i as l,j as te,l as ne,lt as u,m as d,s as re,u as f,ut as p,w as ie}from"./schema-B-RKX_ep.js";import{c as ae,d as oe,n as se,r as ce,t as le,u as ue}from"./index-C-iAN6wp.js";import{t as de}from"./useNotification-kY57Myug.js";import{t as fe}from"./ConfirmDialog-B7nxdDge.js";import{t as pe}from"./useTabIndicator-CvEsGBJh.js";import{t as me}from"./Pagination-BIf7mQy7.js";import{t as he}from"./media-DvQfZD4o.js";var m={class:`mb-[18px] flex flex-wrap items-center justify-between gap-4`},ge={key:0},_e={key:0,class:`mb-5 rounded-md border border-gray-200 bg-white p-4 shadow-sm`},ve={key:0,class:`space-y-3`},ye={class:`text-sm font-medium text-gray-700`},be={class:`flex gap-2`},xe=[`disabled`],Se={key:1,class:`space-y-2`},Ce={class:`text-sm text-gray-500`},we={class:`flex items-center gap-2`},h={class:`h-2 flex-1 overflow-hidden rounded-full bg-gray-100`},g={class:`w-8 shrink-0 text-right text-xs text-gray-500`},_={key:2,class:`mt-2 text-sm text-red-600`,role:`alert`},v=[`data-tab`,`onClick`],y={key:1,class:`mb-3 flex items-center gap-3`},b={class:`flex cursor-pointer items-center gap-2 text-sm text-gray-600`},x=[`checked`,`indeterminate`],S={key:2,class:`grid grid-cols-3 gap-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6`},C={key:3,class:`rounded-2xl border border-dashed border-gray-300 p-12 text-center`},w={class:`text-sm text-muted`},T={key:4,class:`grid grid-cols-3 gap-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6`},E=[`checked`,`onChange`],D=[`aria-label`,`onClick`],O=[`src`,`alt`],k={key:1,class:`flex h-full w-full flex-col items-center justify-center gap-1 bg-gray-50 p-1 text-gray-400`},Te={class:`text-3xl`,"aria-hidden":`true`},Ee={class:`max-w-full truncate text-center text-xs`},De={class:`text-xs text-gray-300`},Oe={key:5,class:`mt-5 flex justify-center`},A=20,j=c({__name:`MediaLibraryView`,setup(c){let j=ae(),M=le(),{can:N}=se(),P=de(),ke=ce(),F=he(),I=e(`all`),L=re(()=>I.value===`orphaned`),Ae=[{value:`all`,label:`All`},{value:`image`,label:`Images`},{value:`video`,label:`Videos`},{value:`file`,label:`PDFs`},{value:`orphaned`,label:`Orphaned`}],R=e(null),{left:je,width:Me}=pe(R,I),z=e([]),B=e(0),V=e(1),H=e(!1);function Ne(e,t){let n=new URLSearchParams({page:String(t),per_page:String(A)});return e===`orphaned`?n.set(`orphaned`,`true`):e!==`all`&&n.set(`type`,e),`/media?${n.toString()}`}async function U(e,t){H.value=!0;let n=await M.get(Ne(e,t));H.value=!1,n.ok&&(z.value=n.data,B.value=n.meta?.total??n.data.length,F.setItems(n.data))}ie(()=>{U(I.value,V.value)}),te(I,e=>{V.value=1,W.value.clear(),U(e,1)});function Pe(e){V.value=e,U(I.value,e)}function Fe(e){j.push({name:`media-detail`,params:{id:e}})}let W=e(new Set),G=e(!1);function Ie(e){W.value.has(e)?W.value.delete(e):W.value.add(e)}function Le(){W.value.size===z.value.length?W.value.clear():W.value=new Set(z.value.map(e=>e.id))}async function Re(){G.value=!1;let e=[...W.value];for(let t of e)await M.del(`/media/${t}`),F.removeItem(t);z.value=z.value.filter(t=>!e.includes(t.id)),B.value=Math.max(0,B.value-e.length),W.value.clear(),P.success(`Deleted ${e.length} item${e.length===1?``:`s`}.`)}let K=e(`idle`),q=e(null),J=e(`file`),Y=e(``),X=e(0),Z=e(``),Q=e(null);function ze(e){return e.type.startsWith(`image/`)?`image`:e.type.startsWith(`video/`)?`video`:`file`}function Be(e){return e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${Math.round(e/1e3)} KB`:`${e} B`}function Ve(e){let t=e.target.files?.[0];t&&(e.target.value=``,q.value=t,J.value=ze(t),Y.value=``,Z.value=``,J.value===`image`?$(t):K.value=`alt-collect`)}function He(e,t){return new Promise((n,r)=>{let i=new FormData;i.append(`file`,e),t&&i.append(`alt`,t);let a=new XMLHttpRequest;a.withCredentials=!0,a.open(`POST`,`/admin/api/media/${J.value}`),a.upload.onprogress=e=>{e.lengthComputable&&(X.value=Math.round(e.loaded/e.total*100))},a.onload=()=>{try{let e=JSON.parse(a.responseText);e.ok&&e.data?n(e.data):r(Error(e.error?.message??`Upload failed`))}catch{r(Error(`Invalid server response`))}},a.onerror=()=>r(Error(`Network error`)),a.send(i)})}async function Ue(e,t){let n=new URLSearchParams({type:J.value,filename:e.name,mime_type:e.type}),r=await(await fetch(`/admin/api/media/presigned-url?${n.toString()}`,{credentials:`include`})).json();if(!r.ok||!r.data)throw Error(r.error?.message??`Failed to get upload URL`);let{upload_url:i,media_id:a,method:o,fields:s}=r.data;await new Promise((t,n)=>{let r=new XMLHttpRequest;if(r.upload.onprogress=e=>{e.lengthComputable&&(X.value=Math.round(e.loaded/e.total*100))},r.onload=()=>r.status>=200&&r.status<300?t():n(Error(`Storage upload failed (${r.status})`)),r.onerror=()=>n(Error(`Network error`)),o===`POST`&&s){let t=new FormData;for(let[e,n]of Object.entries(s))t.append(e,n);t.append(`file`,e),r.open(`POST`,i),r.send(t)}else r.open(`PUT`,i),r.send(e)});let c=await(await fetch(`/admin/api/media/confirm/${a}`,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`},body:JSON.stringify({alt:t})})).json();if(!c.ok||!c.data)throw Error(c.error?.message??`Upload confirmation failed`);return c.data}async function $(e){K.value=`uploading`,X.value=0,Z.value=``;try{let t=Y.value.trim(),n=ke.presignedUploads?await Ue(e,t):await He(e,t);z.value=[n,...z.value],B.value+=1,F.setItem(n),P.success(`Upload complete.`)}catch(e){Z.value=e instanceof Error?e.message:`Upload failed`}finally{K.value=`idle`,q.value=null}}function We(){q.value&&$(q.value)}function Ge(){q.value=null,Y.value=``,Z.value=``,K.value=`idle`}return(e,c)=>(t(),s(`div`,null,[a(`div`,m,[c[5]||=a(`h1`,{class:`text-[26px] font-bold tracking-tight text-ink`},`Media library`,-1),i(N)(`media:create`)?(t(),s(`div`,ge,[a(`input`,{ref_key:`fileInputRef`,ref:Q,type:`file`,class:`hidden`,accept:`image/*,video/*,application/pdf,.pdf`,onChange:Ve},null,544),a(`button`,{type:`button`,class:`inline-flex items-center gap-1.75 rounded-[11px] bg-indigo-600 px-4 py-2.5 text-[13.5px] font-semibold text-white shadow-[0_3px_10px_rgba(91,87,232,0.3)] transition-all hover:bg-indigo-700 hover:shadow-[0_6px_18px_rgba(91,87,232,0.4)]`,onClick:c[0]||=e=>Q.value?.click()},[...c[4]||=[a(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.9`,"stroke-linecap":`round`,"stroke-linejoin":`round`},[a(`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`}),a(`path`,{d:`M17 8l-5-5-5 5`}),a(`path`,{d:`M12 3v12`})],-1),d(` Upload `,-1)]])])):f(``,!0)]),K.value===`idle`?f(``,!0):(t(),s(`div`,_e,[K.value===`alt-collect`?(t(),s(`div`,ve,[a(`p`,ye,p(q.value?.name),1),a(`div`,null,[c[6]||=a(`label`,{for:`upload-alt`,class:`block text-xs text-gray-600`},[d(` Alt text `),a(`span`,{class:`text-red-500`},`*`)],-1),r(a(`input`,{id:`upload-alt`,"onUpdate:modelValue":c[1]||=e=>Y.value=e,type:`text`,placeholder:`Describe this file`,class:`mt-0.5 block w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm shadow-sm focus:border-indigo-400 focus:outline-none focus:ring-2 focus:ring-indigo-200`},null,512),[[ue,Y.value]])]),a(`div`,be,[a(`button`,{type:`button`,class:`rounded-md px-3 py-1.5 text-sm text-gray-600 ring-1 ring-inset ring-gray-300 hover:bg-gray-50`,onClick:Ge},` Cancel `),a(`button`,{type:`button`,disabled:!Y.value.trim(),class:`rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50`,onClick:We},` Upload `,8,xe)])])):K.value===`uploading`?(t(),s(`div`,Se,[a(`p`,Ce,`Uploading`+p(q.value?` ${q.value.name}`:`…`),1),a(`div`,we,[a(`div`,h,[a(`div`,{class:`h-2 rounded-full bg-indigo-600 transition-all duration-150`,style:u({width:`${X.value}%`})},null,4)]),a(`span`,g,p(X.value)+`%`,1)])])):f(``,!0),Z.value?(t(),s(`p`,_,p(Z.value),1)):f(``,!0)])),a(`div`,{ref_key:`tabBarRef`,ref:R,class:`relative mb-[22px] flex gap-0 overflow-x-auto border-b border-card-border`},[(t(),s(l,null,n(Ae,e=>a(`button`,{key:e.value,"data-tab":e.value,type:`button`,class:o([`mr-[22px] whitespace-nowrap bg-none px-0.5 py-[11px] text-sm transition-colors`,I.value===e.value?`font-semibold text-indigo-600`:`font-medium text-faint hover:text-[#8A8A9E]`]),onClick:t=>I.value=e.value},p(e.label),11,v)),64)),a(`div`,{class:`absolute bottom-[-1px] h-[2px] rounded-full bg-indigo-600 transition-[left,width] duration-300`,style:u({left:`${i(je)}px`,width:`${i(Me)}px`})},null,4)],512),L.value&&z.value.length>0&&i(N)(`media:delete`)?(t(),s(`div`,y,[a(`label`,b,[a(`input`,{type:`checkbox`,checked:W.value.size===z.value.length&&z.value.length>0,indeterminate:W.value.size>0&&W.value.size<z.value.length,class:`rounded border-gray-300 text-indigo-600 focus:ring-indigo-500`,onChange:Le},null,40,x),c[7]||=d(` Select all `,-1)]),W.value.size>0?(t(),s(`button`,{key:0,type:`button`,class:`rounded-md bg-red-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-red-700`,onClick:c[2]||=e=>G.value=!0},` Delete `+p(W.value.size)+` selected `,1)):f(``,!0)])):f(``,!0),H.value?(t(),s(`div`,S,[(t(),s(l,null,n(12,e=>a(`div`,{key:e,class:`aspect-square animate-pulse rounded-[14px] bg-gray-100`})),64))])):z.value.length===0?(t(),s(`div`,C,[a(`p`,w,p(L.value?`No orphaned files.`:`No media files yet.`),1)])):(t(),s(`div`,T,[(t(!0),s(l,null,n(z.value,e=>(t(),s(`div`,{key:e.id,class:`group relative aspect-square`},[L.value&&i(N)(`media:delete`)?(t(),s(`label`,{key:0,class:`absolute left-1.5 top-1.5 z-10 cursor-pointer`,onClick:c[3]||=oe(()=>{},[`stop`])},[a(`input`,{type:`checkbox`,checked:W.value.has(e.id),class:`rounded border-gray-300 bg-white text-indigo-600 shadow focus:ring-indigo-500`,onChange:t=>Ie(e.id)},null,40,E)])):f(``,!0),a(`button`,{type:`button`,class:`h-full w-full overflow-hidden rounded-[14px] border border-card-border shadow-[0_1px_2px_rgba(24,24,48,0.04),0_8px_22px_rgba(24,24,48,0.05)] transition-all hover:-translate-y-[3px] hover:shadow-[0_12px_30px_rgba(24,24,48,0.12)] focus:outline-none focus:ring-2 focus:ring-indigo-500`,"aria-label":`View ${e.alt??e.url.split(`/`).pop()}`,onClick:t=>Fe(e.id)},[e.type===`image`?(t(),s(`img`,{key:0,src:e.url,alt:e.alt??``,class:`h-full w-full object-cover`,loading:`lazy`},null,8,O)):(t(),s(`div`,k,[a(`span`,Te,p(e.type===`video`?`▶`:`📄`),1),a(`span`,Ee,p(e.url.split(`/`).pop()),1),a(`span`,De,p(Be(e.file_size)),1)]))],8,D)]))),128))])),!H.value&&B.value>A?(t(),s(`div`,Oe,[ee(me,{total:B.value,page:V.value,"per-page":A,"onUpdate:page":Pe},null,8,[`total`,`page`])])):f(``,!0),G.value?(t(),ne(fe,{key:6,message:`Permanently delete ${W.value.size} file${W.value.size===1?``:`s`}? This cannot be undone.`,"on-confirm":Re,"on-cancel":()=>G.value=!1},null,8,[`message`,`on-cancel`])):f(``,!0)]))}});export{j as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as e,B as t,E as n,O as r,W as i,c as a,d as o,g as s,i as c,j as ee,l,s as u,t as d,u as f,ut as p,w as te}from"./schema-B-RKX_ep.js";import{c as ne,n as re,s as ie,t as ae}from"./index-C-iAN6wp.js";import{a as m,c as oe,i as se,n as ce,o as h,r as le,s as g,t as _}from"./ComputedDisplay-Df_HvjzX.js";import{t as v}from"./useNotification-kY57Myug.js";import{t as y}from"./ConfirmDialog-B7nxdDge.js";import{t as b}from"./taxonomy-DC-6wyg3.js";var ue={key:0,class:`flex items-center justify-center py-20`},de={key:1,class:`py-12 text-center text-sm text-gray-500`},x={key:2},S={class:`mb-6 flex items-start justify-between gap-4`},C={class:`text-xs font-medium uppercase tracking-wide text-gray-400`},w={class:`text-[26px] font-bold tracking-tight text-ink`},T={class:`flex shrink-0 items-center gap-2`},E=[`disabled`],D=[`disabled`],O={class:`space-y-5`},k={key:0,class:`mt-4 text-sm text-red-600`,role:`alert`},A=s({__name:`TaxonomyFormView`,setup(s){let A=ie(),j=ne(),M=ae(),{can:N}=re(),{errors:P,validate:F,mergeServerErrors:I,clearErrors:L,setError:R}=oe(),z=v(),fe=d(),B=b(),V=u(()=>A.params.type),H=u(()=>A.params.id),U=u(()=>!!H.value),W=u(()=>fe.taxonomyTypes[V.value]),G=u(()=>W.value?.fields??[]),K=t(null),q=t({}),J=t(!0),Y=t(!1),X=t(``),Z=t(!1),pe={"text/plain":g,"text/rich":h,integer:m,float:m,boolean:se,date:le,enum:ce,programmatic:_};function me(e){let t=e.field_type;return pe[t]??g}function he(e){switch(e.field_type){case`text/plain`:case`text/rich`:return``;case`integer`:case`float`:return null;case`boolean`:return!1;case`date`:return null;case`enum`:return``;default:return null}}function Q(e){let t={};for(let n of G.value)n.field_type!==`programmatic`&&(t[n.name]=e?.[n.name]??he(n));q.value=t}function ge(e,t){q.value[e]=t}async function $(e){let t=await M.get(`/taxonomy/${V.value}/${e}`);t.ok?(K.value=t.data,Q(t.data)):X.value=t.error.message}te(async()=>{if(!W.value){J.value=!1;return}U.value&&H.value?await $(H.value):Q(),J.value=!1}),ee(H,async(e,t)=>{e!==t&&(J.value=!0,L(),e?await $(e):(K.value=null,Q()),J.value=!1)});async function _e(){if(!F(G.value,q.value))return;Y.value=!0,X.value=``;let e=U.value?await M.patch(`/taxonomy/${V.value}/${H.value}`,q.value):await M.post(`/taxonomy/${V.value}`,q.value);if(Y.value=!1,!e.ok){let t=e.error;t.code===`PUBLISH_VALIDATION_ERROR`&&t.details?I(t.details):t.code===`SLUG_CONFLICT`?R(`slug`,`This slug is already taken.`):X.value=t.message;return}K.value=e.data,B.invalidate(V.value),z.success(`Saved.`),U.value||j.replace({name:`taxonomy-edit`,params:{type:V.value,id:String(e.data.id)}})}async function ve(){Z.value=!1,Y.value=!0;let e=await M.del(`/taxonomy/${V.value}/${H.value}`);if(Y.value=!1,!e.ok){X.value=e.error.message;return}B.invalidate(V.value),j.push({name:`taxonomy-list`,params:{type:V.value}})}let ye=u(()=>{if(!U.value)return`New ${W.value?.label??``}`;let e=G.value.find(e=>e.field_type===`text/plain`);return e?String(K.value?.[e.name]??``):W.value?.label??``});return(t,s)=>J.value?(n(),o(`div`,ue,[...s[1]||=[a(`span`,{class:`inline-block h-6 w-6 animate-spin rounded-full border-2 border-indigo-600 border-t-transparent`,"aria-hidden":`true`},null,-1)]])):W.value?(n(),o(`div`,x,[a(`div`,S,[a(`div`,null,[a(`p`,C,p(W.value.label),1),a(`h1`,w,p(ye.value),1)]),a(`div`,T,[i(N)(`taxonomy:delete`)&&U.value?(n(),o(`button`,{key:0,type:`button`,disabled:Y.value,class:`rounded-md px-3 py-2 text-sm font-medium text-red-600 ring-1 ring-inset ring-red-300 hover:bg-red-50 disabled:cursor-not-allowed disabled:opacity-50`,onClick:s[0]||=e=>Z.value=!0},` Delete `,8,E)):f(``,!0),(U.value?i(N)(`taxonomy:edit`):i(N)(`taxonomy:create`))?(n(),o(`button`,{key:1,type:`button`,disabled:Y.value,class:`rounded-[11px] bg-indigo-600 px-4 py-2.5 text-[13.5px] font-semibold text-white shadow-[0_3px_10px_rgba(91,87,232,0.3)] transition-all hover:bg-indigo-700 hover:shadow-[0_6px_18px_rgba(91,87,232,0.4)] disabled:cursor-not-allowed disabled:opacity-50`,onClick:_e},p(Y.value?`Saving…`:`Save`),9,D)):f(``,!0)])]),a(`div`,O,[(n(!0),o(c,null,r(G.value,t=>(n(),l(e(me(t)),{key:t.name,field:t,"model-value":q.value[t.name],error:i(P)[t.name],disabled:Y.value,"onUpdate:modelValue":e=>ge(t.name,e)},null,8,[`field`,`model-value`,`error`,`disabled`,`onUpdate:modelValue`]))),128))]),X.value?(n(),o(`p`,k,p(X.value),1)):f(``,!0),Z.value?(n(),l(y,{key:1,message:`Are you sure you want to delete this term? This action cannot be undone.`,"on-confirm":ve,"on-cancel":()=>Z.value=!1},null,8,[`on-cancel`])):f(``,!0)])):(n(),o(`div`,de,` Taxonomy type not found. `))}});export{A as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{B as e,S as t,j as n}from"./schema-B-RKX_ep.js";function r(r,i){let a=e(0),o=e(0);function s(){let e=r.value;if(!e)return;let t=e.querySelector(`[data-tab="${i.value}"]`);t&&(a.value=t.offsetLeft,o.value=t.offsetWidth)}return n([r,i],()=>{t(()=>s())},{immediate:!0}),{left:a,width:o,measure:s}}export{r as t};
|