@mixd-id/web-scaffold 0.2.240706 → 0.2.250801010
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/docs/components/Dashboard.md +56 -0
- package/log.txt +7 -0
- package/package.json +27 -19
- package/src/components/404.vue +61 -0
- package/src/components/AccountIcon.vue +19 -0
- package/src/components/Ahref.vue +1 -1
- package/src/components/Alert.vue +4 -13
- package/src/components/ArrayList.vue +49 -0
- package/src/components/Article.vue +24 -30
- package/src/components/Button.vue +83 -169
- package/src/components/Card.vue +257 -0
- package/src/components/Carousel.vue +61 -60
- package/src/components/Cart.vue +192 -0
- package/src/components/CartIcon.vue +89 -0
- package/src/components/ChartBar.vue +2 -3
- package/src/components/Checkbox.vue +20 -11
- package/src/components/Checkout.vue +373 -0
- package/src/components/CheckoutDelivery.vue +267 -0
- package/src/components/CodeEditor.vue +5 -16
- package/src/components/CollapsiblePanel.vue +70 -0
- package/src/components/ColorPicker.vue +12 -5
- package/src/components/ColorPicker2.vue +41 -19
- package/src/components/ColorPicker3.vue +100 -0
- package/src/components/Confirm.vue +9 -7
- package/src/components/ContextMenu.vue +122 -206
- package/src/components/ContextMenuItem.vue +53 -0
- package/src/components/Dashboard.vue +243 -0
- package/src/components/Dashboard2.vue +118 -0
- package/src/components/DashboardComponentSelector.vue +96 -0
- package/src/components/DashboardConfigs.vue +202 -0
- package/src/components/Datepicker.vue +102 -41
- package/src/components/DayTimeRange.vue +3 -2
- package/src/components/Dropdown.vue +7 -4
- package/src/components/Flex.vue +14 -40
- package/src/components/GHeatMaps.vue +2 -2
- package/src/components/Grid.vue +6 -6
- package/src/components/HTMLEditor.vue +27 -14
- package/src/components/Image.vue +62 -108
- package/src/components/ImagePreview.vue +14 -4
- package/src/components/ImageUploader.vue +114 -0
- package/src/components/ImportModal.vue +3 -3
- package/src/components/Link.vue +62 -6
- package/src/components/List.vue +528 -403
- package/src/components/ListContextMenu.vue +88 -0
- package/src/components/ListItem.vue +6 -4
- package/src/components/ListPage1.vue +14 -15
- package/src/components/ListView.vue +5 -6
- package/src/components/ListViewSettings.vue +2 -2
- package/src/components/LogViewerItem.vue +1 -1
- package/src/components/MarkdownEdit.vue +128 -0
- package/src/components/MarkdownPreview.vue +102 -0
- package/src/components/MenuItem1.vue +36 -0
- package/src/components/Modal.vue +95 -43
- package/src/components/MultiDropdown.vue +124 -0
- package/src/components/MultilineText.vue +1 -4
- package/src/components/OTPField.vue +40 -26
- package/src/components/ObjectTree.vue +1 -1
- package/src/components/PageBuilder.vue +3 -3
- package/src/components/Paragraph.vue +1 -2
- package/src/components/PresetSelectorFilterItem.vue +107 -95
- package/src/components/Radio.vue +1 -1
- package/src/components/SearchModal.vue +153 -0
- package/src/components/Slider.vue +1 -1
- package/src/components/Svg.vue +1 -1
- package/src/components/SvgEditor.vue +173 -0
- package/src/components/Switch.vue +4 -5
- package/src/components/Table.vue +2 -2
- package/src/components/TableView.vue +2 -3
- package/src/components/TableViewHead.vue +2 -2
- package/src/components/Tabs.vue +1 -1
- package/src/components/Testimonial.vue +2 -2
- package/src/components/Text.vue +7 -22
- package/src/components/TextEditor.vue +3 -3
- package/src/components/TextWithTag.vue +61 -30
- package/src/components/Textarea.vue +16 -22
- package/src/components/Textbox.vue +9 -19
- package/src/components/Timepicker.vue +25 -15
- package/src/components/Toast.vue +5 -3
- package/src/components/TreeMenu.vue +122 -0
- package/src/components/TreeView.vue +15 -10
- package/src/components/TreeView2.vue +38 -0
- package/src/components/TreeViewItem.vue +58 -29
- package/src/components/TreeViewItem2.vue +55 -0
- package/src/components/Uploader.vue +45 -0
- package/src/components/Video.vue +119 -0
- package/src/components/VirtualGrid.vue +24 -7
- package/src/components/VirtualTable.vue +363 -128
- package/src/configs/dashboard/data-table.js +9 -0
- package/src/configs/web-page-builder.js +118 -0
- package/src/directives/intersect.js +26 -0
- package/src/hooks/device.js +14 -0
- package/src/index.js +62 -107
- package/src/mixin/component.js +151 -67
- package/src/themes/default/index.js +118 -159
- package/src/utils/dashboard.js +22 -962
- package/src/utils/helpers.cjs +635 -0
- package/src/utils/helpers.js +91 -60
- package/src/utils/helpers.mjs +245 -12
- package/src/utils/importer.js +22 -3
- package/src/utils/list.mjs +1509 -0
- package/src/utils/preset-selector.cjs +1455 -0
- package/src/utils/preset-selector.js +489 -95
- package/src/utils/preset-selector.mjs +59 -20
- package/src/utils/queue.js +63 -0
- package/src/utils/web.mjs +120 -0
- package/src/utils/wss.js +38 -36
- package/src/utils/wss.mjs +24 -19
- package/src/widgets/AhrefSetting.vue +16 -13
- package/src/widgets/ArticleSetting.vue +15 -27
- package/src/widgets/BackgroundColorSetting.vue +153 -0
- package/src/widgets/BorderColorSetting.vue +57 -0
- package/src/widgets/BotEditor/BotEditorActions.vue +3 -2
- package/src/widgets/BotEditor/BotEditorSettings.vue +21 -0
- package/src/widgets/BotEditor.vue +35 -15
- package/src/widgets/ButtonSetting.vue +12 -13
- package/src/widgets/CarouselSetting.vue +33 -45
- package/src/widgets/CartSetting.vue +46 -0
- package/src/widgets/CheckoutSetting.vue +46 -0
- package/src/widgets/CollapsiblePanelSetting.vue +46 -0
- package/src/widgets/ColumnSelector.vue +29 -5
- package/src/widgets/ComponentSetting.vue +1 -1
- package/src/widgets/ComponentSetting2.vue +145 -236
- package/src/widgets/ComponentSetting3.vue +1 -1
- package/src/widgets/ContactForm.vue +3 -3
- package/src/widgets/ContactFormSetting.vue +41 -30
- package/src/widgets/Dashboard/BarChart.vue +47 -11
- package/src/widgets/Dashboard/BarChartSetting.vue +1 -1
- package/src/widgets/Dashboard/DataTable.vue +125 -0
- package/src/widgets/Dashboard/DataTableSetting.vue +243 -0
- package/src/widgets/Dashboard/DatasourceSelector.vue +1 -1
- package/src/widgets/Dashboard/Doughnut.vue +49 -7
- package/src/widgets/Dashboard/DoughnutSetting.vue +2 -2
- package/src/widgets/Dashboard/Metric.vue +78 -19
- package/src/widgets/Dashboard/MetricSetting.vue +81 -28
- package/src/widgets/Dashboard/Pie.vue +55 -6
- package/src/widgets/Dashboard/PieSetting.vue +1 -1
- package/src/widgets/Dashboard/PolarArea.vue +49 -7
- package/src/widgets/Dashboard/PolarAreaSetting.vue +1 -1
- package/src/widgets/Dashboard/SharingModal.vue +4 -5
- package/src/widgets/Dashboard/ViewSelector.vue +2 -2
- package/src/widgets/Dashboard/VirtualTableSetting.vue +121 -184
- package/src/widgets/{Dashboard.vue → Dashboard0.vue} +426 -343
- package/src/widgets/EmbeddedVideoSetting.vue +7 -5
- package/src/widgets/FAQ.vue +16 -3
- package/src/widgets/FAQSetting.vue +53 -47
- package/src/widgets/FeatureList.vue +3 -0
- package/src/widgets/FeatureListSetting.vue +112 -102
- package/src/widgets/FlexSetting.vue +83 -106
- package/src/widgets/GridSetting.vue +71 -196
- package/src/widgets/Header2.vue +34 -71
- package/src/widgets/Header2Setting.vue +95 -179
- package/src/widgets/HeaderSetting.vue +16 -18
- package/src/widgets/IconListSetting.vue +69 -65
- package/src/widgets/ImageSetting.vue +33 -60
- package/src/widgets/LinkSetting.vue +60 -37
- package/src/widgets/LinkSettingModal.vue +173 -0
- package/src/widgets/LogViewer.vue +1 -1
- package/src/widgets/MarginSetting.vue +2 -2
- package/src/widgets/MenuEditor.vue +1 -1
- package/src/widgets/MenuItem1Setting.vue +78 -0
- package/src/widgets/ModalSetting.vue +42 -44
- package/src/widgets/MultiValueSetting.vue +2 -2
- package/src/widgets/MultiValueSetting2.vue +78 -45
- package/src/widgets/OGSettingModal.vue +103 -0
- package/src/widgets/PaddingSetting.vue +2 -2
- package/src/widgets/ParagraphSetting.vue +16 -13
- package/src/widgets/PositionSetting.vue +209 -0
- package/src/widgets/PresetBar.vue +359 -210
- package/src/widgets/PresetBarPivot.vue +31 -19
- package/src/widgets/PresetSelector.vue +29 -17
- package/src/widgets/SearchModalSetting.vue +70 -0
- package/src/widgets/Share.vue +1 -2
- package/src/widgets/ShareSetting.vue +67 -60
- package/src/widgets/StyleSetting.vue +365 -150
- package/src/widgets/TestimonialSetting.vue +97 -88
- package/src/widgets/TextBlockSetting.vue +16 -13
- package/src/widgets/UserActionBuilder/UserActionConsole.vue +30 -10
- package/src/widgets/UserActionBuilder/UserActionOutput.vue +2 -2
- package/src/widgets/UserActionBuilder/UserActionOutputReply.vue +64 -87
- package/src/widgets/UserActionBuilder/UserActionProps.vue +3 -3
- package/src/widgets/UserActionBuilder.vue +4 -16
- package/src/widgets/WebComponentSelector.vue +15 -11
- package/src/widgets/WebLayoutSelector.vue +41 -270
- package/src/widgets/WebPageBuilder.vue +1019 -707
- package/src/widgets/WebPageBuilder2.vue +7 -7
- package/src/widgets/WebPageBuilder4/ButtonSetting.vue +0 -8
- package/src/widgets/WebPageBuilder4/CarouselSetting.vue +63 -7
- package/src/widgets/WebPageBuilder4/FlexAlignSetting.vue +3 -3
- package/src/widgets/WebPageBuilder4/FlexSetting.vue +1 -10
- package/src/widgets/WebPageBuilder4/MultiValueSetting.vue +2 -2
- package/src/widgets/WebPageBuilder4/PropertySetting.vue +0 -7
- package/src/widgets/WebPageBuilder4/WebPageComponentSelector.vue +1 -7
- package/src/widgets/WebPageBuilder4.vue +289 -575
- package/src/widgets/WebPageSelector.vue +1 -1
- package/src/widgets/YoutubeVideoSetting.vue +16 -13
- package/tailwind.config.js +3 -35
- package/docs/schema/user-action.json +0 -266
- package/src/App.vue +0 -25
- package/src/components/SearchButton.vue +0 -57
- package/src/entry-client.js +0 -27
- package/src/entry-server.js +0 -73
- package/src/events/event.js +0 -2
- package/src/main.js +0 -29
- package/src/mixin/website.js +0 -121
- package/src/router.js +0 -57
- package/src/widgets/MobileMenu.vue +0 -182
- package/src/widgets/WebPageBuilder4/ActionSetting.vue +0 -158
- package/src/widgets/WebPageBuilder4/ColorSetting.vue +0 -63
- package/src/widgets/WebPageBuilder4/DataSetting.vue +0 -92
- package/src/widgets/WebPageBuilder4/FontSizeSetting.vue +0 -76
- package/src/widgets/WebPageBuilder4/LinkSetting.vue +0 -68
- package/src/widgets/WebPageBuilder4/MobileMenuSetting.vue +0 -106
- package/src/widgets/WebPageBuilder4/Setting.vue +0 -73
- package/src/widgets/WebPageBuilder4/StyleSetting.vue +0 -77
- package/src/widgets/WebPageBuilder4/SvgSetting.vue +0 -207
- package/src/widgets/WebPageBuilder4/TextTransformSetting.vue +0 -70
- package/src/widgets/WebPageBuilder4/WebPageDataEdit.vue +0 -121
- package/test.json +0 -22
- /package/src/widgets/{Header1.vue → Header0.vue} +0 -0
- /package/src/widgets/{Header1Setting.vue → Header0Setting.vue} +0 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="flex-1 flex items-center justify-center" v-if="
|
|
2
|
+
<div class="flex-1 flex items-center justify-center" v-if="readyState === 2">
|
|
3
3
|
<svg class="animate-spin aspect-square w-[48px]" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
|
4
4
|
</div>
|
|
5
5
|
<div :class="$style.comp" v-else-if="page">
|
|
6
6
|
|
|
7
7
|
<div class="flex-1 flex flex-col bg-base-400">
|
|
8
8
|
|
|
9
|
-
<div class="p-3 pr-5
|
|
10
|
-
<div class="flex-1 flex flex-row gap-4 items-center"
|
|
9
|
+
<div class="p-3 pr-5 flex justify-center gap-4 border-b-[1px] border-border-50">
|
|
10
|
+
<div class="flex-1 flex flex-row gap-4 items-center"
|
|
11
|
+
@click.meta="log(page)"
|
|
12
|
+
@click.alt="log(layout)">
|
|
11
13
|
|
|
12
14
|
<button ref="close" class=" p-1"
|
|
13
15
|
@click="close">
|
|
@@ -23,27 +25,18 @@
|
|
|
23
25
|
<template #start>
|
|
24
26
|
<div class="flex flex-row items-center mr-2">
|
|
25
27
|
<button @click="reloadIframe" class="p-3">
|
|
26
|
-
<svg width="14" height="14" viewBox="0 0 24 24" class="fill-
|
|
28
|
+
<svg width="14" height="14" viewBox="0 0 24 24" class="fill-primary" xmlns="http://www.w3.org/2000/svg">
|
|
27
29
|
<path d="M3.75 12C3.75 7.44365 7.44365 3.75 12 3.75C14.7802 3.75 17.1982 5.12612 18.6816 7.24467L16.5022 7.23828C16.088 7.23707 15.7512 7.57187 15.75 7.98608C15.7488 8.4003 16.0836 8.73706 16.4978 8.73828L19.9491 8.74839C19.9817 8.75065 20.0147 8.75076 20.0477 8.74868L20.4978 8.75C20.6971 8.75058 20.8884 8.67182 21.0296 8.53111C21.1707 8.39039 21.25 8.19929 21.25 8L21.25 4C21.25 3.58579 20.9142 3.25 20.5 3.25C20.0858 3.25 19.75 3.58579 19.75 4L19.75 6.16237C17.9894 3.79113 15.2004 2.25 12 2.25C6.61522 2.25 2.25 6.61522 2.25 12C2.25 17.3848 6.61522 21.75 12 21.75C15.8354 21.75 19.0799 19.5367 20.6716 16.3338C20.856 15.9628 20.7047 15.5127 20.3338 15.3284C19.9628 15.144 19.5127 15.2953 19.3284 15.6662C17.9747 18.3902 15.2321 20.25 12 20.25C7.44365 20.25 3.75 16.5563 3.75 12Z"/>
|
|
28
30
|
</svg>
|
|
29
31
|
</button>
|
|
30
|
-
<select v-model="store.zoomLevel" :class="$style.zoomLevel" @change="resize()">
|
|
31
|
-
<optgroup label="Zoom Level">
|
|
32
|
-
<option value="fit">Fit</option>
|
|
33
|
-
<option value="125%">125%</option>
|
|
34
|
-
<option value="100%">100%</option>
|
|
35
|
-
<option value="75%">75%</option>
|
|
36
|
-
<option value="50%">50%</option>
|
|
37
|
-
</optgroup>
|
|
38
|
-
</select>
|
|
39
32
|
</div>
|
|
40
33
|
</template>
|
|
41
34
|
<template #end>
|
|
42
|
-
<div class="flex flex-row gap-
|
|
43
|
-
<CopyToClipboard :value="computedIframeSrc" @copied="toast($t('Copied'))">
|
|
35
|
+
<div class="flex flex-row gap-5 ml-3">
|
|
36
|
+
<CopyToClipboard :value="computedIframeSrc" @copied="toast($t('URL Copied'))">
|
|
44
37
|
<svg width="14" height="14" class="fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM352 32.491a15.88 15.88 0 0 1 7.431 4.195l51.882 51.883A15.885 15.885 0 0 1 415.508 96H352V32.491zM288 464c0 8.822-7.178 16-16 16H48c-8.822 0-16-7.178-16-16V144c0-8.822 7.178-16 16-16h80v240c0 26.51 21.49 48 48 48h112v48zm128-96c0 8.822-7.178 16-16 16H176c-8.822 0-16-7.178-16-16V48c0-8.822 7.178-16 16-16h144v72c0 13.2 10.8 24 24 24h72v240z"/></svg>
|
|
45
38
|
</CopyToClipboard>
|
|
46
|
-
<a type="button" class="w-[
|
|
39
|
+
<a type="button" class="w-[24px]" :href="computedIframeSrc" target="_blank">
|
|
47
40
|
<svg width="12" height="12" class="fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M497.6,0,334.4.17A14.4,14.4,0,0,0,320,14.57V47.88a14.4,14.4,0,0,0,14.69,14.4l73.63-2.72,2.06,2.06L131.52,340.49a12,12,0,0,0,0,17l23,23a12,12,0,0,0,17,0L450.38,101.62l2.06,2.06-2.72,73.63A14.4,14.4,0,0,0,464.12,192h33.31a14.4,14.4,0,0,0,14.4-14.4L512,14.4A14.4,14.4,0,0,0,497.6,0ZM432,288H416a16,16,0,0,0-16,16V458a6,6,0,0,1-6,6H54a6,6,0,0,1-6-6V118a6,6,0,0,1,6-6H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V304A16,16,0,0,0,432,288Z"/></svg>
|
|
48
41
|
</a>
|
|
49
42
|
</div>
|
|
@@ -51,9 +44,9 @@
|
|
|
51
44
|
</Textbox>
|
|
52
45
|
</div>
|
|
53
46
|
|
|
54
|
-
<Tabs :items="previewModes" v-model="store.previewMode" variant="button" @change="updateIframe" />
|
|
47
|
+
<Tabs :items="previewModes" v-model="store.previewMode" variant="button" @change="updateIframe" class="rounded-full" />
|
|
55
48
|
|
|
56
|
-
<div v-if="pageHistory" class="flex flex-row border-[1px] border-
|
|
49
|
+
<div v-if="pageHistory" class="flex flex-row border-[1px] border-border-200 bg-text-50 rounded-full overflow-hidden">
|
|
57
50
|
<button type="button" class="p-2 px-3 group"
|
|
58
51
|
:class="pageHistory.canUndo.value && pageHistory.history.value.length > 2 ? 'hover:bg-primary' : 'opacity-50 cursor-not-allowed'"
|
|
59
52
|
:disabled="!(pageHistory.canUndo.value && pageHistory.history.value.length > 2)"
|
|
@@ -76,27 +69,27 @@
|
|
|
76
69
|
class="w-[70px] rounded-full p-1"
|
|
77
70
|
:state="canSave ? 1 : -1"
|
|
78
71
|
@click="save">{{ $t('Save') }}</Button>
|
|
72
|
+
|
|
79
73
|
</div>
|
|
80
74
|
</div>
|
|
81
75
|
|
|
82
76
|
<div class="flex-1 flex flex-row">
|
|
83
77
|
|
|
84
|
-
<div class="flex flex-row
|
|
78
|
+
<div ref="leftPanel" class="flex flex-row"
|
|
85
79
|
:style="section1Style">
|
|
86
80
|
|
|
87
81
|
<div class="flex-1 flex flex-col overflow-y-auto">
|
|
88
82
|
|
|
89
|
-
<div class="flex flex-col
|
|
83
|
+
<div class="flex flex-col px-3 border-b-[1px] border-border-100 overflow-x-auto no-scrollbar pt-1">
|
|
90
84
|
<Tabs :items="tabItems"
|
|
91
|
-
class="pt-1"
|
|
92
85
|
v-model="store.tabIndex" />
|
|
93
86
|
</div>
|
|
94
87
|
|
|
95
|
-
<div v-if="store.tabIndex === 1" class="flex-1 overflow-y-auto flex flex-col gap-4 p-6"
|
|
88
|
+
<div v-if="store.tabIndex === 1" class="flex-1 overflow-y-auto flex flex-col gap-4 p-6">
|
|
96
89
|
|
|
97
90
|
<div class="flex flex-row gap-4" v-if="!page.isSystem">
|
|
98
91
|
<div class="flex flex-col gap-1">
|
|
99
|
-
<
|
|
92
|
+
<small class="text-text-400 w-[40px]">{{ $t('Status') }}</small>
|
|
100
93
|
<Dropdown v-model="page.status">
|
|
101
94
|
<option :value="-1">{{ $t('Disabled') }}</option>
|
|
102
95
|
<option :value="0">{{ $t('Draft') }}</option>
|
|
@@ -105,52 +98,55 @@
|
|
|
105
98
|
</div>
|
|
106
99
|
|
|
107
100
|
<div class="flex-1">
|
|
108
|
-
<
|
|
101
|
+
<small class="text-text-400">{{ $t('Path')}}</small>
|
|
109
102
|
<Textbox v-model="page.path" />
|
|
110
103
|
</div>
|
|
111
104
|
</div>
|
|
112
105
|
|
|
113
106
|
<div class="flex flex-col gap-1">
|
|
114
|
-
<
|
|
107
|
+
<small class="text-text-400">{{ $t('Title')}}</small>
|
|
115
108
|
<Textbox v-model="page.title" />
|
|
116
109
|
</div>
|
|
117
110
|
|
|
118
111
|
<div class="flex flex-col gap-1">
|
|
119
|
-
<
|
|
112
|
+
<small class="text-text-400">{{ $t('Description')}}</small>
|
|
120
113
|
<Textarea v-model="page.description" />
|
|
121
114
|
</div>
|
|
122
115
|
|
|
123
116
|
<div class="flex flex-col gap-1">
|
|
124
|
-
<
|
|
117
|
+
<small class="text-text-400">{{ $t('Keywords')}}</small>
|
|
125
118
|
<Textbox v-model="page.keywords" />
|
|
126
119
|
</div>
|
|
127
120
|
|
|
128
121
|
<div>
|
|
129
122
|
<div class="mb-1">
|
|
130
|
-
<
|
|
123
|
+
<small class="text-text-400">{{ $t('OG')}}</small>
|
|
131
124
|
</div>
|
|
132
|
-
<div class="flex flex-row gap-
|
|
133
|
-
@click="$refs.ogModal.open({ ...this.page.og })"
|
|
125
|
+
<div class="flex flex-row gap-2 bg-base-500 border-[1px] border-border-200 rounded-lg p-1 cursor-pointer"
|
|
126
|
+
@click="$refs.ogModal.open({ ...this.page.og }, og => page.og = og)"
|
|
134
127
|
v-if="page.og && Object.keys(page.og).length > 0">
|
|
135
128
|
<div>
|
|
136
|
-
<Image :src="
|
|
129
|
+
<Image :src="page.og.image" class="w-[40px] aspect-square bg-text-50" />
|
|
137
130
|
</div>
|
|
138
131
|
<div class="flex-1 flex flex-col">
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
132
|
+
<label class="text-sm text-ellipsis-nowrap">
|
|
133
|
+
{{ page.og.title }}
|
|
134
|
+
</label>
|
|
135
|
+
<small class="text-sm text-ellipsis-nowrap">
|
|
136
|
+
{{ page.og.description }}
|
|
137
|
+
</small>
|
|
142
138
|
</div>
|
|
143
139
|
</div>
|
|
144
|
-
<div v-else class="bg-base-500 p-2 text-center border-[1px] border-
|
|
145
|
-
@click="$refs.ogModal.open(
|
|
140
|
+
<div v-else class="bg-base-500 p-2 text-center border-[1px] border-border-100 rounded-lg cursor-pointer"
|
|
141
|
+
@click="$refs.ogModal.open(page.og, og => page.og = og)">
|
|
146
142
|
Set OG
|
|
147
143
|
</div>
|
|
148
144
|
</div>
|
|
149
145
|
|
|
150
146
|
<div>
|
|
151
147
|
<div class="flex flex-row gap-2 mb-1">
|
|
152
|
-
<
|
|
153
|
-
<button type="button" class="text-primary" @click="$refs.ldjsonModal.open({})">
|
|
148
|
+
<small class="flex-1 text-text-400">{{ $t('JSON-LD')}}</small>
|
|
149
|
+
<button type="button" class="text-primary text-sm" @click="$refs.ldjsonModal.open({})">
|
|
154
150
|
{{ $t('Add') }}
|
|
155
151
|
</button>
|
|
156
152
|
</div>
|
|
@@ -166,46 +162,97 @@
|
|
|
166
162
|
</div>
|
|
167
163
|
</template>
|
|
168
164
|
</ListItem>
|
|
169
|
-
<div v-else class="bg-base-500 p-2 text-center border-[1px] border-
|
|
165
|
+
<div v-else class="bg-base-500 p-2 text-center border-[1px] border-border-100 rounded-lg cursor-pointer text-text-300">
|
|
170
166
|
No JSON-LD set
|
|
171
167
|
</div>
|
|
172
168
|
</div>
|
|
173
169
|
|
|
174
170
|
<div>
|
|
175
|
-
<
|
|
176
|
-
<Dropdown v-model="page.noIndex" class="max-w-[
|
|
171
|
+
<small class="flex-1 text-text-400">{{ $t('No Index')}}</small>
|
|
172
|
+
<Dropdown v-model="page.noIndex" class="w-full max-w-[300px]">
|
|
177
173
|
<option value="none">None</option>
|
|
178
174
|
<option value="robots">All</option>
|
|
179
175
|
<option value="googlebot">Google Bot</option>
|
|
180
176
|
</Dropdown>
|
|
181
177
|
</div>
|
|
182
178
|
|
|
183
|
-
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<div v-else-if="store.tabIndex === 2" class="flex-1 overflow-y-auto p-6 flex flex-col gap-6">
|
|
184
182
|
|
|
185
183
|
<div>
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
184
|
+
<div class="flex flex-row gap-1 items-end cursor-pointer">
|
|
185
|
+
<small class="flex-1 text-text-400 text-overflow-ellipsis">{{ $t('Components')}}</small>
|
|
186
|
+
<button type="button" class="text-primary text-sm flex flex-row items-center gap-1"
|
|
187
|
+
@click="openComponentSelector({ callback:(component) => page.components.push(component) })">
|
|
188
|
+
{{ $t('Add')}}
|
|
189
|
+
</button>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<div class="flex flex-col gap-10">
|
|
193
|
+
<TreeView class="mt-2"
|
|
194
|
+
v-model="page.components"
|
|
195
|
+
:selected-item="currentItem"
|
|
196
|
+
@add="(items) => openComponentSelector({ callback:(component) => items.push(component) })"
|
|
197
|
+
@duplicate="duplicate"
|
|
198
|
+
@change="pageHistory.commit()">
|
|
199
|
+
<template #default="{ item }">
|
|
200
|
+
<div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
|
|
201
|
+
:class="!item.props.enabled ? 'line-through' : ''"
|
|
202
|
+
@click="select(item.uid)">
|
|
203
|
+
{{ item.props.name ?? item.type }}
|
|
204
|
+
</div>
|
|
205
|
+
</template>
|
|
206
|
+
</TreeView>
|
|
207
|
+
</div>
|
|
192
208
|
</div>
|
|
193
209
|
|
|
194
|
-
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<div v-else-if="store.tabIndex === 3" class="flex-1 overflow-y-auto p-6">
|
|
213
|
+
|
|
214
|
+
<div class="p-6 flex flex-col gap-2" v-if="Array.isArray(page.datasource) && page.datasource.length > 0">
|
|
215
|
+
<div v-for="(ds, index) in page.datasource"
|
|
216
|
+
class="p-3 border-[1px] border-border-50 rounded-lg flex flex-row items-start gap-2">
|
|
217
|
+
<div class="flex-1 flex flex-col" @click="$refs.webDatasourceSelector.open({ _index:index, ...ds })">
|
|
218
|
+
<label>{{ ds.name }}</label>
|
|
219
|
+
</div>
|
|
220
|
+
<button type="button"
|
|
221
|
+
@click="removeDatasource(index)">
|
|
222
|
+
<svg width="14" height="14" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
|
|
223
|
+
</button>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
<div v-else>
|
|
227
|
+
<div class="p-6 text-center">
|
|
228
|
+
<small class="text-text-400">{{ $t('No Datasource')}}</small>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<div class="text-center" v-if="useDatasource">
|
|
233
|
+
<button type="button" class="text-primary"
|
|
234
|
+
@click="$refs.webDatasourceSelector.create()">
|
|
235
|
+
Add Datasource
|
|
236
|
+
</button>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
<WebDatasourceSelector ref="webDatasourceSelector"
|
|
240
|
+
@apply="addDatasource"
|
|
241
|
+
:use-datasource="useDatasource" />
|
|
195
242
|
|
|
196
243
|
</div>
|
|
197
244
|
|
|
198
|
-
<div v-else-if="store.tabIndex ===
|
|
245
|
+
<div v-else-if="store.tabIndex === 4" class="flex-1 overflow-y-auto flex flex-col">
|
|
199
246
|
|
|
200
|
-
<div>
|
|
201
|
-
<div class="flex flex-row gap-2"
|
|
202
|
-
<
|
|
203
|
-
<button type="button" class="text-primary" @click="store.layoutMode = !store.layoutMode">
|
|
204
|
-
{{ store.layoutMode ? 'Hide Layout' : '
|
|
247
|
+
<div class="p-6">
|
|
248
|
+
<div class="flex flex-row items-end gap-2">
|
|
249
|
+
<small class="flex-1 text-text-400">{{ $t('Layout')}}</small>
|
|
250
|
+
<button type="button" class="text-primary text-sm" @click="store.layoutMode = !store.layoutMode">
|
|
251
|
+
{{ store.layoutMode ? 'Hide Layout' : 'Edit Layout' }}
|
|
205
252
|
</button>
|
|
206
253
|
</div>
|
|
207
|
-
<div class="mt-
|
|
208
|
-
<div class="cursor-pointer bg-text-50 p-2 border-[1px] border-
|
|
254
|
+
<div class="mt-1">
|
|
255
|
+
<div class="cursor-pointer bg-text-50 p-2 border-[1px] border-border-200 flex flex-row items-center rounded-lg"
|
|
209
256
|
@click="(e) => $refs.layoutSelector.open(e.target)">
|
|
210
257
|
<div class="flex-1 pointer-events-none">
|
|
211
258
|
{{ layout ? (layout.name ?? layout.title) : 'None' }}
|
|
@@ -218,19 +265,21 @@
|
|
|
218
265
|
</div>
|
|
219
266
|
|
|
220
267
|
<ContextMenu ref="layoutSelector">
|
|
221
|
-
<div class="flex flex-col min-w-[260px] divide-y divide-
|
|
268
|
+
<div class="flex flex-col min-w-[260px] divide-y divide-border-50">
|
|
222
269
|
|
|
223
|
-
<div
|
|
270
|
+
<div @click="page.layoutId = null;" :class="appStyle.menuItem">None</div>
|
|
224
271
|
|
|
225
272
|
<div v-for="layout in layouts"
|
|
226
|
-
class="
|
|
273
|
+
:class="appStyle.menuItem"
|
|
227
274
|
@click="page.layoutId = layout.id;pageHistory.commit()">
|
|
228
275
|
{{ layout.name ?? layout.title }}
|
|
229
276
|
</div>
|
|
230
277
|
|
|
231
|
-
<div class="flex flex-row"
|
|
232
|
-
<
|
|
233
|
-
|
|
278
|
+
<div class="flex flex-row">
|
|
279
|
+
<button type="button" class="p-3 flex-1 cursor-pointer text-primary"
|
|
280
|
+
@click="$refs.webLayoutSelector.create({})">
|
|
281
|
+
Create New...
|
|
282
|
+
</button>
|
|
234
283
|
</div>
|
|
235
284
|
|
|
236
285
|
</div>
|
|
@@ -238,57 +287,26 @@
|
|
|
238
287
|
</div>
|
|
239
288
|
</div>
|
|
240
289
|
|
|
241
|
-
<div v-if="
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
@click="store.selectedComponent = [ 'style' ]">Edit Style</button>
|
|
246
|
-
</div>
|
|
247
|
-
|
|
248
|
-
<div v-if="store.layoutMode && layout" @click="currentArea = 'headers'">
|
|
249
|
-
<div class="flex flex-row gap-1 items-center cursor-pointer">
|
|
250
|
-
<svg v-if="!expanded['headers']" width="12" height="12" @click="expanded['headers'] = !expanded['headers']" class="fill-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"/></svg>
|
|
251
|
-
<svg v-else width="12" height="12" @click="expanded['headers'] = !expanded['headers']" class="fill-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"/></svg>
|
|
252
|
-
<strong class="flex-1 text-text-400 line-clamp-1" @click="expanded['headers'] = !expanded['headers']">{{ $t('Header')}}</strong>
|
|
253
|
-
<button type="button" class="text-primary flex flex-row items-center gap-1"
|
|
254
|
-
@click="openComponentSelector({ items:layout.headers, isLayout:true })">
|
|
255
|
-
<svg width="16" height="16" class="fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M376 232H216V72c0-4.42-3.58-8-8-8h-32c-4.42 0-8 3.58-8 8v160H8c-4.42 0-8 3.58-8 8v32c0 4.42 3.58 8 8 8h160v160c0 4.42 3.58 8 8 8h32c4.42 0 8-3.58 8-8V280h160c4.42 0 8-3.58 8-8v-32c0-4.42-3.58-8-8-8z"/></svg>
|
|
256
|
-
{{ $t('Add')}}
|
|
257
|
-
</button>
|
|
258
|
-
</div>
|
|
259
|
-
<div v-if="expanded['headers']" class="flex flex-col gap-10">
|
|
260
|
-
<TreeView class="mt-2"
|
|
261
|
-
v-model="layoutHeaders"
|
|
262
|
-
:selected-item="currentItem"
|
|
263
|
-
@add="(items) => openComponentSelector({ items })">
|
|
264
|
-
<template #default="{ item }">
|
|
265
|
-
<div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
|
|
266
|
-
:class="!item.props.enabled ? 'line-through' : ''"
|
|
267
|
-
@click="select(item.uid)">
|
|
268
|
-
{{ item.name ?? item.type }}
|
|
269
|
-
</div>
|
|
270
|
-
</template>
|
|
271
|
-
</TreeView>
|
|
290
|
+
<div v-if="layout" class="flex flex-col gap-6 p-6 border-t-[1px] border-border-50">
|
|
291
|
+
<div>
|
|
292
|
+
<small class="text-text-400">Name</small>
|
|
293
|
+
<Textbox v-model="layout.title"/>
|
|
272
294
|
</div>
|
|
273
|
-
</div>
|
|
274
295
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
{{ $t('Add')}}
|
|
284
|
-
</button>
|
|
285
|
-
</div>
|
|
296
|
+
<div>
|
|
297
|
+
<div class="flex flex-row gap-1 items-end cursor-pointer">
|
|
298
|
+
<small class="flex-1 text-text-400 text-overflow-ellipsis">{{ $t('Headers')}}</small>
|
|
299
|
+
<button type="button" class="text-primary text-sm flex flex-row items-center gap-1"
|
|
300
|
+
@click="openComponentSelector({ callback:(component) => layout.headers.push(component) })">
|
|
301
|
+
{{ $t('Add')}}
|
|
302
|
+
</button>
|
|
303
|
+
</div>
|
|
286
304
|
|
|
287
|
-
<div v-if="expanded['components']" class="flex flex-col gap-10">
|
|
288
305
|
<TreeView class="mt-2"
|
|
289
|
-
v-model="
|
|
306
|
+
v-model="layout.headers"
|
|
290
307
|
:selected-item="currentItem"
|
|
291
|
-
@add="(items) => openComponentSelector({ items })"
|
|
308
|
+
@add="(items) => openComponentSelector({ callback:(component) => items.push(component) })"
|
|
309
|
+
@duplicate="duplicate"
|
|
292
310
|
@change="pageHistory.commit()">
|
|
293
311
|
<template #default="{ item }">
|
|
294
312
|
<div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
|
|
@@ -300,25 +318,21 @@
|
|
|
300
318
|
</TreeView>
|
|
301
319
|
</div>
|
|
302
320
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
@click="openComponentSelector({ items:layoutFooters, isLayout:true })">
|
|
312
|
-
<svg width="16" height="16" class="fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M376 232H216V72c0-4.42-3.58-8-8-8h-32c-4.42 0-8 3.58-8 8v160H8c-4.42 0-8 3.58-8 8v32c0 4.42 3.58 8 8 8h160v160c0 4.42 3.58 8 8 8h32c4.42 0 8-3.58 8-8V280h160c4.42 0 8-3.58 8-8v-32c0-4.42-3.58-8-8-8z"/></svg>
|
|
313
|
-
{{ $t('Add')}}
|
|
314
|
-
</button>
|
|
315
|
-
</div>
|
|
321
|
+
<div>
|
|
322
|
+
<div class="flex flex-row gap-1 items-end cursor-pointer">
|
|
323
|
+
<small class="flex-1 text-text-400 text-overflow-ellipsis">{{ $t('Footers')}}</small>
|
|
324
|
+
<button type="button" class="text-primary text-sm flex flex-row items-center gap-1"
|
|
325
|
+
@click="openComponentSelector({ callback:(component) => layout.footers.push(component) })">
|
|
326
|
+
{{ $t('Add')}}
|
|
327
|
+
</button>
|
|
328
|
+
</div>
|
|
316
329
|
|
|
317
|
-
<div v-if="expanded['footers']" class="flex flex-col gap-10">
|
|
318
330
|
<TreeView class="mt-2"
|
|
319
|
-
v-model="
|
|
331
|
+
v-model="layout.footers"
|
|
320
332
|
:selected-item="currentItem"
|
|
321
|
-
@add="(items) => openComponentSelector({ items })"
|
|
333
|
+
@add="(items) => openComponentSelector({ callback:(component) => items.push(component) })"
|
|
334
|
+
@duplicate="duplicate"
|
|
335
|
+
@change="pageHistory.commit()">
|
|
322
336
|
<template #default="{ item }">
|
|
323
337
|
<div class="flex-1 text-ellipsis whitespace-nowrap overflow-hidden"
|
|
324
338
|
:class="!item.props.enabled ? 'line-through' : ''"
|
|
@@ -328,160 +342,136 @@
|
|
|
328
342
|
</template>
|
|
329
343
|
</TreeView>
|
|
330
344
|
</div>
|
|
331
|
-
</div>
|
|
332
345
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
@apply="addComponent"
|
|
341
|
-
dismissable="true"
|
|
342
|
-
@dismiss="$refs.webPageComponentSelector.close()" />
|
|
343
|
-
|
|
344
|
-
</div>
|
|
345
|
-
|
|
346
|
-
<div v-else-if="store.tabIndex === 3" class="flex-1 overflow-y-auto p-6" @click="currentArea = 'datasource'">
|
|
347
|
-
|
|
348
|
-
<div class="p-6 flex flex-col gap-2" v-if="Array.isArray(page.datasource) && page.datasource.length > 0">
|
|
349
|
-
<div v-for="(ds, index) in page.datasource"
|
|
350
|
-
class="p-3 border-[1px] border-text-50 rounded-lg flex flex-row items-start gap-2">
|
|
351
|
-
<div class="flex-1 flex flex-col" @click="$refs.webDatasourceSelector.open({ _index:index, ...ds })">
|
|
352
|
-
<label>{{ ds.name }}</label>
|
|
346
|
+
<div>
|
|
347
|
+
<div class="flex flex-row gap-1 items-end cursor-pointer">
|
|
348
|
+
<small class="flex-1 text-text-400 text-overflow-ellipsis">{{ $t('Styles')}}</small>
|
|
349
|
+
<button type="button" class="text-primary text-sm flex flex-row items-center gap-1"
|
|
350
|
+
@click="select('style')">
|
|
351
|
+
{{ $t('Edit Style')}}
|
|
352
|
+
</button>
|
|
353
353
|
</div>
|
|
354
|
-
<button type="button"
|
|
355
|
-
@click="removeDatasource(index)">
|
|
356
|
-
<svg width="14" height="14" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
|
|
357
|
-
</button>
|
|
358
|
-
</div>
|
|
359
|
-
</div>
|
|
360
|
-
<div v-else>
|
|
361
|
-
<div class="p-6 text-center">
|
|
362
|
-
<label class="text-text-400">{{ $t('No Datasource')}}</label>
|
|
363
354
|
</div>
|
|
364
355
|
</div>
|
|
365
356
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
357
|
+
</div>
|
|
358
|
+
|
|
359
|
+
<div v-else-if="store.tabIndex === 7" class="flex-1 flex flex-col">
|
|
360
|
+
<div class="flex flex-row justify-end p-4">
|
|
361
|
+
<button type="button" @click="newChat()">
|
|
362
|
+
<svg width="19" height="19" class="fill-primary hover:fill-primary-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256C397.4 512 512 397.4 512 256S397.4 0 256 0zM352 280H280V352c0 13.2-10.8 24-23.1 24C242.8 376 232 365.2 232 352V280H160C146.8 280 136 269.2 136 256c0-13.2 10.8-24 24-24H232V160c0-13.2 10.8-24 24-24C269.2 136 280 146.8 280 160v72h72C365.2 232 376 242.8 376 256C376 269.2 365.2 280 352 280z"/></svg>
|
|
370
363
|
</button>
|
|
371
364
|
</div>
|
|
365
|
+
<div class="flex-1 overflow-y-auto">
|
|
372
366
|
|
|
373
|
-
|
|
374
|
-
@apply="addDatasource"
|
|
375
|
-
:use-datasource="useDatasource" />
|
|
376
|
-
|
|
377
|
-
</div>
|
|
367
|
+
<div class="flex flex-col gap-4 p-4">
|
|
378
368
|
|
|
379
|
-
|
|
369
|
+
<div v-for="message in chat.messages"
|
|
370
|
+
:class="$style.chat + ' ' + (message.direction === 1 ? $style.chatIn : $style.chatOut)">
|
|
380
371
|
|
|
381
|
-
|
|
382
|
-
@mousedown="(e) => $util.dragResize(e, resize1)"></div>
|
|
372
|
+
<p>{{ message.body }}</p>
|
|
383
373
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
</div>
|
|
395
|
-
</div>
|
|
396
|
-
</template>
|
|
397
|
-
<template v-slot:foot="{ context }">
|
|
398
|
-
<div class="p-5">
|
|
399
|
-
<Button type="button" class="w-[100px]"
|
|
400
|
-
@click="Object.assign(this.page.og, context);$refs.ogModal.close()">
|
|
401
|
-
OK
|
|
402
|
-
</Button>
|
|
403
|
-
</div>
|
|
404
|
-
</template>
|
|
405
|
-
<template #default="{ context }">
|
|
406
|
-
<div class="flex-1 p-5 flex flex-col gap-4">
|
|
407
|
-
<div class="flex flex-row gap-4">
|
|
408
|
-
<div>
|
|
409
|
-
<label class="text-text-400">Type</label>
|
|
410
|
-
<Dropdown v-model="context.type" class="mt-1 w-[120px]">
|
|
411
|
-
<option value="website">Website</option>
|
|
412
|
-
<option value="article">Article</option>
|
|
413
|
-
</Dropdown>
|
|
414
|
-
</div>
|
|
415
|
-
<div class="flex-1">
|
|
416
|
-
<label class="text-text-400">Title</label>
|
|
417
|
-
<Textbox v-model="context.title" class="mt-1" />
|
|
374
|
+
<div v-if="message.direction !== 1" class="flex text-text-300 flex-row items-center gap-2 self-stretch pl-3">
|
|
375
|
+
<small class="text-xs text-text-300">{{ message.llmOutputTokenCount }} token</small>
|
|
376
|
+
•
|
|
377
|
+
<small class="text-xs text-text-300">{{ message.llmEllapsedMs }} ms</small>
|
|
378
|
+
<div class="flex-1"></div>
|
|
379
|
+
<button type="button" class="text-xs group hover:text-primary" v-if="(message.attachments ?? [])[0]" @click="chatSet(message.attachments[0])">
|
|
380
|
+
<svg width="9" height="9" class="inline fill-text-300 group-hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M176 480C148.6 480 128 457.6 128 432v-352c0-25.38 20.4-47.98 48.01-47.98c8.686 0 17.35 2.352 25.02 7.031l288 176C503.3 223.8 512 239.3 512 256s-8.703 32.23-22.97 40.95l-288 176C193.4 477.6 184.7 480 176 480z"/></svg>
|
|
381
|
+
Apply
|
|
382
|
+
</button>
|
|
383
|
+
</div>
|
|
418
384
|
</div>
|
|
419
|
-
</div>
|
|
420
385
|
|
|
421
|
-
<div>
|
|
422
|
-
<label class="text-text-400">Description</label>
|
|
423
|
-
<Textarea v-model="context.description" class="mt-1" rows="3" />
|
|
424
386
|
</div>
|
|
425
387
|
|
|
426
|
-
<
|
|
427
|
-
<label class="text-text-400">Url</label>
|
|
428
|
-
<Textbox v-model="context.url" class="mt-1" />
|
|
429
|
-
</div>
|
|
388
|
+
<pre class="text-xs break-all whitespace-pre-wrap">
|
|
430
389
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
390
|
+
</pre>
|
|
391
|
+
|
|
392
|
+
</div>
|
|
393
|
+
<div class="p-2">
|
|
394
|
+
<div class="flex flex-col gap-2">
|
|
395
|
+
<div class="flex flex-row gap-2 items-start">
|
|
396
|
+
<div class="w-[22px]"></div>
|
|
397
|
+
<div class="flex-1 flex flex-row flex-wrap gap-2">
|
|
398
|
+
<div v-for="(attachment, idx) in chat.attachments">
|
|
399
|
+
<Image :src="attachment.image"
|
|
400
|
+
@click="chat.attachments.splice(idx, 1)"
|
|
401
|
+
class="w-[48px] h-[48px] border-[1px] rounded-lg border-border-200" />
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
405
|
+
|
|
406
|
+
<div class="flex flex-row items-start gap-2">
|
|
407
|
+
<div class="pt-1">
|
|
408
|
+
<Button variant="minimal" class="p-0 mt-1" type="button" @click="$refs.chatFile.click()">
|
|
409
|
+
<svg width="19" height="19" class="fill-primary hover:fill-primary-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256C397.4 512 512 397.4 512 256S397.4 0 256 0zM352 280H280V352c0 13.2-10.8 24-23.1 24C242.8 376 232 365.2 232 352V280H160C146.8 280 136 269.2 136 256c0-13.2 10.8-24 24-24H232V160c0-13.2 10.8-24 24-24C269.2 136 280 146.8 280 160v72h72C365.2 232 376 242.8 376 256C376 269.2 365.2 280 352 280z"/></svg>
|
|
410
|
+
</Button>
|
|
411
|
+
<input type="file" accept="image/*" multiple ref="chatFile" class="hidden" @change="onChatUpload" />
|
|
412
|
+
</div>
|
|
413
|
+
<div class="flex-1">
|
|
414
|
+
<Textarea v-model="chat.input" rows="5" class="max-h-[60vh]">
|
|
415
|
+
<template #end>
|
|
416
|
+
<div class="p-2">
|
|
417
|
+
<Button ref="chatBtn" variant="minimal" class="p-0" type="button" @click="chatApply">
|
|
418
|
+
<svg width="19" height="19" class="fill-primary hover:fill-primary-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM372.5 276.5l-144 88C224.7 366.8 220.3 368 216 368c-13.69 0-24-11.2-24-24V168C192 155.3 202.2 144 216 144c4.344 0 8.678 1.176 12.51 3.516l144 88C379.6 239.9 384 247.6 384 256C384 264.4 379.6 272.1 372.5 276.5z"/></svg>
|
|
419
|
+
</Button>
|
|
420
|
+
</div>
|
|
421
|
+
</template>
|
|
422
|
+
</Textarea>
|
|
423
|
+
</div>
|
|
436
424
|
</div>
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
425
|
+
|
|
426
|
+
<div class="flex flex-row justify-end px-3 gap-2 text-text-300 text-xs">
|
|
427
|
+
<div class="text-text-300">{{ totalChatTokens }} tokens</div>
|
|
428
|
+
•
|
|
429
|
+
<div class="text-text-300">{{ chat.model }}</div>
|
|
441
430
|
</div>
|
|
442
431
|
</div>
|
|
443
432
|
</div>
|
|
444
|
-
</
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
<h3>JSON-LD</h3>
|
|
451
|
-
<div class="absolute top-0 right-0 p-2">
|
|
452
|
-
<button type="button" class="p-2" @click="$refs.ldjsonModal.close()">
|
|
453
|
-
<svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
|
|
454
|
-
<path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
|
|
455
|
-
</svg>
|
|
456
|
-
</button>
|
|
457
|
-
</div>
|
|
458
|
-
</div>
|
|
459
|
-
</template>
|
|
460
|
-
<template #foot="{ context }">
|
|
461
|
-
<div class="p-5">
|
|
462
|
-
<Button type="button" class="w-[100px]"
|
|
463
|
-
@click="saveLdjson(context)">
|
|
464
|
-
Save
|
|
465
|
-
</Button>
|
|
466
|
-
</div>
|
|
467
|
-
</template>
|
|
468
|
-
<template #default="{ context }">
|
|
469
|
-
<div class="flex-1 p-5">
|
|
470
|
-
<Textarea v-model="context.code" rows="10" ></Textarea>
|
|
471
|
-
</div>
|
|
472
|
-
</template>
|
|
473
|
-
</Modal>
|
|
433
|
+
</div>
|
|
434
|
+
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<div :class="$style.resize1"
|
|
438
|
+
@mousedown="(e) => $util.dragResize(e, resize1)"></div>
|
|
474
439
|
|
|
475
440
|
</div>
|
|
476
441
|
|
|
477
|
-
<div class="flex-1
|
|
478
|
-
|
|
479
|
-
<div class="flex flex-row p-2">
|
|
480
|
-
<select
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
442
|
+
<div ref="preview" class="flex-1 relative" :class="previewClass">
|
|
443
|
+
|
|
444
|
+
<div class="flex flex-row gap-4 items-center p-2">
|
|
445
|
+
<select v-model="store.zoomLevel" :class="$style.zoomLevel">
|
|
446
|
+
<optgroup label="Zoom Level">
|
|
447
|
+
<option value="fit">Fit</option>
|
|
448
|
+
<option value="125%">125%</option>
|
|
449
|
+
<option value="100%">100%</option>
|
|
450
|
+
<option value="75%">75%</option>
|
|
451
|
+
<option value="50%">50%</option>
|
|
452
|
+
</optgroup>
|
|
484
453
|
</select>
|
|
454
|
+
|
|
455
|
+
<div class="flex-1"></div>
|
|
456
|
+
|
|
457
|
+
<div class="flex flex-row border-[1px] border-border-200 divide-x divide-border-50" :class="$style.zoomLevel">
|
|
458
|
+
<Radio v-for="_type in viewTypes" :value="_type.value" v-model="store.viewType" :custom="true">
|
|
459
|
+
<template #default="">
|
|
460
|
+
<button v-if="_type.value === ''" type="button" class="w-[30px] flex items-center justify-center">
|
|
461
|
+
<svg width="14" height="14" :class="_type.value === store.viewType ? 'fill-primary' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M320 0H64C37.5 0 16 21.5 16 48v416C16 490.5 37.5 512 64 512h256c26.5 0 48-21.5 48-48v-416C368 21.5 346.5 0 320 0zM240 447.1C240 456.8 232.8 464 224 464H159.1C151.2 464 144 456.8 144 448S151.2 432 160 432h64C232.8 432 240 439.2 240 447.1zM304 384h-224V64h224V384z"/></svg>
|
|
462
|
+
</button>
|
|
463
|
+
<button v-if="_type.value === 'md:'" type="button" class="w-[30px] flex items-center justify-center">
|
|
464
|
+
<svg width="14" height="14" :class="_type.value === store.viewType ? 'fill-primary' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M384 .0001H64c-35.35 0-64 28.65-64 64v384c0 35.35 28.65 63.1 64 63.1h320c35.35 0 64-28.65 64-63.1v-384C448 28.65 419.3 .0001 384 .0001zM288 448c0 8.837-7.163 16-15.1 16H175.1c-8.837 0-15.1-7.163-15.1-16s7.163-16 15.1-16h96C280.8 432 288 439.2 288 448zM384 384H64v-320h320V384z"/></svg>
|
|
465
|
+
</button>
|
|
466
|
+
<button v-if="_type.value === 'xl:'" type="button" class="w-[30px] flex items-center justify-center">
|
|
467
|
+
<svg width="14" height="14" :class="_type.value === store.viewType ? 'fill-primary' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M528 0h-480C21.5 0 0 21.5 0 48v320C0 394.5 21.5 416 48 416h192L224 464H152C138.8 464 128 474.8 128 488S138.8 512 152 512h272c13.25 0 24-10.75 24-24s-10.75-24-24-24H352L336 416h192c26.5 0 48-21.5 48-48v-320C576 21.5 554.5 0 528 0zM512 288H64V64h448V288z"/></svg>
|
|
468
|
+
</button>
|
|
469
|
+
<button v-if="_type.value === '2xl:'" type="button" class="w-[30px] flex items-center justify-center">
|
|
470
|
+
<svg width="14" height="14" :class="_type.value === store.viewType ? 'fill-primary' : 'fill-text'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M512 448H127.1C110.3 448 96 462.3 96 479.1S110.3 512 127.1 512h384C529.7 512 544 497.7 544 480S529.7 448 512 448zM592 0h-544C21.5 0 0 21.5 0 48v320C0 394.5 21.5 416 48 416h544c26.5 0 48-21.5 48-48v-320C640 21.5 618.5 0 592 0zM576 352H64v-288h512V352z"/></svg>
|
|
471
|
+
</button>
|
|
472
|
+
</template>
|
|
473
|
+
</Radio>
|
|
474
|
+
</div>
|
|
485
475
|
</div>
|
|
486
476
|
|
|
487
477
|
<div class="p-6">
|
|
@@ -490,74 +480,97 @@
|
|
|
490
480
|
</div>
|
|
491
481
|
</div>
|
|
492
482
|
|
|
493
|
-
<div v-if="currentItem" class="flex flex-
|
|
494
|
-
|
|
495
|
-
:style="section3Style">
|
|
496
|
-
|
|
497
|
-
<div class="px-6 py-4 flex flex-row items-center gap-2">
|
|
498
|
-
<Textbox v-if="currentItem.type !== 'Style'"
|
|
499
|
-
v-model="currentItem.props.name"
|
|
500
|
-
:placeholder="currentItem.type"
|
|
501
|
-
class="bg-base-500 rounded-full flex-1"
|
|
502
|
-
item-class="p-0 px-2"
|
|
503
|
-
variant="minimal">
|
|
504
|
-
<template #start>
|
|
505
|
-
<div class="pl-3">
|
|
506
|
-
<Switch v-model="currentItem.props.enabled"/>
|
|
507
|
-
</div>
|
|
508
|
-
</template>
|
|
509
|
-
</Textbox>
|
|
483
|
+
<div v-if="currentItem" ref="rightPanel" class="flex flex-row"
|
|
484
|
+
:style="section3Style" @click.meta="log(currentItem)">
|
|
510
485
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
</div>
|
|
514
|
-
</div>
|
|
486
|
+
<div :class="$style.resize3"
|
|
487
|
+
@mousedown="(e) => $util.dragResize(e, resize3)"></div>
|
|
515
488
|
|
|
516
|
-
<div
|
|
517
|
-
|
|
518
|
-
<template #tab="{ item }">
|
|
519
|
-
<div v-if="item.value === ''" class="px-6 p-2 border-[1px] border-b-0 relative top-[1px] rounded-t-md overflow-hidden"
|
|
520
|
-
:class="store.viewType === item.value ? 'bg-base-400 border-text-50' : 'border-transparent'">
|
|
521
|
-
<div v-if="store.viewType === item.value" class="absolute top-0 left-0 right-0 h-[2px] bg-primary"></div>
|
|
522
|
-
Mobile
|
|
523
|
-
</div>
|
|
524
|
-
<div v-else-if="item.value === 'md:'" class="px-6 p-2 border-[1px] border-b-0 relative top-[1px] rounded-t-md overflow-hidden"
|
|
525
|
-
:class="store.viewType === item.value ? 'bg-base-400 border-text-50' : 'border-transparent'">
|
|
526
|
-
<div v-if="store.viewType === item.value" class="absolute top-0 left-0 right-0 h-[2px] bg-primary"></div>
|
|
527
|
-
Tablet
|
|
528
|
-
</div>
|
|
529
|
-
</template>
|
|
530
|
-
</Tabs>
|
|
531
|
-
</div>
|
|
489
|
+
<div class="flex-1 flex flex-col relative"
|
|
490
|
+
ref="rightPane">
|
|
532
491
|
|
|
533
|
-
|
|
492
|
+
<TransitionGroup name="openltr" tag="div" class="flex-1 flex flex-col">
|
|
534
493
|
|
|
535
|
-
|
|
536
|
-
@mousedown="(e) => $util.dragResize(e, resize3)"></div>
|
|
494
|
+
<div v-if="extRightPane === null" class="flex-1 flex flex-col divide-y divide-border-50 overflow-y-auto">
|
|
537
495
|
|
|
538
|
-
|
|
496
|
+
<div v-if="currentItem.type !== 'Style'" class="px-6 py-4 flex flex-row gap-5 items-start">
|
|
497
|
+
<div>
|
|
498
|
+
<small class="text-text-400">Enabled</small>
|
|
499
|
+
<Switch v-model="currentItem.props.enabled"/>
|
|
500
|
+
</div>
|
|
501
|
+
<div v-if="currentItem.type !== 'Style'" class="flex-1">
|
|
502
|
+
<small class="text-text-400">Name</small>
|
|
503
|
+
<Textbox v-model="currentItem.props.name"
|
|
504
|
+
:placeholder="currentItem.type"
|
|
505
|
+
class="bg-base-500 flex-1"
|
|
506
|
+
variant="minimal" />
|
|
507
|
+
</div>
|
|
508
|
+
<div v-else class="px-3">
|
|
509
|
+
<h4>Style</h4>
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
539
512
|
|
|
540
|
-
<div>
|
|
541
513
|
<component :is="`${currentItem.type}Setting`"
|
|
542
514
|
:item="currentItem"
|
|
543
515
|
:view-type="store.viewType"
|
|
516
|
+
:view-index="viewIndex"
|
|
544
517
|
:view-types="viewTypes"
|
|
545
518
|
ref="settingComponent"
|
|
546
519
|
@change="pageHistory.commit()"
|
|
547
520
|
@postMessageToIframe="onPostMessageToIframe"/>
|
|
521
|
+
|
|
522
|
+
<div class="p-6 py-4" v-if="debugMode">
|
|
523
|
+
<small class="text-text-400">Debug ID</small>
|
|
524
|
+
<Textbox v-model="currentItem.props.debugId" maxlength="5" />
|
|
525
|
+
</div>
|
|
526
|
+
|
|
527
|
+
<br />
|
|
528
|
+
<br />
|
|
529
|
+
<br />
|
|
530
|
+
|
|
548
531
|
</div>
|
|
549
532
|
|
|
550
|
-
<div class="
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
533
|
+
<div v-else-if="extRightPane?.type" class="flex-1 flex flex-col divide-y divide-border-50 overflow-y-auto">
|
|
534
|
+
|
|
535
|
+
<div class="px-6 py-4 flex flex-row gap-5 items-center">
|
|
536
|
+
<div class="flex flex-col">
|
|
537
|
+
<small class="text-text-400"> </small>
|
|
538
|
+
<button type="button" @click="extRightPane = null">
|
|
539
|
+
<svg width="14" height="14" class="fill-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M447.1 256C447.1 273.7 433.7 288 416 288H109.3l105.4 105.4c12.5 12.5 12.5 32.75 0 45.25C208.4 444.9 200.2 448 192 448s-16.38-3.125-22.62-9.375l-160-160c-12.5-12.5-12.5-32.75 0-45.25l160-160c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25L109.3 224H416C433.7 224 447.1 238.3 447.1 256z"/></svg>
|
|
540
|
+
</button>
|
|
541
|
+
</div>
|
|
542
|
+
<div>
|
|
543
|
+
<small class="text-text-400">Enabled</small>
|
|
544
|
+
<Switch v-model="extRightPane.props.enabled"/>
|
|
545
|
+
</div>
|
|
546
|
+
<div v-if="extRightPane.type !== 'Style'" class="flex-1">
|
|
547
|
+
<small class="text-text-400">Name</small>
|
|
548
|
+
<Textbox v-model="currentItem.props.name"
|
|
549
|
+
:placeholder="extRightPane.type"
|
|
550
|
+
class="bg-base-500 flex-1"
|
|
551
|
+
variant="minimal" />
|
|
552
|
+
</div>
|
|
553
|
+
<div v-else class="px-3">
|
|
554
|
+
<h4>Style</h4>
|
|
555
|
+
</div>
|
|
556
|
+
</div>
|
|
557
|
+
|
|
558
|
+
<component :is="`${extRightPane.type}Setting`"
|
|
559
|
+
:item="extRightPane"
|
|
560
|
+
:view-type="store.viewType"
|
|
561
|
+
:view-index="viewIndex"
|
|
562
|
+
:view-types="viewTypes"
|
|
563
|
+
ref="settingComponent"
|
|
564
|
+
@change="pageHistory.commit()"
|
|
565
|
+
@postMessageToIframe="onPostMessageToIframe"/>
|
|
566
|
+
|
|
567
|
+
<br />
|
|
568
|
+
<br />
|
|
569
|
+
<br />
|
|
555
570
|
|
|
556
|
-
<WebTemplateCreator :="useTemplateCreator"
|
|
557
|
-
ref="templateCreator"
|
|
558
|
-
@save="templateCreatorAfterSave" />
|
|
559
571
|
</div>
|
|
560
|
-
|
|
572
|
+
|
|
573
|
+
</TransitionGroup>
|
|
561
574
|
|
|
562
575
|
</div>
|
|
563
576
|
|
|
@@ -568,7 +581,44 @@
|
|
|
568
581
|
</div>
|
|
569
582
|
|
|
570
583
|
<div class="absolute">
|
|
571
|
-
<WebLayoutSelector ref="webLayoutSelector"
|
|
584
|
+
<WebLayoutSelector ref="webLayoutSelector" @apply="createLayout"/>
|
|
585
|
+
|
|
586
|
+
<WebComponentSelector ref="webPageComponentSelector"
|
|
587
|
+
:component-src="`${this.controller}.load-templates`"
|
|
588
|
+
:components="availableComponents"
|
|
589
|
+
@apply="addComponent"
|
|
590
|
+
dismissable="true"
|
|
591
|
+
@dismiss="$refs.webPageComponentSelector.close()" />
|
|
592
|
+
|
|
593
|
+
<OGSettingModal ref="ogModal" />
|
|
594
|
+
|
|
595
|
+
<Modal ref="ldjsonModal" width="600" height="480">
|
|
596
|
+
<template v-slot:head>
|
|
597
|
+
<div class="relative p-5">
|
|
598
|
+
<h3>JSON-LD</h3>
|
|
599
|
+
<div class="absolute top-0 right-0 p-2">
|
|
600
|
+
<button type="button" class="p-2" @click="$refs.ldjsonModal.close()">
|
|
601
|
+
<svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
|
|
602
|
+
<path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
|
|
603
|
+
</svg>
|
|
604
|
+
</button>
|
|
605
|
+
</div>
|
|
606
|
+
</div>
|
|
607
|
+
</template>
|
|
608
|
+
<template #foot="{ context }">
|
|
609
|
+
<div class="p-5">
|
|
610
|
+
<Button type="button" class="w-[100px]"
|
|
611
|
+
@click="saveLdjson(context)">
|
|
612
|
+
Save
|
|
613
|
+
</Button>
|
|
614
|
+
</div>
|
|
615
|
+
</template>
|
|
616
|
+
<template #default="{ context }">
|
|
617
|
+
<div class="flex-1 p-5">
|
|
618
|
+
<Textarea v-model="context.code" rows="10" ></Textarea>
|
|
619
|
+
</div>
|
|
620
|
+
</template>
|
|
621
|
+
</Modal>
|
|
572
622
|
</div>
|
|
573
623
|
|
|
574
624
|
</div>
|
|
@@ -578,14 +628,123 @@
|
|
|
578
628
|
|
|
579
629
|
import throttle from "lodash/throttle";
|
|
580
630
|
import md5 from "md5";
|
|
581
|
-
import {
|
|
631
|
+
import {createFormData, invokeAfterIdle} from "../utils/helpers.mjs";
|
|
582
632
|
import {ref} from 'vue'
|
|
583
633
|
import {useManualRefHistory} from "@vueuse/core";
|
|
584
634
|
import axios from "axios";
|
|
585
635
|
import {useRouter} from "vue-router";
|
|
636
|
+
import WebLayoutSelector from "./WebLayoutSelector.vue";
|
|
637
|
+
import WebComponentSelector from "./WebComponentSelector.vue";
|
|
638
|
+
import defaultConfig from "../configs/web-page-builder.js"
|
|
639
|
+
import OGSettingModal from "./OGSettingModal.vue";
|
|
640
|
+
|
|
641
|
+
const patchPageCache = {}
|
|
642
|
+
|
|
643
|
+
const fontFamilies = {
|
|
644
|
+
'"Anton", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Anton&display=swap');`,
|
|
645
|
+
'Dosis, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Dosis:wght@400;700&display=swap');`,
|
|
646
|
+
'Lato, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap');`,
|
|
647
|
+
'Merriweather, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Merriweather:wght@400;700&display=swap');`,
|
|
648
|
+
'Montserrat, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');`,
|
|
649
|
+
'"Noto Sans", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;800&display=swap');`,
|
|
650
|
+
'Oswald, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;700&display=swap');`,
|
|
651
|
+
'Oxygen, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Oxygen:wght@400;700&display=swap');`,
|
|
652
|
+
'Poppins, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');`,
|
|
653
|
+
'Quantico, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Quantico:wght@400;700&display=swap"');`,
|
|
654
|
+
'Raleway, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap');`,
|
|
655
|
+
'"Reddit Sans", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Reddit+Sans:wght@400;700&display=swap');`,
|
|
656
|
+
'"Roboto", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');`,
|
|
657
|
+
'"Roboto Slab", serif': `@import url('https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;800&display=swap');`,
|
|
658
|
+
'Volkhov, serif': `@import url('https://fonts.googleapis.com/css2?family=Volkhov:wght@400;700&display=swap');`,
|
|
659
|
+
'"Work Sans", serif': `@import url('https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;700&display=swap');`,
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const defaultMedia = {
|
|
663
|
+
":root": {
|
|
664
|
+
"--spacing-1": [],
|
|
665
|
+
"--spacing-2": [],
|
|
666
|
+
"--spacing-3": [],
|
|
667
|
+
"--spacing-4": [],
|
|
668
|
+
"--spacing-5": [],
|
|
669
|
+
"--spacing-6": [],
|
|
670
|
+
"--spacing-7": [],
|
|
671
|
+
"--spacing-8": [],
|
|
672
|
+
"--spacing-9": [],
|
|
673
|
+
"--spacing-10": [],
|
|
674
|
+
"--spacing-11": [],
|
|
675
|
+
"--spacing-12": []
|
|
676
|
+
},
|
|
677
|
+
"*": {
|
|
678
|
+
"font-family": [ "Poppins, sans-serif" ]
|
|
679
|
+
},
|
|
680
|
+
"html, .html": {
|
|
681
|
+
"font-size": [],
|
|
682
|
+
"--base-300": [ "rgb(235, 235, 235)" ],
|
|
683
|
+
"--base-400": [ "rgb(245, 245, 245)" ],
|
|
684
|
+
"--base-500": [ "rgb(255, 255, 255)" ],
|
|
685
|
+
"--primary-100": [],
|
|
686
|
+
"--primary-200": [],
|
|
687
|
+
"--primary-300": [],
|
|
688
|
+
"--primary-400": [],
|
|
689
|
+
"--primary-500": [ "rgb(0, 0, 0)" ],
|
|
690
|
+
"--primary-600": [ "rgb(15, 15, 15)" ],
|
|
691
|
+
"--primary-700": [],
|
|
692
|
+
"--primary-800": [],
|
|
693
|
+
"--primary-900": [],
|
|
694
|
+
"--secondary-100": [],
|
|
695
|
+
"--secondary-200": [],
|
|
696
|
+
"--secondary-300": [],
|
|
697
|
+
"--secondary-400": [],
|
|
698
|
+
"--secondary-500": [],
|
|
699
|
+
"--secondary-600": [],
|
|
700
|
+
"--secondary-700": [],
|
|
701
|
+
"--secondary-800": [],
|
|
702
|
+
"--secondary-900": [],
|
|
703
|
+
"--text-100": [],
|
|
704
|
+
"--text-200": [],
|
|
705
|
+
"--text-300": [],
|
|
706
|
+
"--text-400": [],
|
|
707
|
+
"--text-500": [ "rgb(33, 33, 33)" ],
|
|
708
|
+
"--text-600": [],
|
|
709
|
+
"--text-700": [],
|
|
710
|
+
"--text-800": [],
|
|
711
|
+
"--text-900": []
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
function collectFontImports(styles) {
|
|
716
|
+
const usedFonts = new Set()
|
|
717
|
+
const media = styles?.media || {}
|
|
718
|
+
|
|
719
|
+
for (const selector in media) {
|
|
720
|
+
const rules = media[selector]
|
|
721
|
+
if (!rules || !rules['font-family']) continue
|
|
722
|
+
|
|
723
|
+
const values = rules['font-family']
|
|
724
|
+
if (!Array.isArray(values)) continue
|
|
725
|
+
|
|
726
|
+
for (const val of values) {
|
|
727
|
+
if (!val) continue
|
|
728
|
+
if (fontFamilies[val]) {
|
|
729
|
+
usedFonts.add(val)
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
return Array.from(usedFonts)
|
|
735
|
+
.map(font => fontFamilies[font])
|
|
736
|
+
.join('\n')
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function indent(str, spaces = 2) {
|
|
740
|
+
const pad = ' '.repeat(spaces)
|
|
741
|
+
return str.split('\n').map(line => pad + line).join('\n')
|
|
742
|
+
}
|
|
586
743
|
|
|
587
744
|
export default{
|
|
588
745
|
|
|
746
|
+
components: {OGSettingModal, WebComponentSelector, WebLayoutSelector},
|
|
747
|
+
|
|
589
748
|
setup(){
|
|
590
749
|
const page = ref({})
|
|
591
750
|
const pageHistory = useManualRefHistory(page, { clone:true })
|
|
@@ -598,78 +757,34 @@ export default{
|
|
|
598
757
|
|
|
599
758
|
props: {
|
|
600
759
|
|
|
601
|
-
/**
|
|
602
|
-
* Can add/remove layout
|
|
603
|
-
*/
|
|
604
760
|
canManageLayout: {
|
|
605
761
|
type: Boolean,
|
|
606
762
|
default: false
|
|
607
763
|
},
|
|
608
764
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
* @param {Array} components
|
|
612
|
-
* @param {String} components[]
|
|
613
|
-
*/
|
|
765
|
+
controller: String,
|
|
766
|
+
|
|
614
767
|
excludeComponents: {
|
|
615
768
|
type: Array,
|
|
616
769
|
default: []
|
|
617
770
|
},
|
|
618
771
|
|
|
619
|
-
/**
|
|
620
|
-
* Add more components
|
|
621
|
-
* @param {Array} components
|
|
622
|
-
* @param {String} components[]
|
|
623
|
-
*/
|
|
624
772
|
moreComponents: {
|
|
625
773
|
type: Array,
|
|
626
774
|
default: []
|
|
627
775
|
},
|
|
628
776
|
|
|
629
|
-
/**
|
|
630
|
-
* Persist web page builder state
|
|
631
|
-
*/
|
|
632
|
-
store: {
|
|
633
|
-
type: Object,
|
|
634
|
-
default: {
|
|
635
|
-
version: '0.0.999',
|
|
636
|
-
layoutMode: false,
|
|
637
|
-
selectedComponent: null, // [ 'uid|style', 'style|headers|components|footers' ]
|
|
638
|
-
tabIndex: 2,
|
|
639
|
-
viewType: '',
|
|
640
|
-
zoomLevel: 'fit',
|
|
641
|
-
width: [ 320, 320 ]
|
|
642
|
-
}
|
|
643
|
-
},
|
|
644
|
-
|
|
645
|
-
src:{
|
|
646
|
-
type: [ String, Array ],
|
|
647
|
-
default: 'page.open'
|
|
648
|
-
},
|
|
649
|
-
|
|
650
|
-
saveSrc:{
|
|
651
|
-
type: [ String, Array ],
|
|
652
|
-
default: 'page.save'
|
|
653
|
-
},
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
* @param {Object} config
|
|
657
|
-
* @param {String} config.method
|
|
658
|
-
* @param {String} config.url
|
|
659
|
-
*/
|
|
660
777
|
uploadConfig: {
|
|
661
|
-
type: Object
|
|
662
|
-
required: true
|
|
778
|
+
type: Object
|
|
663
779
|
},
|
|
664
780
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
* @param {Object} config
|
|
668
|
-
* @param {String} config.url
|
|
669
|
-
*/
|
|
781
|
+
uploadImageFn: Function,
|
|
782
|
+
|
|
670
783
|
useDatasource: undefined,
|
|
671
784
|
|
|
672
|
-
useTemplateCreator: undefined
|
|
785
|
+
useTemplateCreator: undefined,
|
|
786
|
+
|
|
787
|
+
presetKey: String
|
|
673
788
|
|
|
674
789
|
},
|
|
675
790
|
|
|
@@ -708,27 +823,6 @@ export default{
|
|
|
708
823
|
this.loadDatasource()
|
|
709
824
|
},
|
|
710
825
|
|
|
711
|
-
cleanItem(item){
|
|
712
|
-
|
|
713
|
-
delete item.uid
|
|
714
|
-
delete item.enabled
|
|
715
|
-
|
|
716
|
-
if(item.props){
|
|
717
|
-
for(let key in item.props){
|
|
718
|
-
if(Array.isArray(item.props[key]) &&
|
|
719
|
-
(item.props[key].length === 0 || [ '[{},{}]', '[]', '["",""]', '[""]' ].includes(JSON.stringify(item.props[key])))){
|
|
720
|
-
delete item.props[key]
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
if(Array.isArray(item.items)){
|
|
726
|
-
for(let i in item.items){
|
|
727
|
-
this.cleanItem(item.items[i])
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
},
|
|
731
|
-
|
|
732
826
|
close(){
|
|
733
827
|
this.$emit('close')
|
|
734
828
|
},
|
|
@@ -760,7 +854,13 @@ export default{
|
|
|
760
854
|
return Array.isArray(component.props[key]) ? component.props[key].join(' ') : ''
|
|
761
855
|
})
|
|
762
856
|
.filter(_ => _)
|
|
763
|
-
.join(' ')
|
|
857
|
+
.join(' '),
|
|
858
|
+
|
|
859
|
+
style: this.styleClasses.reduce((res, cur) => {
|
|
860
|
+
if(Array.isArray(component.props[cur]))
|
|
861
|
+
res[cur] = component.props[cur]
|
|
862
|
+
return res
|
|
863
|
+
}, {})
|
|
764
864
|
}
|
|
765
865
|
|
|
766
866
|
for(let key in component.props){
|
|
@@ -779,44 +879,136 @@ export default{
|
|
|
779
879
|
}
|
|
780
880
|
})
|
|
781
881
|
|
|
782
|
-
if(Array.isArray(component.items)){
|
|
783
|
-
instance.items = component.items.map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
882
|
+
if(Array.isArray(component.items)){
|
|
883
|
+
instance.items = component.items.map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if(Array.isArray(component.items2)){
|
|
887
|
+
instance.items2 = component.items2.map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if(Array.isArray(component.items3)){
|
|
891
|
+
instance.items3 = component.items3.map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if(component.props && Array.isArray(component.props.items)){
|
|
895
|
+
instance.items = component.props.items
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
if(component.slots){
|
|
899
|
+
const slots = {}
|
|
900
|
+
for(let key in component.slots){
|
|
901
|
+
slots[key] = component.slots[key].map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
902
|
+
}
|
|
903
|
+
instance.slots = slots
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
return instance
|
|
907
|
+
},
|
|
908
|
+
|
|
909
|
+
createLayout(layout){
|
|
910
|
+
this.useSocket().send(`${this.controller}.create-layout`, layout)
|
|
911
|
+
.then(layout => {
|
|
912
|
+
this.loadLayouts()
|
|
913
|
+
this.page.layoutId = layout.id
|
|
914
|
+
this.$refs.webLayoutSelector.close()
|
|
915
|
+
})
|
|
916
|
+
.catch(err => this.alert(err))
|
|
917
|
+
},
|
|
918
|
+
|
|
919
|
+
createStyleSheet(styles, breakpoints = {
|
|
920
|
+
md: '768px',
|
|
921
|
+
lg: '1024px',
|
|
922
|
+
xl: '1280px'
|
|
923
|
+
}){
|
|
924
|
+
const mediaBuckets = {
|
|
925
|
+
base: [],
|
|
926
|
+
md: [],
|
|
927
|
+
lg: [],
|
|
928
|
+
xl: []
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const media = styles?.media || {}
|
|
932
|
+
|
|
933
|
+
for (const selector in media) {
|
|
934
|
+
const rules = media[selector]
|
|
935
|
+
if (!rules || Object.keys(rules).length === 0) continue
|
|
936
|
+
|
|
937
|
+
const ruleSets = {
|
|
938
|
+
base: [],
|
|
939
|
+
md: [],
|
|
940
|
+
lg: [],
|
|
941
|
+
xl: []
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
for (const prop in rules) {
|
|
945
|
+
const values = rules[prop]
|
|
946
|
+
if (!Array.isArray(values)) continue
|
|
947
|
+
|
|
948
|
+
if (values[0] !== undefined) ruleSets.base.push(`${prop}: ${values[0]};`)
|
|
949
|
+
if (values[1] !== undefined) ruleSets.md.push(`${prop}: ${values[1]};`)
|
|
950
|
+
if (values[2] !== undefined) ruleSets.lg.push(`${prop}: ${values[2]};`)
|
|
951
|
+
if (values[3] !== undefined) ruleSets.xl.push(`${prop}: ${values[3]};`)
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
for (const size in ruleSets) {
|
|
955
|
+
if (ruleSets[size].length === 0) continue
|
|
956
|
+
mediaBuckets[size].push(
|
|
957
|
+
`${selector} {\n ${ruleSets[size].join('\n ')}\n}`
|
|
958
|
+
)
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
let css = ''
|
|
963
|
+
|
|
964
|
+
const fontImports = collectFontImports(styles, fontFamilies)
|
|
965
|
+
if (fontImports) {
|
|
966
|
+
css += fontImports + '\n\n'
|
|
784
967
|
}
|
|
785
968
|
|
|
786
|
-
|
|
787
|
-
|
|
969
|
+
const mediaImports = styles?.imports || []
|
|
970
|
+
if (Array.isArray(mediaImports)) {
|
|
971
|
+
css += mediaImports.join('\n') + '\n\n'
|
|
788
972
|
}
|
|
789
973
|
|
|
790
|
-
|
|
791
|
-
|
|
974
|
+
if (mediaBuckets.base.length) {
|
|
975
|
+
css += mediaBuckets.base.join('\n\n') + '\n\n'
|
|
976
|
+
}
|
|
792
977
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
978
|
+
if (mediaBuckets.md.length) {
|
|
979
|
+
css += `@media (min-width: ${breakpoints.md}) {\n${indent(mediaBuckets.md.join('\n\n'))}\n}\n\n`
|
|
980
|
+
}
|
|
796
981
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
982
|
+
if (mediaBuckets.lg.length) {
|
|
983
|
+
css += `@media (min-width: ${breakpoints.lg}) {\n${indent(mediaBuckets.lg.join('\n\n'))}\n}\n\n`
|
|
984
|
+
}
|
|
800
985
|
|
|
801
|
-
|
|
802
|
-
|
|
986
|
+
if (mediaBuckets.xl.length) {
|
|
987
|
+
css += `@media (min-width: ${breakpoints.xl}) {\n${indent(mediaBuckets.xl.join('\n\n'))}\n}\n\n`
|
|
988
|
+
}
|
|
803
989
|
|
|
804
|
-
|
|
805
|
-
.then(() => this.toast('Copied to clipboard'))
|
|
990
|
+
return css.trim()
|
|
806
991
|
},
|
|
807
992
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
993
|
+
createInstances(){
|
|
994
|
+
if(!this.page.instances || typeof this.page.instances !== 'object' || Array.isArray(this.page.instances))
|
|
995
|
+
this.page.instances = {}
|
|
996
|
+
this.page.instances.components = (this.page.components ?? []).map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
997
|
+
|
|
998
|
+
if(this.layout){
|
|
999
|
+
if(!this.layout.instances || typeof this.layout.instances !== 'object' || Array.isArray(this.layout.instances))
|
|
1000
|
+
this.layout.instances = {}
|
|
1001
|
+
this.layout.instances.headers = (this.layout.headers ?? []).map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
1002
|
+
this.layout.instances.footers = (this.layout.footers ?? []).map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
811
1003
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
})
|
|
1004
|
+
this.layout.instances.stylesheet = this.createStyleSheet(this.layout.styles)
|
|
1005
|
+
}
|
|
815
1006
|
},
|
|
816
1007
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
this
|
|
1008
|
+
duplicate(parent, item){
|
|
1009
|
+
const newItem = JSON.parse(JSON.stringify(item))
|
|
1010
|
+
this.setUid(newItem)
|
|
1011
|
+
parent.push(newItem)
|
|
820
1012
|
},
|
|
821
1013
|
|
|
822
1014
|
findCompByUid(uid, components){
|
|
@@ -893,7 +1085,7 @@ export default{
|
|
|
893
1085
|
},
|
|
894
1086
|
|
|
895
1087
|
listen(){
|
|
896
|
-
this.
|
|
1088
|
+
this.useSocket().send(`${this.controller}.subscribe`, { name:'page' })
|
|
897
1089
|
.then(() => {
|
|
898
1090
|
|
|
899
1091
|
})
|
|
@@ -901,11 +1093,16 @@ export default{
|
|
|
901
1093
|
},
|
|
902
1094
|
|
|
903
1095
|
async load(){
|
|
904
|
-
return this.
|
|
905
|
-
.then(({ page,
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
1096
|
+
return this.useSocket().send(`${this.controller}.open`, { uid:this.$route.params.uid })
|
|
1097
|
+
.then(({ page, previewHost, debugMode, useChat }) => {
|
|
1098
|
+
|
|
1099
|
+
this.patchPage(page)
|
|
1100
|
+
|
|
1101
|
+
if(page) Object.assign(this.page, page)
|
|
1102
|
+
this.debugMode = debugMode ?? this.debugMode
|
|
1103
|
+
if(previewHost) this.previewHost = previewHost
|
|
1104
|
+
|
|
1105
|
+
this.useChat = useChat ?? this.useChat
|
|
909
1106
|
|
|
910
1107
|
this.prevData = {
|
|
911
1108
|
page: JSON.stringify(this.page),
|
|
@@ -916,25 +1113,117 @@ export default{
|
|
|
916
1113
|
|
|
917
1114
|
this.$nextTick(() => {
|
|
918
1115
|
this.resize()
|
|
919
|
-
this.iframeSrc = (this.host ?? import.meta.env.VITE_WEB_HOST) + '/' + (this.page.path ?? '') +
|
|
920
|
-
`?edit-mode=${this.store.previewMode}`
|
|
921
|
-
window.setTimeout(() => {
|
|
922
|
-
this.updateIframe()
|
|
923
|
-
}, 500)
|
|
924
|
-
})
|
|
925
1116
|
|
|
926
|
-
|
|
1117
|
+
this.iframeSrc = this.previewHost + `?edit-mode=${this.store.previewMode}`
|
|
1118
|
+
})
|
|
927
1119
|
|
|
1120
|
+
this.readyState = 1
|
|
928
1121
|
})
|
|
929
1122
|
.catch((err) => {
|
|
930
1123
|
this.toast(err)
|
|
931
|
-
this
|
|
1124
|
+
this.readyState = -1
|
|
1125
|
+
console.error(err)
|
|
1126
|
+
})
|
|
1127
|
+
},
|
|
1128
|
+
|
|
1129
|
+
patchBgColors(bgColors){
|
|
1130
|
+
if (!Array.isArray(bgColors)) return
|
|
1131
|
+
|
|
1132
|
+
for(let i = 0 ; i < bgColors.length ; i++){
|
|
1133
|
+
let value = bgColors[i]
|
|
1134
|
+
if(`${bgColors[i]}`.startsWith('bg-')){
|
|
1135
|
+
if(patchPageCache[bgColors[i]]){
|
|
1136
|
+
value = patchPageCache[bgColors[i]]
|
|
1137
|
+
}
|
|
1138
|
+
else{
|
|
1139
|
+
const el = document.createElement('div')
|
|
1140
|
+
el.classList.add(bgColors[i])
|
|
1141
|
+
el.style.position = 'fixed'
|
|
1142
|
+
el.style.top = '-100000px'
|
|
1143
|
+
document.body.appendChild(el)
|
|
1144
|
+
|
|
1145
|
+
const rgbText = window.getComputedStyle(el)['background-color']
|
|
1146
|
+
|
|
1147
|
+
const rgb = rgbText.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*\d+)?\)/)
|
|
1148
|
+
if(rgb){
|
|
1149
|
+
value = `#${((1 << 24) + (parseInt(rgb[1]) << 16) +
|
|
1150
|
+
(parseInt(rgb[2]) << 8) +
|
|
1151
|
+
parseInt(rgb[3])).toString(16).slice(1)}`
|
|
1152
|
+
}
|
|
1153
|
+
document.body.removeChild(el)
|
|
1154
|
+
|
|
1155
|
+
patchPageCache[bgColors[i]] = value
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
bgColors[i] = value
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1162
|
+
|
|
1163
|
+
patchBdColor(bdColor){
|
|
1164
|
+
if (!Array.isArray(bdColor)) return
|
|
1165
|
+
|
|
1166
|
+
for(let i = 0 ; i < bdColor.length ; i++){
|
|
1167
|
+
let value = bdColor[i]
|
|
1168
|
+
if(`${bdColor[i]}`.startsWith('border-')){
|
|
1169
|
+
if(patchPageCache[bdColor[i]]){
|
|
1170
|
+
value = patchPageCache[bdColor[i]]
|
|
1171
|
+
}
|
|
1172
|
+
else{
|
|
1173
|
+
const el = document.createElement('div')
|
|
1174
|
+
el.classList.add(bdColor[i])
|
|
1175
|
+
el.style.position = 'fixed'
|
|
1176
|
+
el.style.borderStyle = "solid"
|
|
1177
|
+
el.style.borderWidth = "5px"
|
|
1178
|
+
el.style.width = '100px'
|
|
1179
|
+
el.style.height = '100px'
|
|
1180
|
+
el.style.top = '10px'
|
|
1181
|
+
el.style.left = '10px'
|
|
1182
|
+
document.body.appendChild(el)
|
|
1183
|
+
|
|
1184
|
+
const rgbText = window.getComputedStyle(el)['border-color']
|
|
1185
|
+
const rgb = rgbText.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*\d+)?\)/)
|
|
1186
|
+
if(rgb){
|
|
1187
|
+
value = `#${((1 << 24) + (parseInt(rgb[1]) << 16) +
|
|
1188
|
+
(parseInt(rgb[2]) << 8) +
|
|
1189
|
+
parseInt(rgb[3])).toString(16).slice(1)}`
|
|
1190
|
+
}
|
|
1191
|
+
document.body.removeChild(el)
|
|
1192
|
+
|
|
1193
|
+
patchPageCache[bdColor[i]] = value
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
bdColor[i] = value
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
},
|
|
1200
|
+
|
|
1201
|
+
patchPage(page){
|
|
1202
|
+
|
|
1203
|
+
const recursePatch = (components) => {
|
|
1204
|
+
for(let component of components){
|
|
1205
|
+
this.patchBgColors(component.props.bgColors)
|
|
1206
|
+
this.patchBdColor(component.props.bdColor)
|
|
1207
|
+
|
|
1208
|
+
if(Array.isArray(component.items)){
|
|
1209
|
+
recursePatch(component.items)
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
recursePatch(page.components)
|
|
1215
|
+
},
|
|
1216
|
+
|
|
1217
|
+
async loadLayouts(){
|
|
1218
|
+
this.useSocket().send(`${this.controller}.load-layouts`, {})
|
|
1219
|
+
.then(_ => {
|
|
1220
|
+
this.layouts = _
|
|
932
1221
|
})
|
|
933
1222
|
},
|
|
934
1223
|
|
|
935
1224
|
loadDatasource(){
|
|
936
1225
|
if(this.useDatasource && this.useDatasource[1]){
|
|
937
|
-
this.
|
|
1226
|
+
this.useSocket().send(this.useDatasource[1], this.page.datasource)
|
|
938
1227
|
.then((data) => {
|
|
939
1228
|
Object.assign(this.page, { data })
|
|
940
1229
|
this.updateIframe()
|
|
@@ -942,32 +1231,40 @@ export default{
|
|
|
942
1231
|
}
|
|
943
1232
|
},
|
|
944
1233
|
|
|
945
|
-
|
|
946
|
-
this.$
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1234
|
+
loadPreset(){
|
|
1235
|
+
if(!Object.keys(this.$route.query).map(_ => _.toLowerCase()).includes('reset')){
|
|
1236
|
+
if(this.presetKey){
|
|
1237
|
+
return this.useSocket().send(this.presetSrc, { key:this.presetKey })
|
|
1238
|
+
.then(config => {
|
|
1239
|
+
if(config){
|
|
1240
|
+
Object.assign(this.config.params, config.params)
|
|
952
1241
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1242
|
+
if(this.$route.query?.search)
|
|
1243
|
+
this.preset.search = this.$route.query.search
|
|
1244
|
+
}
|
|
1245
|
+
})
|
|
1246
|
+
}
|
|
1247
|
+
return new Promise(resolve => resolve())
|
|
1248
|
+
}
|
|
1249
|
+
else{
|
|
1250
|
+
return new Promise((resolve) => {
|
|
1251
|
+
const query = {}
|
|
1252
|
+
for(let key in this.$route.query){
|
|
1253
|
+
if(key.toLowerCase() !== 'reset')
|
|
1254
|
+
query[key] = this.$route.query[key]
|
|
1255
|
+
}
|
|
1256
|
+
this.$router.replace({
|
|
1257
|
+
...this.$route,
|
|
1258
|
+
query
|
|
958
1259
|
})
|
|
959
|
-
this.setUid(item)
|
|
960
1260
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1261
|
+
resolve()
|
|
1262
|
+
})
|
|
1263
|
+
}
|
|
1264
|
+
},
|
|
964
1265
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
catch(e){
|
|
968
|
-
console.error(e)
|
|
969
|
-
}
|
|
970
|
-
})
|
|
1266
|
+
openComponentSelector(params, callback){
|
|
1267
|
+
this.$refs.webPageComponentSelector.open(params, callback)
|
|
971
1268
|
},
|
|
972
1269
|
|
|
973
1270
|
onHooks(model, event, items){
|
|
@@ -983,25 +1280,19 @@ export default{
|
|
|
983
1280
|
|
|
984
1281
|
onKeyDown(e){
|
|
985
1282
|
|
|
986
|
-
if(e.
|
|
987
|
-
this.copy()
|
|
988
|
-
}
|
|
989
|
-
else if(e.keyCode === 86 && (e.metaKey || e.ctrlKey)){
|
|
990
|
-
this.paste(e)
|
|
991
|
-
}
|
|
992
|
-
else if(e.altKey){
|
|
1283
|
+
if(e.altKey){
|
|
993
1284
|
if([ 49, 50, 51, 52 ].includes(e.keyCode)){
|
|
994
1285
|
if(e.keyCode === 49){
|
|
995
|
-
this.store.
|
|
1286
|
+
this.store.viewType = ''
|
|
996
1287
|
}
|
|
997
1288
|
else if(e.keyCode === 50){
|
|
998
|
-
this.store.
|
|
1289
|
+
this.store.viewType = 'md:'
|
|
999
1290
|
}
|
|
1000
1291
|
else if(e.keyCode === 51){
|
|
1001
|
-
this.store.
|
|
1292
|
+
this.store.viewType = 'xl:'
|
|
1002
1293
|
}
|
|
1003
1294
|
else if(e.keyCode === 52){
|
|
1004
|
-
this.store.
|
|
1295
|
+
this.store.viewType = '2xl:'
|
|
1005
1296
|
}
|
|
1006
1297
|
this.resize()
|
|
1007
1298
|
}
|
|
@@ -1049,11 +1340,26 @@ export default{
|
|
|
1049
1340
|
break
|
|
1050
1341
|
|
|
1051
1342
|
case 'component-click':
|
|
1052
|
-
|
|
1053
|
-
if(
|
|
1343
|
+
let component = this.findCompByUid(uid, this.page.components)
|
|
1344
|
+
if(component){
|
|
1345
|
+
this.store.tabIndex = 2
|
|
1346
|
+
this.store.selectedComponent = [ uid ]
|
|
1347
|
+
return
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
component = this.findCompByUid(uid, this.layout.headers)
|
|
1351
|
+
if(!component)
|
|
1352
|
+
component = this.findCompByUid(uid, this.layout.footers)
|
|
1353
|
+
if(component){
|
|
1354
|
+
this.store.tabIndex = 4
|
|
1054
1355
|
this.store.selectedComponent = [ uid ]
|
|
1356
|
+
return
|
|
1055
1357
|
}
|
|
1056
1358
|
break
|
|
1359
|
+
|
|
1360
|
+
case 'mounted':
|
|
1361
|
+
this.updateIframe()
|
|
1362
|
+
break
|
|
1057
1363
|
}
|
|
1058
1364
|
},
|
|
1059
1365
|
|
|
@@ -1072,6 +1378,10 @@ export default{
|
|
|
1072
1378
|
}
|
|
1073
1379
|
},
|
|
1074
1380
|
|
|
1381
|
+
openRightPane2(component){
|
|
1382
|
+
this.extRightPane = component
|
|
1383
|
+
},
|
|
1384
|
+
|
|
1075
1385
|
postIframe(data){
|
|
1076
1386
|
return new Promise((resolve, reject) => {
|
|
1077
1387
|
const handleResponse = (e) => {
|
|
@@ -1115,7 +1425,7 @@ export default{
|
|
|
1115
1425
|
|
|
1116
1426
|
resize(){
|
|
1117
1427
|
|
|
1118
|
-
const transformOrigin = this.
|
|
1428
|
+
const transformOrigin = this.store.viewType === '' ? 'center top' : '0 0'
|
|
1119
1429
|
|
|
1120
1430
|
switch(this.store.zoomLevel){
|
|
1121
1431
|
|
|
@@ -1125,7 +1435,7 @@ export default{
|
|
|
1125
1435
|
const previewHeight = this.$refs.preview.clientHeight - 70
|
|
1126
1436
|
|
|
1127
1437
|
let scale = 1
|
|
1128
|
-
switch(this.
|
|
1438
|
+
switch(this.store.viewType){
|
|
1129
1439
|
|
|
1130
1440
|
case 'md:':
|
|
1131
1441
|
scale = (previewWidth / 1024).toFixed(2)
|
|
@@ -1209,80 +1519,16 @@ export default{
|
|
|
1209
1519
|
},
|
|
1210
1520
|
|
|
1211
1521
|
resize3(w){
|
|
1212
|
-
if(this.store.width[1] - w >= 270){
|
|
1522
|
+
if(this.store.width[1] - w >= 270 && this.store.width[1] - w <= 480){
|
|
1213
1523
|
this.store.width[1] -= w
|
|
1214
1524
|
}
|
|
1215
1525
|
},
|
|
1216
1526
|
|
|
1217
|
-
createStyleSheet(styles){
|
|
1218
|
-
|
|
1219
|
-
const mediaQueries = {
|
|
1220
|
-
'': '@media screen',
|
|
1221
|
-
'md:': '@media screen and (min-width: 640px)',
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
const fontFamilies = {
|
|
1225
|
-
'"Anton", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Anton&display=swap');`,
|
|
1226
|
-
'Dosis, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Dosis:wght@400;700&display=swap');`,
|
|
1227
|
-
'Lato, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap');`,
|
|
1228
|
-
'Merriweather, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Merriweather:wght@400;700&display=swap');`,
|
|
1229
|
-
'Montserrat, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');`,
|
|
1230
|
-
'"Noto Sans", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;800&display=swap');`,
|
|
1231
|
-
'Oswald, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;700&display=swap');`,
|
|
1232
|
-
'Poppins, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap');`,
|
|
1233
|
-
'Raleway, sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap');`,
|
|
1234
|
-
'"Roboto", sans-serif': `@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');`,
|
|
1235
|
-
'"Roboto Slab", serif': `@import url('https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;800&display=swap');`,
|
|
1236
|
-
'"Work Sans", serif': `@import url('https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;700&display=swap');`,
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
let text = ''
|
|
1240
|
-
const usedFonts = {}
|
|
1241
|
-
for(let mediaKey in styles.media){
|
|
1242
|
-
const css = styles.media[mediaKey]
|
|
1243
|
-
|
|
1244
|
-
text += mediaQueries[mediaKey] + '{ '
|
|
1245
|
-
for(let key in css){
|
|
1246
|
-
text += key + '{ '
|
|
1247
|
-
for(let selector in css[key]){
|
|
1248
|
-
text += selector + ':' + css[key][selector] + ';'
|
|
1249
|
-
|
|
1250
|
-
if(selector === 'font-family' && fontFamilies[css[key][selector]]){
|
|
1251
|
-
usedFonts[css[key][selector]] = fontFamilies[css[key][selector]]
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
text += '}'
|
|
1255
|
-
}
|
|
1256
|
-
text += '}\n'
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
return [
|
|
1260
|
-
...Object.values(usedFonts),
|
|
1261
|
-
text
|
|
1262
|
-
]
|
|
1263
|
-
.join("\n")
|
|
1264
|
-
},
|
|
1265
|
-
|
|
1266
|
-
createInstances(){
|
|
1267
|
-
if(!this.page.instances || typeof this.page.instances !== 'object' || Array.isArray(this.page.instances))
|
|
1268
|
-
this.page.instances = {}
|
|
1269
|
-
this.page.instances.components = (this.page.components ?? []).map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
1270
|
-
|
|
1271
|
-
if(this.layout){
|
|
1272
|
-
if(!this.layout.instances || typeof this.layout.instances !== 'object' || Array.isArray(this.layout.instances))
|
|
1273
|
-
this.layout.instances = {}
|
|
1274
|
-
this.layout.instances.headers = (this.layout.headers ?? []).map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
1275
|
-
this.layout.instances.footers = (this.layout.footers ?? []).map((_) => this.createComponentInstance(_)).filter(_=>_)
|
|
1276
|
-
|
|
1277
|
-
this.layout.instances.stylesheet = this.createStyleSheet(this.layout.styles)
|
|
1278
|
-
}
|
|
1279
|
-
},
|
|
1280
|
-
|
|
1281
1527
|
save(){
|
|
1282
1528
|
this.createInstances()
|
|
1283
1529
|
|
|
1284
1530
|
this.$refs.saveBtn.setState(2)
|
|
1285
|
-
this.
|
|
1531
|
+
this.useSocket().send(`${this.controller}.save`, { ...this.page, layout:this.layout })
|
|
1286
1532
|
.then((_) => {
|
|
1287
1533
|
this.prevData = {
|
|
1288
1534
|
page: JSON.stringify(this.page),
|
|
@@ -1290,8 +1536,8 @@ export default{
|
|
|
1290
1536
|
}
|
|
1291
1537
|
})
|
|
1292
1538
|
.catch((err) => {
|
|
1539
|
+
console.log('ERR', err)
|
|
1293
1540
|
this.toast(err)
|
|
1294
|
-
this.load()
|
|
1295
1541
|
})
|
|
1296
1542
|
.finally(_ => this.$refs.saveBtn.resetState())
|
|
1297
1543
|
},
|
|
@@ -1312,8 +1558,16 @@ export default{
|
|
|
1312
1558
|
this.$refs.ldjsonModal.close()
|
|
1313
1559
|
},
|
|
1314
1560
|
|
|
1561
|
+
savePreset: invokeAfterIdle(function() {
|
|
1562
|
+
if(this.presetKey) {
|
|
1563
|
+
this.useSocket().send(this.presetSrc,
|
|
1564
|
+
{key: this.presetKey, config: this.config})
|
|
1565
|
+
}
|
|
1566
|
+
}),
|
|
1567
|
+
|
|
1315
1568
|
select(uid){
|
|
1316
1569
|
this.store.selectedComponent = [ uid ]
|
|
1570
|
+
this.extRightPane = null
|
|
1317
1571
|
|
|
1318
1572
|
this.$refs.iframe.contentWindow.postMessage({
|
|
1319
1573
|
action: 'select',
|
|
@@ -1332,10 +1586,7 @@ export default{
|
|
|
1332
1586
|
},
|
|
1333
1587
|
|
|
1334
1588
|
stopListen(){
|
|
1335
|
-
this.
|
|
1336
|
-
.then(() => {
|
|
1337
|
-
|
|
1338
|
-
})
|
|
1589
|
+
this.useSocket().send(`${this.controller}.unsubscribe`, { name:'page' })
|
|
1339
1590
|
.catch((err) => this.toast(err))
|
|
1340
1591
|
},
|
|
1341
1592
|
|
|
@@ -1375,37 +1626,136 @@ export default{
|
|
|
1375
1626
|
|
|
1376
1627
|
async uploadImage(image, extra = {}, opt = {}){
|
|
1377
1628
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1629
|
+
if(typeof this.uploadImageFn === 'function'){
|
|
1630
|
+
return this.uploadImageFn(image, extra, opt)
|
|
1631
|
+
}
|
|
1632
|
+
else if(this.uploadConfig?.method){
|
|
1633
|
+
return axios({
|
|
1634
|
+
method: this.uploadConfig.method,
|
|
1635
|
+
url: this.uploadConfig.url,
|
|
1636
|
+
data: createFormData({ image, ...extra, ...(this.uploadConfig.data ?? {}) }),
|
|
1637
|
+
onUploadProgress: function (progressEvent) {
|
|
1638
|
+
if(opt.onUploadProgress)
|
|
1639
|
+
opt.onUploadProgress(progressEvent)
|
|
1640
|
+
},
|
|
1641
|
+
})
|
|
1642
|
+
.then((res) => {
|
|
1643
|
+
return res.data
|
|
1644
|
+
})
|
|
1645
|
+
.catch((err) => {
|
|
1646
|
+
this.$refs.image.value = ''
|
|
1647
|
+
this.$refs.imageModal.close()
|
|
1648
|
+
this.toast(err)
|
|
1649
|
+
})
|
|
1650
|
+
}
|
|
1651
|
+
else{
|
|
1652
|
+
throw 'Unable to upload image'
|
|
1653
|
+
}
|
|
1654
|
+
},
|
|
1655
|
+
|
|
1656
|
+
chatApply(){
|
|
1657
|
+
|
|
1658
|
+
this.$refs.chatBtn.setState(2)
|
|
1659
|
+
return this.useSocket()
|
|
1660
|
+
.send(`${this.controller}.chat`, {
|
|
1661
|
+
key: this.chat.key,
|
|
1662
|
+
prompt: this.chat.input,
|
|
1663
|
+
attachments: this.chat.attachments,
|
|
1664
|
+
pageId: this.page.id,
|
|
1665
|
+
input: {
|
|
1666
|
+
components: this.page.components,
|
|
1667
|
+
styles: this.layout?.styles ?? {}
|
|
1668
|
+
}
|
|
1669
|
+
})
|
|
1670
|
+
.catch(err => this.alert(err))
|
|
1671
|
+
.then(res => {
|
|
1672
|
+
for(let message of res.messages){
|
|
1673
|
+
try{
|
|
1674
|
+
for(let attachment of (message.attachments ?? [])){
|
|
1675
|
+
if(attachment.type === 'page'){
|
|
1676
|
+
this.chatSet(attachment)
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
if(message.model) this.chat.model = message.model
|
|
1681
|
+
|
|
1682
|
+
this.chat.messages.push(message)
|
|
1683
|
+
}
|
|
1684
|
+
catch(e){
|
|
1685
|
+
console.error(e)
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
this.chat.input = ''
|
|
1690
|
+
this.chat.attachments = []
|
|
1691
|
+
})
|
|
1692
|
+
.finally(_ => this.$refs.chatBtn?.resetState())
|
|
1693
|
+
},
|
|
1694
|
+
|
|
1695
|
+
onChatUpload(e){
|
|
1696
|
+
for(let file of e.target.files){
|
|
1697
|
+
this.chat.attachments.push({
|
|
1698
|
+
type: "image",
|
|
1699
|
+
image: file
|
|
1700
|
+
})
|
|
1701
|
+
}
|
|
1702
|
+
},
|
|
1703
|
+
|
|
1704
|
+
chatSet(obj){
|
|
1705
|
+
|
|
1706
|
+
if(obj?.styles?.media && this.layout){
|
|
1707
|
+
Object.assign(this.layout, {
|
|
1708
|
+
styles: {
|
|
1709
|
+
media: this.createMedia(obj.styles.media),
|
|
1710
|
+
imports: obj.styles.imports
|
|
1711
|
+
}
|
|
1389
1712
|
})
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
if((obj?.components ?? []).length > 0){
|
|
1716
|
+
Object.assign(this.page, {
|
|
1717
|
+
components: obj.components
|
|
1394
1718
|
})
|
|
1719
|
+
}
|
|
1720
|
+
},
|
|
1721
|
+
|
|
1722
|
+
createMedia(obj){
|
|
1723
|
+
|
|
1724
|
+
const newMedia = JSON.parse(JSON.stringify(defaultMedia))
|
|
1725
|
+
|
|
1726
|
+
for(let selector in obj){
|
|
1727
|
+
if(!newMedia[selector]){
|
|
1728
|
+
newMedia[selector] = {}
|
|
1729
|
+
}
|
|
1730
|
+
for(let prop in obj[selector]){
|
|
1731
|
+
newMedia[selector][prop] = obj[selector][prop]
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
return newMedia
|
|
1395
1736
|
},
|
|
1396
1737
|
|
|
1738
|
+
newChat(){
|
|
1739
|
+
this.config.params.chat = {
|
|
1740
|
+
key: md5('web-page-chat-' + new Date().getTime()),
|
|
1741
|
+
input: '',
|
|
1742
|
+
attachments: [],
|
|
1743
|
+
messages: []
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1397
1747
|
},
|
|
1398
1748
|
|
|
1399
1749
|
computed: {
|
|
1400
1750
|
|
|
1401
1751
|
componentStore(){
|
|
1402
|
-
if(this.store
|
|
1403
|
-
|
|
1404
|
-
this.store.components.compsetting = {}
|
|
1752
|
+
if(!this.store.components)
|
|
1753
|
+
this.store.components = {}
|
|
1405
1754
|
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1755
|
+
if(!this.store.components.compsetting)
|
|
1756
|
+
this.store.components.compsetting = {}
|
|
1757
|
+
|
|
1758
|
+
return this.store.components.compsetting
|
|
1409
1759
|
},
|
|
1410
1760
|
|
|
1411
1761
|
expanded(){
|
|
@@ -1430,14 +1780,8 @@ export default{
|
|
|
1430
1780
|
this.prevData.layout !== JSON.stringify(this.layout))
|
|
1431
1781
|
},
|
|
1432
1782
|
|
|
1433
|
-
computedPreviewViewType(){
|
|
1434
|
-
if(this.store.previewViewType === 'auto')
|
|
1435
|
-
return this.store.viewType
|
|
1436
|
-
return this.store.previewViewType
|
|
1437
|
-
},
|
|
1438
|
-
|
|
1439
1783
|
computedIframeSrc(){
|
|
1440
|
-
return this.
|
|
1784
|
+
return this.page.app.hosts[0].name + this.page.path
|
|
1441
1785
|
},
|
|
1442
1786
|
|
|
1443
1787
|
currentItem(){
|
|
@@ -1483,7 +1827,7 @@ export default{
|
|
|
1483
1827
|
iframeSize(){
|
|
1484
1828
|
|
|
1485
1829
|
let width, height
|
|
1486
|
-
switch(this.
|
|
1830
|
+
switch(this.store.viewType){
|
|
1487
1831
|
case '':
|
|
1488
1832
|
width = 390
|
|
1489
1833
|
height = 844
|
|
@@ -1517,24 +1861,6 @@ export default{
|
|
|
1517
1861
|
}
|
|
1518
1862
|
},
|
|
1519
1863
|
|
|
1520
|
-
layoutHeaders(){
|
|
1521
|
-
if(!this.layout) return []
|
|
1522
|
-
|
|
1523
|
-
if(!Array.isArray(this.layout.headers))
|
|
1524
|
-
this.layout.headers = []
|
|
1525
|
-
|
|
1526
|
-
return this.layout.headers
|
|
1527
|
-
},
|
|
1528
|
-
|
|
1529
|
-
layoutFooters(){
|
|
1530
|
-
if(!this.layout) return []
|
|
1531
|
-
|
|
1532
|
-
if(!Array.isArray(this.layout.footers))
|
|
1533
|
-
this.layout.footers = []
|
|
1534
|
-
|
|
1535
|
-
return this.layout.footers
|
|
1536
|
-
},
|
|
1537
|
-
|
|
1538
1864
|
previewClass(){
|
|
1539
1865
|
return {
|
|
1540
1866
|
'overflow-auto': this.store.zoomLevel !== 'fit',
|
|
@@ -1554,125 +1880,71 @@ export default{
|
|
|
1554
1880
|
}
|
|
1555
1881
|
},
|
|
1556
1882
|
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
return {
|
|
1561
|
-
components: [
|
|
1562
|
-
|
|
1563
|
-
{"type":"Flex","name":"3 Column Layout","group":"Layouts","thumbnailUrl":"/images/templates/3-column-layout1.png", "items":[{"type":"Flex","name":"Flex","group":"Components","items":[{"type":"Article","name":"Article","group":"Components","props":{"htmlText":"Left","padding":["p-6",""],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"name":"Dummy Text"}}],"props":{"direction":["flex-col"],"enabled":true,"width":["","md:w-2/12"],"name":"Left"}},{"type":"Flex","name":"Flex","group":"Components","items":[{"type":"Article","name":"Article","group":"Components","props":{"htmlText":"Middle","padding":["p-6",""],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"name":"Dummy Text"}}],"props":{"direction":["flex-col"],"enabled":true,"width":[null,"md:flex-1"],"name":"Middle"}},{"type":"Flex","name":"Flex","group":"Components","items":[{"type":"Article","name":"Article","group":"Components","props":{"htmlText":"Right","padding":["p-6",""],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"name":"Dummy Text"}}],"props":{"direction":["flex-col"],"enabled":true,"width":[null,"md:w-3/12"],"name":"RIght"}}],"props":{"direction":["flex-col","md:flex-row"],"gap":[null,"md:gap-4"],"enabled":true,"name":"3 Column Layout"}},
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
{"type":"Flex","name":"Thumbnails","group":"Sections","thumbnailUrl":"/images/templates/thumbnails.gif","items":[{"type":"Flex","name":"Flex","group":"Components","items":[{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Thumbnails","tagName":"h5","flex":["flex-1"]}},{"type":"Link","name":"Link","group":"Components","props":{"enabled":true,"textColor":["text-primary-500"],"direction":["flex-column"],"gap":["gap-2"],"text":"More Thumbnails"},"items":[]}],"props":{"direction":["flex-row"],"enabled":true,"flexAlign":["items-center"]}},{"type":"Flex","name":"Flex","group":"Components","items":[{"type":"Thumbnail","name":"Thumbnail","group":"Components","props":{"enabled":true,"width":["w-5/12"],"direction":["flex-column"],"gap":["gap-2"],"flex":["flex-0"]},"items":[]},{"type":"Thumbnail","name":"Thumbnail","group":"Components","props":{"enabled":true,"width":["w-5/12"],"direction":["flex-column"],"gap":["gap-2"],"flex":["flex-0"]},"items":[]},{"type":"Thumbnail","name":"Thumbnail","group":"Components","props":{"enabled":true,"width":["w-5/12"],"direction":["flex-column"],"gap":["gap-2"],"flex":["flex-0"]},"items":[]}],"props":{"direction":["flex-row"],"gap":["gap-4"],"enabled":true,"overflow":["overflow-x-scroll"],"width":["w-full"],"minWidth":["min-w-0"]}}],"props":{"direction":["flex-col"],"gap":["gap-2"],"enabled":true,"padding":["p-5",""],"name":"Thumbnails"}},
|
|
1567
|
-
|
|
1568
|
-
{"type":"Carousel","name":"Image Carousel","group":"Sections","thumbnailUrl":"/images/templates/carousel1.png","items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["/assets/web/banner1.jpg"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"bdRadius":["rounded-xl"],"aspectRatio":["aspect-[2/1]"],"bgColors":["bg-amber-300"]}},{"type":"Image","name":"Image","group":"Components","props":{"src":["/assets/web/banner1.jpg"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"bdRadius":["rounded-xl"],"aspectRatio":["aspect-[2/1]"],"bgColors":["bg-lime-300"]}},{"type":"Image","name":"Image","group":"Components","props":{"src":["/assets/web/banner1.jpg"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"bdRadius":["rounded-xl"],"aspectRatio":["aspect-[2/1]"],"bgColors":["bg-blue-300"]}}],"props":{"enabled":true,"containerGap":["gap-2"],"padding":["p-4",""],"direction":["flex-column"],"gap":["gap-2"],"useLegend":true}},
|
|
1569
|
-
|
|
1570
|
-
{"type":"Link","name":"Icon Link","group":"Sections","thumbnailUrl":"/images/templates/icon-link.png","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["059bae0eadf1b650f3acff7dd1e7433a.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","fontWeight":["font-normal"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Icon Link 1"}}]},
|
|
1571
|
-
|
|
1572
|
-
{"type":"Carousel","name":"Icon Link Carousel","group":"Sections","thumbnailUrl":"/images/templates/icon-link-carousel.gif", "items":[{"type":"Grid","name":"Grid","group":"Components","thumbnailUrl":"/images/templates/grid1.png","items":[{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["059bae0eadf1b650f3acff7dd1e7433a.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 1","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["c7e8d12c0dcda3b9d3b2862559a8bc2e.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 2","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["47bcb782edfc426c8506664cc3b320e7.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 3","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["01e5a3e8f0e89562a7f6a5449be44614.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 4","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["7d7cc53e346aa5abf1f1ada463ed0e5c.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 5","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["4a1d1808e9f1be18f0ba18322647a11e.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 6","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["1b7f9673aeee9ebdf305658a54c63dc8.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 7","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["71828d52f682527cd500c1ba6c2a9ef0.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 8","fontSize":["text-sm"]}}]}],"gap":[],"props":{"columns":["grid-cols-4"],"gap":["gap-5"],"enabled":true,"direction":["flex-column"],"padding":["p-5",""]}},{"type":"Grid","name":"Grid","group":"Components","thumbnailUrl":"/images/templates/grid1.png","items":[{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["71828d52f682527cd500c1ba6c2a9ef0.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 9","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["059bae0eadf1b650f3acff7dd1e7433a.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 10","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["4a1d1808e9f1be18f0ba18322647a11e.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 11","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["7d7cc53e346aa5abf1f1ada463ed0e5c.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 12","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["47bcb782edfc426c8506664cc3b320e7.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 13","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["c7e8d12c0dcda3b9d3b2862559a8bc2e.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 14","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["4a1d1808e9f1be18f0ba18322647a11e.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 15","fontSize":["text-sm"]}}]},{"type":"Link","name":"Icon Link","group":"Sections","props":{"enabled":true,"display":["flex"],"direction":["flex-col"],"gap":["gap-2"],"flexAlign":["items-center"],"name":"Icon Link"},"items":[{"type":"Image","name":"Image","group":"Components","props":{"src":["059bae0eadf1b650f3acff7dd1e7433a.png"],"enabled":true,"direction":["flex-column"],"gap":["gap-2"]}},{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","enabled":true,"direction":["flex-column"],"gap":["gap-2"],"text":"Link 16","fontSize":["text-sm"]}}]}],"gap":[],"props":{"columns":["grid-cols-4"],"gap":["gap-5"],"enabled":true,"direction":["flex-column"],"padding":["p-5",""]}}],"props":{"enabled":true,"containerGap":["gap-2"],"padding":["p-4",""],"direction":["flex-column"],"gap":["gap-2"],"useLegend":true,"bgColors":["bg-gray-200"],"name":"Icon Link Carousel"}},
|
|
1573
|
-
|
|
1574
|
-
{ type:'ContactForm', name:'Contact Form', group:'Widgets', thumbnailUrl:"/images/templates/contact-form1.png", props:{
|
|
1575
|
-
fields:[
|
|
1576
|
-
{ type:'name', label:'Nama', required:true },
|
|
1577
|
-
{ type:'mobileNumber', label:'Nomor HP', required:true },
|
|
1578
|
-
{ type:'remark', label:'Pertanyaan' },
|
|
1579
|
-
],
|
|
1580
|
-
title: 'Contact Us',
|
|
1581
|
-
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent gravida erat eget nisi',
|
|
1582
|
-
submitMethod: 'post',
|
|
1583
|
-
submitUrl: '/inquiry',
|
|
1584
|
-
onSubmit:[],
|
|
1585
|
-
}},
|
|
1586
|
-
|
|
1587
|
-
{ type:'IconList', name:'Icon List', group:'Widgets', props:{
|
|
1588
|
-
icons:[], columns:[ 'grid-cols-4' ],
|
|
1589
|
-
}},
|
|
1590
|
-
|
|
1591
|
-
{ type:'DataList', name:'Data List', group:'Widgets', props:{}, items:[] },
|
|
1592
|
-
|
|
1593
|
-
{ type:'FAQ', name:'FAQ', group:'Widgets', thumbnailUrl:"/images/templates/faq.gif", props:{ items:[] }},
|
|
1594
|
-
{ type:'FAQ', name:'FAQ', group:'Widgets', thumbnailUrl:"/images/templates/faq.gif", props:{ items:[] }},
|
|
1595
|
-
|
|
1596
|
-
{ type:'FeatureList', name:'Feature List', group:'Widgets', props:{ items:[], columns:[], variant:['variant1'] }},
|
|
1597
|
-
|
|
1598
|
-
{ type:'Review', name:'Review', group:'Widgets', props:{} },
|
|
1599
|
-
|
|
1600
|
-
{ type:'Share', name:'Share To', group:'Widgets', props:{ channels:[] }},
|
|
1601
|
-
|
|
1602
|
-
{ type:'Testimonial', name:'Testimonial', group:'Widgets', props:{} },
|
|
1603
|
-
|
|
1604
|
-
{ type:'Header', name:'Header', group:'Widgets', props:{}, items:[] },
|
|
1605
|
-
|
|
1606
|
-
{ type:'ThumbnailList', name:'Thumbnail List', group:'Widgets', props:{ items:[] } },
|
|
1607
|
-
|
|
1608
|
-
{ type:'ProductDetail', name:'Product Detail', props:{}, group:'Widgets' },
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
{"type":"Flex","name":"Section 1","group":"Components","items":[{"type":"TextBlock","name":"TextBlock","group":"Components","props":{"htmlText":"","fontSize":["text-4xl"],"enabled":true,"text":"Drive more revenue at lower costs\n","fontWeight":["font-semibold"]}},{"type":"Paragraph","name":"Paragraph","group":"Components","props":{"name":"Paragraph","enabled":true,"text":"Reach every customer on their own preferred channel with dynamic, omnichannel campaigns, using channel-responsive templates.","html":"Reach every customer on their own preferred channel with dynamic, omnichannel campaigns, using channel-responsive templates.","maxWidth":["max-w-lg"],"fontSize":["text-xl"]}},{"type":"Flex","name":"Flex","group":"Components","items":[{"type":"Button","name":"Button","group":"Components","props":{"name":"Button","text":"Start Now","enabled":true,"padding":["px-3 py-0"],"fontSize":["text-xl"]}},{"type":"Button","name":"Button","group":"Components","props":{"name":"Button","text":"Contact Sales","enabled":true,"variant":"outline","padding":["p-3"],"fontSize":["text-xl"]}}],"props":{"direction":["flex-row"],"gap":["gap-3"],"enabled":true}}],"props":{"direction":["flex-col"],"gap":["gap-4"],"enabled":true,"padding":["p-8"],"margin":["mx-auto"],"width":["w-full"],"maxWidth":["max-w-screen-xl"]}},
|
|
1612
|
-
|
|
1613
|
-
{"type":"Carousel","name":"Carousel","group":"Components","items":[],"props":{"enabled":true,"containerGap":["gap-2"],"padding":["p-4",""],"direction":["flex-column"],"gap":["gap-2"],"useLegend":true}},
|
|
1614
|
-
|
|
1615
|
-
{ type:'Link', name:'Link', group:'Components', props:{}, items:[] },
|
|
1616
|
-
|
|
1617
|
-
{ type:'Modal', name:'Modal', group:'Components', props:{}, items:[] },
|
|
1618
|
-
|
|
1619
|
-
{ type:'Thumbnail', name:'Thumbnail', group:'Components', props:{}, items:[] },
|
|
1620
|
-
|
|
1621
|
-
{ type:'Ahref', name:'Ahref', group:'Components', props:{ name:'Ahref', text:'Ahref' } },
|
|
1622
|
-
|
|
1623
|
-
{ type:'Paragraph', name:'Paragraph', group:'Components', thumbnailUrl:"/images/templates/paragraph1.png", props:{ name:'Paragraph' } },
|
|
1624
|
-
|
|
1625
|
-
{ type:'Button', name:'Button', group:'Components', props:{
|
|
1626
|
-
name:'Button', text:'Button'
|
|
1627
|
-
}},
|
|
1628
|
-
|
|
1629
|
-
{ type:'Flex', name:'Flex', group:'Components', items:[], props:{ direction: [ 'flex-row' ] }},
|
|
1630
|
-
|
|
1631
|
-
{ type:'Grid', name:'Grid', group:'Components', thumbnailUrl:"/images/templates/grid1.png", items:[], gap:[], props:{
|
|
1632
|
-
columns: [], gap: [],
|
|
1633
|
-
}},
|
|
1634
|
-
|
|
1635
|
-
{ type:'Image', name:'Image', group:'Components', props:{
|
|
1636
|
-
src:[],
|
|
1637
|
-
}},
|
|
1638
|
-
|
|
1639
|
-
{ type:'EmbeddedVideo', name:'Video', group:'Components', props:{
|
|
1640
|
-
src:[],
|
|
1641
|
-
}},
|
|
1642
|
-
|
|
1643
|
-
{ type:'Article', name:'Article', group:'Components', props:{
|
|
1644
|
-
htmlText:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed convallis odio at odio dapibus, " +
|
|
1645
|
-
"eget molestie risus semper. Aenean magna tellus, aliquet nec tristique eget, lacinia nec urna.",
|
|
1646
|
-
}},
|
|
1883
|
+
store(){
|
|
1884
|
+
return this.config.params
|
|
1885
|
+
},
|
|
1647
1886
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1887
|
+
tabItems(){
|
|
1888
|
+
return [
|
|
1889
|
+
{ text:"Page Info", value:1 },
|
|
1890
|
+
{ text:"Layout", value:4 },
|
|
1891
|
+
{ text:"Components", value:2 },
|
|
1892
|
+
this.useChat ? { text:"Chat", value:7 } : null,
|
|
1893
|
+
/*{ text:"Datasource", value:3 },*/
|
|
1894
|
+
]
|
|
1895
|
+
.filter(_ => _)
|
|
1896
|
+
},
|
|
1651
1897
|
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1898
|
+
presetSrc(){
|
|
1899
|
+
return this.controller ?
|
|
1900
|
+
`${this.controller}.preset` :
|
|
1901
|
+
'user.preset'
|
|
1902
|
+
},
|
|
1656
1903
|
|
|
1657
|
-
|
|
1904
|
+
viewIndex(){
|
|
1905
|
+
return this.viewTypes.findIndex(_ => _.value === this.store.viewType)
|
|
1906
|
+
},
|
|
1658
1907
|
|
|
1659
|
-
|
|
1908
|
+
chat(){
|
|
1909
|
+
if(!this.config.params.chat)
|
|
1910
|
+
this.newChat()
|
|
1911
|
+
return this.config.params.chat
|
|
1912
|
+
},
|
|
1660
1913
|
|
|
1661
|
-
|
|
1914
|
+
totalChatTokens(){
|
|
1915
|
+
let total = 0
|
|
1916
|
+
for(let message of this.chat.messages){
|
|
1917
|
+
total += message.llmOutputTokenCount ?? 0
|
|
1918
|
+
}
|
|
1919
|
+
return total
|
|
1920
|
+
}
|
|
1662
1921
|
|
|
1663
|
-
|
|
1922
|
+
},
|
|
1664
1923
|
|
|
1665
|
-
|
|
1924
|
+
data(){
|
|
1925
|
+
return {
|
|
1926
|
+
components: defaultConfig.components,
|
|
1927
|
+
config: {
|
|
1928
|
+
params: {
|
|
1929
|
+
version: '0.0.999',
|
|
1930
|
+
layoutMode: false,
|
|
1931
|
+
selectedComponent: null, // [ 'uid|style', 'style|headers|components|footers' ]
|
|
1932
|
+
tabIndex: 2,
|
|
1933
|
+
viewType: '',
|
|
1934
|
+
zoomLevel: 'fit',
|
|
1935
|
+
width: [ 320, 320 ],
|
|
1936
|
+
previewMode: 1,
|
|
1937
|
+
}
|
|
1938
|
+
},
|
|
1666
1939
|
|
|
1667
|
-
currentArea: null,
|
|
1668
1940
|
currentComponentItems: null,
|
|
1669
1941
|
compClasses: [
|
|
1670
1942
|
'aspectRatio', 'position', 'left', 'top', 'right', 'bottom',
|
|
1671
1943
|
|
|
1672
|
-
'bdSize', '
|
|
1944
|
+
'bdSize', 'bdRadius', 'bdStyle',
|
|
1673
1945
|
'divideSize', 'divideColor', 'divideStyle',
|
|
1674
1946
|
'outlineWidth', 'outlineColor', 'outlineStyle',
|
|
1675
|
-
'
|
|
1947
|
+
'bgSize', 'bgPosition', 'bgRepeat',
|
|
1676
1948
|
'textAlign', 'verticalAlign',
|
|
1677
1949
|
'gap',
|
|
1678
1950
|
'padding', 'margin',
|
|
@@ -1687,6 +1959,8 @@ export default{
|
|
|
1687
1959
|
'flexDirection',
|
|
1688
1960
|
'zIndex',
|
|
1689
1961
|
|
|
1962
|
+
'backdropBlur',
|
|
1963
|
+
|
|
1690
1964
|
'autoFlow', 'alignItems', 'justifyContent',
|
|
1691
1965
|
'letterSpacing', 'lineClamp',
|
|
1692
1966
|
|
|
@@ -1698,9 +1972,12 @@ export default{
|
|
|
1698
1972
|
'containerVariant', 'containerGridColumn', 'containerGap'
|
|
1699
1973
|
],
|
|
1700
1974
|
itemClasses: [
|
|
1701
|
-
'itemMinWidth', 'itemRatio', 'itemVariant'
|
|
1975
|
+
'itemMinWidth', 'itemRatio', 'itemVariant', 'objectFit'
|
|
1976
|
+
],
|
|
1977
|
+
styleClasses: [
|
|
1978
|
+
'bgColors', 'bgImages', 'bdColor'
|
|
1702
1979
|
],
|
|
1703
|
-
|
|
1980
|
+
previewHost: null,
|
|
1704
1981
|
iframeStyle: {},
|
|
1705
1982
|
iframeSrc: '',
|
|
1706
1983
|
layouts: [],
|
|
@@ -1709,38 +1986,35 @@ export default{
|
|
|
1709
1986
|
{ text:"Design", value:1 },
|
|
1710
1987
|
{ text:"Preview", value:2 },
|
|
1711
1988
|
],
|
|
1712
|
-
previewViewTypes: [
|
|
1713
|
-
{ text:'Mobile', value:'' },
|
|
1714
|
-
{ text:'Tablet', value:'md:' },
|
|
1715
|
-
{ text:'Desktop', value:'xl:' },
|
|
1716
|
-
{ text:'TV', value:'2xl:' },
|
|
1717
|
-
],
|
|
1718
|
-
routerBeforeEach: null,
|
|
1719
|
-
state: 2,
|
|
1720
|
-
tabItems: [
|
|
1721
|
-
{ text:"Page Info", value:1 },
|
|
1722
|
-
{ text:"Components", value:2 },
|
|
1723
|
-
{ text:"Datasource", value:3 },
|
|
1724
|
-
],
|
|
1725
1989
|
viewTypes: [
|
|
1726
1990
|
{ text:'Mobile', value:'' },
|
|
1727
1991
|
{ text:'Tablet', value:'md:' },
|
|
1728
|
-
|
|
1729
|
-
{ text:'TV', value:'2xl:' },*/
|
|
1992
|
+
{ text:'Desktop', value:'xl:' }
|
|
1730
1993
|
],
|
|
1994
|
+
routerBeforeEach: null,
|
|
1995
|
+
readyState: 2,
|
|
1731
1996
|
stylesheets: [
|
|
1732
1997
|
'font-family'
|
|
1733
1998
|
],
|
|
1734
1999
|
updating: true,
|
|
2000
|
+
|
|
2001
|
+
extRightPane: null,
|
|
2002
|
+
debugMode: false,
|
|
2003
|
+
|
|
2004
|
+
useChat: false
|
|
1735
2005
|
}
|
|
1736
2006
|
},
|
|
1737
2007
|
|
|
1738
2008
|
emits: [ 'close', 'unmount' ],
|
|
1739
2009
|
|
|
1740
|
-
inject: [ 'alert', '
|
|
2010
|
+
inject: [ 'alert', 'appStyle', 'confirm', 'useSocket', 'toast' ],
|
|
1741
2011
|
|
|
1742
2012
|
mounted() {
|
|
1743
|
-
this.
|
|
2013
|
+
this.loadPreset()
|
|
2014
|
+
.then(_ => {
|
|
2015
|
+
this.loadLayouts()
|
|
2016
|
+
this.load()
|
|
2017
|
+
})
|
|
1744
2018
|
|
|
1745
2019
|
window.addEventListener('message', this.onMessage)
|
|
1746
2020
|
window.addEventListener('resize', this.onResize)
|
|
@@ -1757,7 +2031,7 @@ export default{
|
|
|
1757
2031
|
})
|
|
1758
2032
|
|
|
1759
2033
|
this.listen()
|
|
1760
|
-
this.
|
|
2034
|
+
this.useSocket().onAny(this.onHooks)
|
|
1761
2035
|
},
|
|
1762
2036
|
|
|
1763
2037
|
unmounted() {
|
|
@@ -1767,7 +2041,7 @@ export default{
|
|
|
1767
2041
|
window.removeEventListener('beforeunload', this.onUnload)
|
|
1768
2042
|
this.routerBeforeEach()
|
|
1769
2043
|
this.stopListen()
|
|
1770
|
-
this.
|
|
2044
|
+
this.useSocket().offAny(this.onHooks)
|
|
1771
2045
|
this.$emit('unmount', { uid:this.page.uid })
|
|
1772
2046
|
},
|
|
1773
2047
|
|
|
@@ -1780,11 +2054,23 @@ export default{
|
|
|
1780
2054
|
getPage: this.getPage,
|
|
1781
2055
|
uploadImage: this.uploadImage,
|
|
1782
2056
|
openComponentSelector: this.openComponentSelector,
|
|
2057
|
+
setUid: this.setUid,
|
|
2058
|
+
openRightPane2: this.openRightPane2,
|
|
2059
|
+
getRightPane: () => this.$refs.rightPane,
|
|
2060
|
+
pageHistory: this.pageHistory,
|
|
2061
|
+
duplicate: this.duplicate
|
|
1783
2062
|
}
|
|
1784
2063
|
},
|
|
1785
2064
|
|
|
1786
2065
|
watch: {
|
|
1787
2066
|
|
|
2067
|
+
config: {
|
|
2068
|
+
deep: true,
|
|
2069
|
+
handler(){
|
|
2070
|
+
this.savePreset()
|
|
2071
|
+
}
|
|
2072
|
+
},
|
|
2073
|
+
|
|
1788
2074
|
currentItem(){
|
|
1789
2075
|
this.$nextTick(() => this.resize())
|
|
1790
2076
|
},
|
|
@@ -1793,6 +2079,11 @@ export default{
|
|
|
1793
2079
|
if(to === 'fit'){
|
|
1794
2080
|
this.$refs.preview.scrollTop = 0
|
|
1795
2081
|
}
|
|
2082
|
+
this.resize()
|
|
2083
|
+
},
|
|
2084
|
+
|
|
2085
|
+
"store.viewType"(to){
|
|
2086
|
+
this.resize()
|
|
1796
2087
|
},
|
|
1797
2088
|
|
|
1798
2089
|
page: {
|
|
@@ -1820,20 +2111,41 @@ export default{
|
|
|
1820
2111
|
.comp{
|
|
1821
2112
|
@apply flex-1;
|
|
1822
2113
|
@apply hidden md:flex flex-row;
|
|
1823
|
-
@apply divide-x divide-
|
|
2114
|
+
@apply divide-x divide-border-50;
|
|
1824
2115
|
}
|
|
1825
2116
|
|
|
1826
2117
|
.resize1{
|
|
1827
|
-
@apply w-[3px] cursor-ew-resize;
|
|
2118
|
+
@apply w-[3px] cursor-ew-resize border-l-[1px] border-border-50;
|
|
1828
2119
|
}
|
|
1829
2120
|
|
|
1830
2121
|
.resize3{
|
|
1831
|
-
@apply w-[3px] cursor-ew-resize;
|
|
2122
|
+
@apply w-[3px] cursor-ew-resize border-r-[1px] border-border-50;
|
|
1832
2123
|
}
|
|
1833
2124
|
|
|
1834
2125
|
.zoomLevel{
|
|
1835
2126
|
@apply appearance-none bg-base-400 text-center outline-none h-[24px] rounded-md;
|
|
1836
|
-
@apply border-[1px] border-
|
|
2127
|
+
@apply border-[1px] border-border-200;
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
.chat{
|
|
2131
|
+
@apply max-w-[80%] flex flex-col;
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
.chatIn{
|
|
2135
|
+
@apply self-start;
|
|
2136
|
+
}
|
|
2137
|
+
.chatIn p{
|
|
2138
|
+
@apply bg-border-100 p-3 rounded-lg;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
.chatOut{
|
|
2142
|
+
@apply self-end flex flex-col items-end;
|
|
2143
|
+
}
|
|
2144
|
+
.chatOut p{
|
|
2145
|
+
@apply bg-primary-100 p-3 rounded-lg;
|
|
2146
|
+
}
|
|
2147
|
+
.chatOut button{
|
|
2148
|
+
@apply p-0 px-2 text-sm mt-1 rounded-sm;
|
|
1837
2149
|
}
|
|
1838
2150
|
|
|
1839
2151
|
</style>
|