@edgedev/create-edge-app 1.1.28 → 1.2.29

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.
@@ -56,12 +56,34 @@ const props = defineProps({
56
56
  type: String,
57
57
  default: '',
58
58
  },
59
+ validateJson: {
60
+ type: Boolean,
61
+ default: false,
62
+ },
59
63
  })
60
64
 
61
65
  const emit = defineEmits(['update:modelValue', 'lineClick'])
62
66
  const localModelValue = ref(null)
63
67
  const edgeFirebase = inject('edgeFirebase')
64
68
  const expectsJsonObject = ref(false)
69
+ const jsonValidationError = computed(() => {
70
+ if (!props.validateJson || props.language !== 'json')
71
+ return ''
72
+ const raw = localModelValue.value
73
+ if (raw === null || raw === undefined)
74
+ return ''
75
+ const text = String(raw).trim()
76
+ if (!text)
77
+ return ''
78
+ try {
79
+ JSON.parse(text)
80
+ return ''
81
+ }
82
+ catch (error) {
83
+ return `Invalid JSON: ${error.message}`
84
+ }
85
+ })
86
+ const displayError = computed(() => props.error || jsonValidationError.value)
65
87
 
66
88
  const editorOptions = {
67
89
  mode: 'htmlmixed',
@@ -379,11 +401,11 @@ onBeforeUnmount(() => {
379
401
  </template>
380
402
  <template #center>
381
403
  <div class="w-full px-2">
382
- <Alert v-if="props.error" variant="destructive" class="rounded-[6px] py-1">
404
+ <Alert v-if="displayError" variant="destructive" class="rounded-[6px] py-1">
383
405
  <TriangleAlert class="h-4 w-4" />
384
406
  <AlertTitle>Error</AlertTitle>
385
407
  <AlertDescription>
386
- {{ props.error }}
408
+ {{ displayError }}
387
409
  </AlertDescription>
388
410
  </Alert>
389
411
  </div>
@@ -699,10 +699,18 @@ function rewriteAllClasses(scopeEl, theme, isolated = true, viewportMode = 'auto
699
699
  scopeEl.querySelectorAll('[class]').forEach((el) => {
700
700
  let base = el.dataset.viewportBaseClass
701
701
  if (typeof base !== 'string') {
702
- base = el.className || ''
702
+ if (typeof el.className === 'string') {
703
+ base = el.className
704
+ }
705
+ else if (el.className && typeof el.className.baseVal === 'string') {
706
+ base = el.className.baseVal
707
+ }
708
+ else {
709
+ base = el.getAttribute('class') || ''
710
+ }
703
711
  el.dataset.viewportBaseClass = base
704
712
  }
705
- const orig = base || ''
713
+ const orig = typeof base === 'string' ? base : String(base || '')
706
714
  if (!orig.trim())
707
715
  return
708
716
  const origTokens = orig.split(/\s+/).filter(Boolean)
@@ -8,6 +8,11 @@ const props = defineProps({
8
8
  required: false,
9
9
  default: 'all',
10
10
  },
11
+ includeCmsAll: {
12
+ type: Boolean,
13
+ required: false,
14
+ default: true,
15
+ },
11
16
  selectMode: {
12
17
  type: Boolean,
13
18
  required: false,
@@ -137,6 +142,7 @@ onBeforeMount(() => {
137
142
  console.log('Default tags prop:', props.defaultTags)
138
143
  if (props.defaultTags && Array.isArray(props.defaultTags) && props.defaultTags.length > 0) {
139
144
  state.filterTags = [...props.defaultTags]
145
+ state.tags = [...props.defaultTags]
140
146
  }
141
147
  })
142
148
 
@@ -166,6 +172,12 @@ const isLightName = (name) => {
166
172
  }
167
173
 
168
174
  const previewBackgroundClass = computed(() => (isLightName(state.workingDoc?.name) ? 'bg-neutral-900/90' : 'bg-neutral-100'))
175
+
176
+ const siteQueryValue = computed(() => {
177
+ if (!props.site)
178
+ return []
179
+ return props.includeCmsAll ? ['all', props.site] : [props.site]
180
+ })
169
181
  </script>
170
182
 
171
183
  <template>
@@ -228,8 +240,12 @@ const previewBackgroundClass = computed(() => (isLightName(state.workingDoc?.nam
228
240
  v-if="state.tags.length === 0"
229
241
  class="pointer-events-auto absolute inset-0 z-20 rounded-[20px] border border-dashed border-border/70 bg-background/85 dark:bg-background/80 backdrop-blur-sm flex flex-col items-center justify-center text-center px-6 text-foreground"
230
242
  >
231
- <div class="text-lg font-semibold">Tags are required</div>
232
- <div class="text-sm text-muted-foreground">Add tags above to enable upload</div>
243
+ <div class="text-lg font-semibold">
244
+ Tags are required
245
+ </div>
246
+ <div class="text-sm text-muted-foreground">
247
+ Add tags above to enable upload
248
+ </div>
233
249
  </div>
234
250
  </div>
235
251
  </SheetContent>
@@ -239,7 +255,7 @@ const previewBackgroundClass = computed(() => (isLightName(state.workingDoc?.nam
239
255
  sort-field="uploadTime"
240
256
  query-field="meta.cmssite"
241
257
  :filters="filters"
242
- :query-value="['all', props.site]"
258
+ :query-value="siteQueryValue"
243
259
  query-operator="array-contains-any"
244
260
  header-class=""
245
261
  sort-direction="desc" class="w-full flex-1 border-none shadow-none bg-background"
@@ -75,6 +75,42 @@ const normalizeForCompare = (value) => {
75
75
 
76
76
  const stableSerialize = value => JSON.stringify(normalizeForCompare(value))
77
77
  const areEqualNormalized = (a, b) => stableSerialize(a) === stableSerialize(b)
78
+ const isBlankString = value => String(value || '').trim() === ''
79
+ const isJsonInvalid = (value) => {
80
+ if (value === null || value === undefined)
81
+ return false
82
+ if (typeof value === 'object')
83
+ return false
84
+ const text = String(value).trim()
85
+ if (!text)
86
+ return false
87
+ try {
88
+ JSON.parse(text)
89
+ return false
90
+ }
91
+ catch {
92
+ return true
93
+ }
94
+ }
95
+ const hasStructuredDataErrors = (doc) => {
96
+ if (!doc)
97
+ return false
98
+ if (isJsonInvalid(doc.structuredData))
99
+ return true
100
+ if (doc.post && isJsonInvalid(doc.postStructuredData))
101
+ return true
102
+ return false
103
+ }
104
+ const ensurePostSeoDefaults = (doc) => {
105
+ if (!doc?.post)
106
+ return
107
+ if (isBlankString(doc.postMetaTitle))
108
+ doc.postMetaTitle = doc.metaTitle || ''
109
+ if (isBlankString(doc.postMetaDescription))
110
+ doc.postMetaDescription = doc.metaDescription || ''
111
+ if (isBlankString(doc.postStructuredData))
112
+ doc.postStructuredData = doc.structuredData || buildPageStructuredData()
113
+ }
78
114
 
79
115
  const orderedMenus = computed(() => {
80
116
  const menuEntries = Object.entries(modelValue.value || {}).map(([name, menu], originalIndex) => ({
@@ -117,6 +153,9 @@ const isPublishedPageDiff = (pageId) => {
117
153
  metaTitle: publishedPage.metaTitle,
118
154
  metaDescription: publishedPage.metaDescription,
119
155
  structuredData: publishedPage.structuredData,
156
+ postMetaTitle: publishedPage.postMetaTitle,
157
+ postMetaDescription: publishedPage.postMetaDescription,
158
+ postStructuredData: publishedPage.postStructuredData,
120
159
  },
121
160
  {
122
161
  content: draftPage.content,
@@ -126,6 +165,9 @@ const isPublishedPageDiff = (pageId) => {
126
165
  metaTitle: draftPage.metaTitle,
127
166
  metaDescription: draftPage.metaDescription,
128
167
  structuredData: draftPage.structuredData,
168
+ postMetaTitle: draftPage.postMetaTitle,
169
+ postMetaDescription: draftPage.postMetaDescription,
170
+ postStructuredData: draftPage.postStructuredData,
129
171
  },
130
172
  )
131
173
  }
@@ -172,6 +214,9 @@ const state = reactive({
172
214
  metaTitle: { value: '' },
173
215
  metaDescription: { value: '' },
174
216
  structuredData: { value: buildPageStructuredData() },
217
+ postMetaTitle: { value: '' },
218
+ postMetaDescription: { value: '' },
219
+ postStructuredData: { value: '' },
175
220
  tags: { value: [] },
176
221
  allowedThemes: { value: [] },
177
222
  },
@@ -337,12 +382,82 @@ const resolveBlockForPreview = (block) => {
337
382
  return null
338
383
  }
339
384
 
340
- const templateHasBlocks = template => Array.isArray(template?.content) && template.content.length > 0
385
+ const normalizePreviewColumns = (row) => {
386
+ if (!Array.isArray(row?.columns) || !row.columns.length)
387
+ return []
388
+ return row.columns.map((column, idx) => ({
389
+ id: column?.id || `${row?.id || 'row'}-col-${idx}`,
390
+ span: Number(column?.span) || null,
391
+ blocks: Array.isArray(column?.blocks) ? column.blocks.filter(Boolean) : [],
392
+ }))
393
+ }
341
394
 
342
- const templatePreviewBlocks = (template) => {
343
- if (!templateHasBlocks(template))
395
+ const templatePreviewRows = (template) => {
396
+ const structureRows = Array.isArray(template?.structure) ? template.structure : []
397
+ if (structureRows.length) {
398
+ return structureRows
399
+ .map((row, rowIndex) => ({
400
+ id: row?.id || `${template?.docId || 'template'}-row-${rowIndex}`,
401
+ columns: normalizePreviewColumns(row),
402
+ }))
403
+ .filter(row => row.columns.length > 0)
404
+ }
405
+
406
+ const legacyBlocks = Array.isArray(template?.content) ? template.content.filter(Boolean) : []
407
+ if (!legacyBlocks.length)
344
408
  return []
345
- return template.content
409
+ return [{
410
+ id: `${template?.docId || 'template'}-legacy-row`,
411
+ columns: [{
412
+ id: `${template?.docId || 'template'}-legacy-col`,
413
+ span: null,
414
+ blocks: legacyBlocks,
415
+ }],
416
+ }]
417
+ }
418
+
419
+ const templateHasPreview = template => templatePreviewRows(template).length > 0
420
+
421
+ const resolveTemplateBlockSource = (template, blockRef) => {
422
+ if (!blockRef)
423
+ return null
424
+ if (typeof blockRef === 'object')
425
+ return blockRef
426
+ const lookupId = String(blockRef).trim()
427
+ if (!lookupId)
428
+ return null
429
+ const templateBlocks = Array.isArray(template?.content) ? template.content : []
430
+ return templateBlocks.find(block => block?.id === lookupId || block?.blockId === lookupId) || null
431
+ }
432
+
433
+ const resolveTemplateBlockForPreview = (template, blockRef) => {
434
+ const source = resolveTemplateBlockSource(template, blockRef)
435
+ return resolveBlockForPreview(source)
436
+ }
437
+
438
+ const hasPreviewSpans = row => (row?.columns || []).some(column => Number.isFinite(Number(column?.span)))
439
+
440
+ const previewGridClass = (row) => {
441
+ if (hasPreviewSpans(row))
442
+ return 'grid grid-cols-1 sm:grid-cols-6 gap-4'
443
+ const count = row?.columns?.length || 1
444
+ const map = {
445
+ 1: 'grid grid-cols-1 gap-4',
446
+ 2: 'grid grid-cols-1 sm:grid-cols-2 gap-4',
447
+ 3: 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4',
448
+ 4: 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4',
449
+ 5: 'grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-5 gap-4',
450
+ 6: 'grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-6 gap-4',
451
+ }
452
+ return map[count] || map[1]
453
+ }
454
+
455
+ const previewColumnStyle = (column) => {
456
+ const span = Number(column?.span)
457
+ if (!Number.isFinite(span))
458
+ return {}
459
+ const safeSpan = Math.min(Math.max(span, 1), 6)
460
+ return { gridColumn: `span ${safeSpan} / span ${safeSpan}` }
346
461
  }
347
462
 
348
463
  const renameFolderOrPageShow = (item) => {
@@ -526,6 +641,9 @@ const buildPagePayloadFromTemplate = (templateDoc, slug) => {
526
641
  metaTitle: '',
527
642
  metaDescription: '',
528
643
  structuredData,
644
+ postMetaTitle: '',
645
+ postMetaDescription: '',
646
+ postStructuredData: '',
529
647
  doc_created_at: timestamp,
530
648
  last_updated: timestamp,
531
649
  }
@@ -797,6 +915,10 @@ const showPageSettings = (page) => {
797
915
  state.pageSettings = true
798
916
  }
799
917
 
918
+ const handlePageWorkingDoc = (doc) => {
919
+ ensurePostSeoDefaults(doc)
920
+ }
921
+
800
922
  const formErrors = (error) => {
801
923
  console.log('Form errors:', error)
802
924
  console.log(Object.values(error))
@@ -1103,19 +1225,34 @@ const theme = computed(() => {
1103
1225
  Blank page
1104
1226
  </div>
1105
1227
  </template>
1106
- <template v-else-if="templateHasBlocks(template)">
1228
+ <template v-else-if="templateHasPreview(template)">
1107
1229
  <div
1108
- v-for="(block, idx) in templatePreviewBlocks(template)"
1109
- :key="`${template.docId}-block-${idx}`"
1230
+ v-for="(row, rowIndex) in templatePreviewRows(template)"
1231
+ :key="`${template.docId}-row-${row.id || rowIndex}`"
1232
+ class="w-full"
1110
1233
  >
1111
- <edge-cms-block-api
1112
- v-if="resolveBlockForPreview(block)"
1113
- :content="resolveBlockForPreview(block).content"
1114
- :values="resolveBlockForPreview(block).values"
1115
- :meta="resolveBlockForPreview(block).meta"
1116
- :theme="theme"
1117
- :isolated="true"
1118
- />
1234
+ <div :class="previewGridClass(row)">
1235
+ <div
1236
+ v-for="(column, colIndex) in row.columns"
1237
+ :key="`${template.docId}-row-${row.id || rowIndex}-col-${column.id || colIndex}`"
1238
+ class="min-w-0"
1239
+ :style="previewColumnStyle(column)"
1240
+ >
1241
+ <div
1242
+ v-for="(blockRef, blockIdx) in column.blocks || []"
1243
+ :key="`${template.docId}-row-${row.id || rowIndex}-col-${column.id || colIndex}-block-${blockIdx}`"
1244
+ >
1245
+ <edge-cms-block-api
1246
+ v-if="resolveTemplateBlockForPreview(template, blockRef)"
1247
+ :content="resolveTemplateBlockForPreview(template, blockRef).content"
1248
+ :values="resolveTemplateBlockForPreview(template, blockRef).values"
1249
+ :meta="resolveTemplateBlockForPreview(template, blockRef).meta"
1250
+ :theme="theme"
1251
+ :isolated="true"
1252
+ />
1253
+ </div>
1254
+ </div>
1255
+ </div>
1119
1256
  </div>
1120
1257
  </template>
1121
1258
  <template v-else>
@@ -1214,6 +1351,7 @@ const theme = computed(() => {
1214
1351
  :save-function-override="onSubmit"
1215
1352
  card-content-class="px-0"
1216
1353
  @error="formErrors"
1354
+ @working-doc="handlePageWorkingDoc"
1217
1355
  >
1218
1356
  <template #main="slotProps">
1219
1357
  <div class="p-6 space-y-4 h-[calc(100vh-142px)] overflow-y-auto">
@@ -1253,24 +1391,83 @@ const theme = computed(() => {
1253
1391
  <CardDescription>Meta tags for the page.</CardDescription>
1254
1392
  </CardHeader>
1255
1393
  <CardContent class="pt-0">
1256
- <edge-shad-input
1257
- v-model="slotProps.workingDoc.metaTitle"
1258
- label="Meta Title"
1259
- name="metaTitle"
1260
- />
1261
- <edge-shad-textarea
1262
- v-model="slotProps.workingDoc.metaDescription"
1263
- label="Meta Description"
1264
- name="metaDescription"
1265
- />
1266
- <edge-cms-code-editor
1267
- v-model="slotProps.workingDoc.structuredData"
1268
- title="Structured Data (JSON-LD)"
1269
- language="json"
1270
- name="structuredData"
1271
- height="300px"
1272
- class="mb-4 w-full"
1273
- />
1394
+ <Tabs class="w-full" default-value="list">
1395
+ <TabsList v-if="slotProps.workingDoc?.post" class="w-full grid grid-cols-2 gap-1 rounded-lg border border-border/60 bg-muted/30 p-1">
1396
+ <TabsTrigger
1397
+ value="list"
1398
+ class="text-xs font-semibold uppercase tracking-wide transition-all data-[state=active]:bg-slate-900 data-[state=active]:text-white data-[state=active]:shadow-sm"
1399
+ >
1400
+ Index Page
1401
+ </TabsTrigger>
1402
+ <TabsTrigger
1403
+ value="post"
1404
+ class="text-xs font-semibold uppercase tracking-wide transition-all data-[state=active]:bg-slate-900 data-[state=active]:text-white data-[state=active]:shadow-sm"
1405
+ >
1406
+ Detail Page
1407
+ </TabsTrigger>
1408
+ </TabsList>
1409
+ <TabsContent value="list" class="mt-4 space-y-4">
1410
+ <edge-shad-input
1411
+ v-model="slotProps.workingDoc.metaTitle"
1412
+ label="Meta Title"
1413
+ name="metaTitle"
1414
+ />
1415
+ <edge-shad-textarea
1416
+ v-model="slotProps.workingDoc.metaDescription"
1417
+ label="Meta Description"
1418
+ name="metaDescription"
1419
+ />
1420
+ <div class="rounded-md border border-border/60 bg-muted/30 px-3 py-2 text-xs text-muted-foreground">
1421
+ CMS tokens in double curly braces are replaced on the front end.
1422
+ Example: <span v-pre class="font-semibold text-foreground">"{{cms-site}}"</span> for the site URL,
1423
+ <span v-pre class="font-semibold text-foreground">"{{cms-url}}"</span> for the page URL, and
1424
+ <span v-pre class="font-semibold text-foreground">"{{cms-logo}}"</span> for the logo URL. Keep the tokens intact.
1425
+ </div>
1426
+ <edge-cms-code-editor
1427
+ v-model="slotProps.workingDoc.structuredData"
1428
+ title="Structured Data (JSON-LD)"
1429
+ language="json"
1430
+ name="structuredData"
1431
+ validate-json
1432
+ height="300px"
1433
+ class="mb-4 w-full"
1434
+ />
1435
+ </TabsContent>
1436
+ <TabsContent value="post" class="mt-4 space-y-4">
1437
+ <div class="rounded-md border border-border/60 bg-muted/30 px-3 py-2 text-xs text-muted-foreground">
1438
+ You can use template keys in double curly braces to pull data from the detail record.
1439
+ Example: <span v-pre class="font-semibold text-foreground">"{{name}}"</span> will be replaced with the record’s name.
1440
+ Dot notation is supported for nested objects, e.g. <span v-pre class="font-semibold text-foreground">"{{data.name}}"</span>.
1441
+ These keys work in the Title, Description, and Structured Data fields.
1442
+ </div>
1443
+ <edge-shad-input
1444
+ v-model="slotProps.workingDoc.postMetaTitle"
1445
+ label="Meta Title"
1446
+ name="postMetaTitle"
1447
+ />
1448
+ <edge-shad-textarea
1449
+ v-model="slotProps.workingDoc.postMetaDescription"
1450
+ label="Meta Description"
1451
+ name="postMetaDescription"
1452
+ />
1453
+
1454
+ <div class="rounded-md border border-border/60 bg-muted/30 px-3 py-2 text-xs text-muted-foreground">
1455
+ CMS tokens in double curly braces are replaced on the front end.
1456
+ Example: <span v-pre class="font-semibold text-foreground">"{{cms-site}}"</span> for the site URL,
1457
+ <span v-pre class="font-semibold text-foreground">"{{cms-url}}"</span> for the page URL, and
1458
+ <span v-pre class="font-semibold text-foreground">"{{cms-logo}}"</span> for the logo URL. Keep the tokens intact.
1459
+ </div>
1460
+ <edge-cms-code-editor
1461
+ v-model="slotProps.workingDoc.postStructuredData"
1462
+ title="Structured Data (JSON-LD)"
1463
+ language="json"
1464
+ name="postStructuredData"
1465
+ validate-json
1466
+ height="300px"
1467
+ class="mb-4 w-full"
1468
+ />
1469
+ </TabsContent>
1470
+ </Tabs>
1274
1471
  </CardContent>
1275
1472
  </Card>
1276
1473
  </div>
@@ -1278,7 +1475,7 @@ const theme = computed(() => {
1278
1475
  <edge-shad-button variant="destructive" class="text-white" @click="state.pageSettings = false">
1279
1476
  Cancel
1280
1477
  </edge-shad-button>
1281
- <edge-shad-button :disabled="slotProps.submitting" type="submit" class=" bg-slate-800 hover:bg-slate-400 w-full">
1478
+ <edge-shad-button :disabled="slotProps.submitting || hasStructuredDataErrors(slotProps.workingDoc)" type="submit" class=" bg-slate-800 hover:bg-slate-400 w-full">
1282
1479
  <Loader2 v-if="slotProps.submitting" class=" h-4 w-4 animate-spin" />
1283
1480
  Update
1284
1481
  </edge-shad-button>
@@ -2,7 +2,7 @@
2
2
  import { useVModel } from '@vueuse/core'
3
3
  const props = defineProps({
4
4
  modelValue: {
5
- type: [String, Boolean, Number, null],
5
+ type: [String, Boolean, Number, Array, null],
6
6
  required: false,
7
7
  default: null,
8
8
  },
@@ -14,6 +14,10 @@ const props = defineProps({
14
14
  type: String,
15
15
  required: false,
16
16
  },
17
+ multiple: {
18
+ type: Boolean,
19
+ default: false,
20
+ },
17
21
  })
18
22
  const emits = defineEmits(['update:modelValue'])
19
23
  const edgeFirebase = inject('edgeFirebase')
@@ -91,17 +95,30 @@ onBeforeMount(async () => {
91
95
  })
92
96
  .filter(Boolean) // remove nulls
93
97
  }
94
- staticOption.options.unshift({ title: '(none)', name: NONE_VALUE })
98
+ if (!props.multiple) {
99
+ staticOption.options.unshift({ title: '(none)', name: NONE_VALUE })
100
+ }
95
101
  state.loading = false
96
102
  })
97
103
  </script>
98
104
 
99
105
  <template>
100
106
  <edge-shad-select
101
- v-if="!state.loading && staticOption.options.length > 0"
107
+ v-if="!state.loading && staticOption.options.length > 0 && !props.multiple"
102
108
  v-model="selectValue"
103
109
  :label="props.label"
104
110
  :name="props.option.field"
105
111
  :items="staticOption.options"
106
112
  />
113
+ <edge-shad-select-tags
114
+ v-else-if="!state.loading && staticOption.options.length > 0 && props.multiple"
115
+ :model-value="Array.isArray(modelValue) ? modelValue : []"
116
+ :label="props.label"
117
+ :name="props.option.field"
118
+ :items="staticOption.options"
119
+ item-title="title"
120
+ item-value="name"
121
+ :allow-additions="false"
122
+ @update:model-value="value => (modelValue = Array.isArray(value) ? value : [])"
123
+ />
107
124
  </template>
@@ -881,6 +881,9 @@ const isPublishedPageDiff = (pageId) => {
881
881
  metaTitle: publishedPage.metaTitle,
882
882
  metaDescription: publishedPage.metaDescription,
883
883
  structuredData: publishedPage.structuredData,
884
+ postMetaTitle: publishedPage.postMetaTitle,
885
+ postMetaDescription: publishedPage.postMetaDescription,
886
+ postStructuredData: publishedPage.postStructuredData,
884
887
  },
885
888
  {
886
889
  content: draftPage.content,
@@ -890,6 +893,9 @@ const isPublishedPageDiff = (pageId) => {
890
893
  metaTitle: draftPage.metaTitle,
891
894
  metaDescription: draftPage.metaDescription,
892
895
  structuredData: draftPage.structuredData,
896
+ postMetaTitle: draftPage.postMetaTitle,
897
+ postMetaDescription: draftPage.postMetaDescription,
898
+ postStructuredData: draftPage.postStructuredData,
893
899
  },
894
900
  )
895
901
  }
@@ -1087,6 +1093,9 @@ const unpublishedChangeDetails = computed(() => {
1087
1093
  compareField('metaTitle', 'Meta title', val => summarizeChangeValue(val, true))
1088
1094
  compareField('metaDescription', 'Meta description', val => summarizeChangeValue(val, true))
1089
1095
  compareField('structuredData', 'Structured data', val => summarizeChangeValue(val, true))
1096
+ compareField('postMetaTitle', 'Detail meta title', val => summarizeChangeValue(val, true))
1097
+ compareField('postMetaDescription', 'Detail meta description', val => summarizeChangeValue(val, true))
1098
+ compareField('postStructuredData', 'Detail structured data', val => summarizeChangeValue(val, true))
1090
1099
 
1091
1100
  return changes
1092
1101
  })