template editor

This commit is contained in:
Julian Krauser 2024-12-21 16:01:18 +01:00
parent 0e430d1c9d
commit 467dfd8c1b
7 changed files with 208 additions and 2 deletions

20
package-lock.json generated
View file

@ -1,11 +1,11 @@
{
"name": "fireportal-ui",
"name": "member-administration-ui",
"version": "0.0.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fireportal-ui",
"name": "member-administration-ui",
"version": "0.0.11",
"license": "GPL-3.0-only",
"dependencies": {
@ -31,6 +31,7 @@
"socket.io-client": "^4.5.0",
"uuid": "^9.0.0",
"vue": "^3.4.29",
"vue-email-editor": "^2.1.4",
"vue-router": "^4.3.3"
},
"devDependencies": {
@ -9410,6 +9411,12 @@
"node": ">= 10.0.0"
}
},
"node_modules/unlayer-types": {
"version": "1.188.0",
"resolved": "https://registry.npmjs.org/unlayer-types/-/unlayer-types-1.188.0.tgz",
"integrity": "sha512-tnn+FjUZv1qUOoRUYRFxSDz9kHfhy7dLxzMZgnU5+k6GDSBlpa8mA+r4+r0D83M+mUUd/XwuM+gvfRLGzrqZ+g==",
"license": "MIT"
},
"node_modules/upath": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
@ -9700,6 +9707,15 @@
}
}
},
"node_modules/vue-email-editor": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/vue-email-editor/-/vue-email-editor-2.1.4.tgz",
"integrity": "sha512-9H6P2zgjOx4XJmKyMb4ZzCpsnKAqFk74daD86l/MhUvucF/qizTMUhOFnIMU6u9jtiB64NFvPTTzkRTTYTGkFw==",
"dependencies": {
"unlayer-types": "latest",
"vue": "^3.2.13"
}
},
"node_modules/vue-eslint-parser": {
"version": "9.4.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",

View file

@ -46,6 +46,7 @@
"socket.io-client": "^4.5.0",
"uuid": "^9.0.0",
"vue": "^3.4.29",
"vue-email-editor": "^2.1.4",
"vue-router": "^4.3.3"
},
"devDependencies": {

51
public/unlayerTool.js Normal file
View file

@ -0,0 +1,51 @@
unlayer.registerTool({
name: "my_tool",
label: "My Tool",
icon: "fa-smile",
// supportedDisplayModes: ["web", "email", "document"],
options: {
colors: {
// Property Group
title: "Colors", // Title for Property Group
position: 1, // Position of Property Group
options: {
textColor: {
// Property: textColor
label: "Text Color", // Label for Property
defaultValue: "#FF0000",
widget: "color_picker", // Property Editor Widget: color_picker
},
backgroundColor: {
// Property: backgroundColor
label: "Background Color", // Label for Property
defaultValue: "#FF0000",
widget: "color_picker", // Property Editor Widget: color_picker
},
},
},
},
values: {},
renderer: {
Viewer: unlayer.createViewer({
render(values) {
return `<div style="color: ${values.textColor}; background-color: ${values.backgroundColor};">I am a custom tool.</div>`;
},
}),
exporters: {
web: function (values) {
return `<div style="color: ${values.textColor}; background-color: ${values.backgroundColor};">I am a custom tool.</div>`;
},
email: function (values) {
return `<div style="color: ${values.textColor}; background-color: ${values.backgroundColor};">I am a custom tool.</div>`;
},
},
head: {
css: function (values) {},
js: function (values) {},
},
},
validator(data) {
const { defaultErrors, values } = data;
return [];
},
});

View file

@ -0,0 +1,28 @@
import type { EmailEditorProps } from "vue-email-editor/dist/components/types";
export const options: EmailEditorProps["options"] = {
tools: {
image: {
enabled: false,
},
menu: {
enabled: false,
},
button: {
enabled: false,
},
},
displayMode: "document",
appearance: {
theme: "light",
panels: {
tools: {
dock: "left",
},
},
},
features: {
preview: false,
},
customJS: [window.location.origin + "/unlayerTool.js"],
};

View file

@ -403,6 +403,28 @@ const router = createRouter({
meta: { type: "read", section: "settings", module: "query_store" },
beforeEnter: [abilityAndNavUpdate],
},
{
path: "template",
name: "admin-settings-template-route",
component: () => import("@/views/RouterView.vue"),
// meta: { type: "read", section: "settings", module: "template" },
beforeEnter: [abilityAndNavUpdate],
children: [
{
path: "",
name: "admin-settings-template",
component: () => import("@/views/admin/settings/template/Template.vue"),
},
{
path: ":id/edit",
name: "admin-settings-template-edit",
component: () => import("@/views/admin/settings/template/Template.vue"),
// meta: { type: "update", section: "settings", module: "template" },
// beforeEnter: [abilityAndNavUpdate],
props: true,
},
],
},
],
},
{

View file

@ -113,6 +113,7 @@ export const useNavigationStore = defineStore("navigation", {
? [{ key: "calendar_type", title: "Terminarten" }]
: []),
...(abilityStore.can("read", "settings", "query") ? [{ key: "query_store", title: "Query Store" }] : []),
...(true ? [{ key: "template", title: "Templates" }] : []),
],
},
user: {

View file

@ -0,0 +1,87 @@
<template>
<MainTemplate>
<template #topBar>
<div class="flex flex-row items-center justify-between pt-5 pb-3 px-7">
<h1 class="font-bold text-xl h-8">Templates</h1>
</div>
</template>
<template #diffMain>
<div class="flex flex-col gap-4 grow pl-7">
<div class="flex flex-col gap-2 grow pr-7">
<EmailEditor
ref="emailEditor"
minHeight="100%"
:options="options"
@load="editorLoaded"
@ready="editorReady"
/>
</div>
<div class="flex flex-row gap-4">
<button primary class="!w-fit" @click="saveDesign">Save Design</button>
<button primary-outline class="!w-fit" @click="loadBlank">leeren</button>
</div>
</div>
</template>
</MainTemplate>
</template>
<script setup lang="ts">
import { defineComponent } from "vue";
import { mapState, mapActions } from "pinia";
import MainTemplate from "@/templates/Main.vue";
import { EmailEditor } from "vue-email-editor";
import { options } from "@/helpers/unlayerEditor";
</script>
<script lang="ts">
export default defineComponent({
methods: {
// called when the editor is created
editorLoaded() {
console.log("editorLoaded");
// Pass the template JSON here
// this.$refs.emailEditor.editor.loadDesign({});
},
// called when the editor has finished loading
editorReady() {
console.log("editorReady");
(this.$refs.emailEditor as typeof EmailEditor).editor.setBodyValues({
contentWidth: "100%",
backgroundColor: "#ffffff",
linkStyle: {
linkColor: "#990b00",
linkHoverColor: "#bb1e10",
linkUnderline: false,
linkHoverUnderline: false,
},
});
},
loadBlank() {
(this.$refs.emailEditor as typeof EmailEditor).editor.loadBlank();
},
loadDesign() {
(this.$refs.emailEditor as typeof EmailEditor).editor.loadDesign((design: any) => {
console.log("saveDesign", design);
});
},
saveDesign() {
(this.$refs.emailEditor as typeof EmailEditor).editor.saveDesign((design: any) => {
console.log("saveDesign", design);
});
},
exportHtml() {
(this.$refs.emailEditor as typeof EmailEditor).editor.exportHtml((data: any) => {}, {
minify: true,
onlyHeader: true,
});
(this.$refs.emailEditor as typeof EmailEditor).editor.exportHtml((data: any) => {}, {
minify: true,
});
(this.$refs.emailEditor as typeof EmailEditor).editor.exportHtml((data: any) => {}, {
minify: true,
onlyFooter: true,
});
},
},
});
</script>