246 lines
7.6 KiB
Vue
246 lines
7.6 KiB
Vue
<template>
|
|
<div class="edit-pages">
|
|
<h2>Webseiten bearbeiten</h2>
|
|
<div>
|
|
<label for="page-select">Wähle eine Seite:</label>
|
|
<select id="page-select" v-model="selectedPage" @change="loadPageContent">
|
|
<option v-for="page in sortedPages" :key="page.link" :value="page.link">{{ page.name }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="toolbar">
|
|
<button @click="editor.chain().focus().toggleHeading({ level: 1 }).run()">H1</button>
|
|
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()">H2</button>
|
|
<button @click="editor.chain().focus().toggleHeading({ level: 3 }).run()">H3</button>
|
|
<button @click="editor.chain().focus().toggleBold().run()">Fett</button>
|
|
<button @click="editor.chain().focus().toggleItalic().run()">Kursiv</button>
|
|
<button @click="editor.chain().focus().toggleUnderline().run()">Unterstrichen</button>
|
|
<button @click="editor.chain().focus().toggleStrike().run()">Durchgestrichen</button>
|
|
<button @click="editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()">Tabelle</button>
|
|
<button @click="editor.chain().focus().toggleBulletList().run()">Liste</button>
|
|
<button @click="editor.chain().focus().toggleOrderedList().run()">Nummerierte Liste</button>
|
|
</div>
|
|
<div class="table-toolbar">
|
|
<button @click="editor.chain().focus().addColumnBefore().run()">Spalte davor einfügen</button>
|
|
<button @click="editor.chain().focus().addColumnAfter().run()">Spalte danach einfügen</button>
|
|
<button @click="editor.chain().focus().addRowBefore().run()">Zeile davor einfügen</button>
|
|
<button @click="editor.chain().focus().addRowAfter().run()">Zeile danach einfügen</button>
|
|
<button @click="editor.chain().focus().deleteColumn().run()">Spalte löschen</button>
|
|
<button @click="editor.chain().focus().deleteRow().run()">Zeile löschen</button>
|
|
<button @click="editor.chain().focus().toggleHeaderColumn().run()">Header-Spalte umschalten</button>
|
|
<button @click="editor.chain().focus().toggleHeaderRow().run()">Header-Zeile umschalten</button>
|
|
<button @click="editor.chain().focus().toggleHeaderCell().run()">Header-Zelle umschalten</button>
|
|
</div>
|
|
<div class="additional-toolbar">
|
|
<button>Events</button>
|
|
<button>Kontaktpersonen</button>
|
|
<button>Institutionen</button>
|
|
<button @click="openWorshipDialog">Gottesdienste</button>
|
|
</div>
|
|
<div :class="['htmleditor']">
|
|
<EditorContent :editor="editor" />
|
|
</div>
|
|
<button @click="savePageContent">Speichern</button>
|
|
|
|
<WorshipDialog ref="worshipDialog" @confirm="insertWorshipList" />
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, computed, onMounted, watch } from 'vue';
|
|
import { useStore } from 'vuex';
|
|
import axios from '../../axios';
|
|
import { EditorContent, useEditor } from '@tiptap/vue-3';
|
|
import StarterKit from '@tiptap/starter-kit';
|
|
import Table from '@tiptap/extension-table';
|
|
import TableRow from '@tiptap/extension-table-row';
|
|
import Bold from '@tiptap/extension-bold';
|
|
import Italic from '@tiptap/extension-italic';
|
|
import Underline from '@tiptap/extension-underline';
|
|
import Strike from '@tiptap/extension-strike';
|
|
import BulletList from '@tiptap/extension-bullet-list';
|
|
import OrderedList from '@tiptap/extension-ordered-list';
|
|
import Heading from '@tiptap/extension-heading';
|
|
import { CustomTableCell, CustomTableHeader } from '../../extensions/CustomTableCell';
|
|
import WorshipDialog from '@/components/WorshipDialog.vue';
|
|
|
|
export default {
|
|
name: 'EditPagesComponent',
|
|
components: {
|
|
EditorContent,
|
|
WorshipDialog,
|
|
},
|
|
setup() {
|
|
const store = useStore();
|
|
const pages = ref([]);
|
|
const selectedPage = ref('');
|
|
const pageHtmlContent = computed(() => store.state.pageContent);
|
|
const worshipDialog = ref(null);
|
|
|
|
const editor = useEditor({
|
|
extensions: [
|
|
StarterKit,
|
|
Table.configure({
|
|
resizable: true,
|
|
}),
|
|
TableRow,
|
|
CustomTableCell,
|
|
CustomTableHeader,
|
|
Bold,
|
|
Italic,
|
|
Underline,
|
|
Strike,
|
|
BulletList,
|
|
OrderedList,
|
|
Heading.configure({
|
|
levels: [1, 2, 3],
|
|
}),
|
|
],
|
|
content: '',
|
|
onUpdate: ({ editor }) => {
|
|
store.commit('SET_PAGE_CONTENT', editor.getHTML());
|
|
},
|
|
});
|
|
|
|
const flattenPages = (pages, allPages, parentName = '') => {
|
|
pages.forEach(page => {
|
|
const pageName = parentName ? `${parentName} -> ${page.name}` : page.name;
|
|
allPages.push({ ...page, name: pageName });
|
|
if (page.submenu && page.submenu.length) {
|
|
flattenPages(page.submenu, allPages, pageName);
|
|
}
|
|
});
|
|
};
|
|
|
|
const fetchPages = async () => {
|
|
try {
|
|
const response = await axios.get('/menu-data');
|
|
const data = response.data;
|
|
const allPages = [];
|
|
flattenPages(data, allPages);
|
|
pages.value = allPages.sort((a, b) => a.name.localeCompare(b.name));
|
|
store.commit('setMenuData', data);
|
|
} catch (error) {
|
|
console.error('Fehler beim Abrufen der Seiten:', error);
|
|
}
|
|
};
|
|
|
|
const loadPageContent = async () => {
|
|
try {
|
|
await store.dispatch('loadPageContent', selectedPage.value);
|
|
const content = store.getters.pageContent;
|
|
const setEditorContent = () => {
|
|
if (editor.value && editor.value.commands) {
|
|
editor.value.commands.setContent(content, false);
|
|
} else {
|
|
setTimeout(setEditorContent, 100);
|
|
}
|
|
};
|
|
setEditorContent();
|
|
} catch (error) {
|
|
console.error('Fehler beim Laden des Seiteninhalts:', error);
|
|
}
|
|
};
|
|
|
|
const savePageContent = async () => {
|
|
try {
|
|
const selectedPageName = pages.value.find(page => page.link === selectedPage.value)?.name || '';
|
|
if (!selectedPageName) {
|
|
return;
|
|
}
|
|
|
|
const contentToSave = editor.value.getHTML();
|
|
store.commit('SET_PAGE_CONTENT', contentToSave);
|
|
|
|
await store.dispatch('savePageContent', {
|
|
link: selectedPage.value,
|
|
name: selectedPageName,
|
|
});
|
|
} catch (error) {
|
|
console.error('Fehler beim Speichern des Seiteninhalts:', error);
|
|
}
|
|
};
|
|
|
|
onMounted(fetchPages);
|
|
|
|
const sortedPages = computed(() => {
|
|
return pages.value;
|
|
});
|
|
|
|
watch(selectedPage, (newPage) => {
|
|
store.dispatch('setSelectedPage', newPage);
|
|
const page = pages.value.find(page => page.link === newPage);
|
|
if (page) {
|
|
store.dispatch('setPageTitle', page.name);
|
|
}
|
|
loadPageContent();
|
|
});
|
|
|
|
const openWorshipDialog = () => {
|
|
worshipDialog.value.openWorshipDialog();
|
|
};
|
|
|
|
const insertWorshipList = (configuration) => {
|
|
if (editor.value) {
|
|
editor.value.chain().focus().insertContent(`{{ worshipslist:location=${configuration},order:"date asc" }}`).run();
|
|
}
|
|
};
|
|
|
|
return {
|
|
pages,
|
|
sortedPages,
|
|
selectedPage,
|
|
editor,
|
|
loadPageContent,
|
|
savePageContent,
|
|
pageHtmlContent,
|
|
openWorshipDialog,
|
|
insertWorshipList,
|
|
worshipDialog,
|
|
};
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.edit-pages {
|
|
width: 100%;
|
|
margin: auto;
|
|
}
|
|
|
|
#page-select {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.toolbar {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.toolbar button {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.table-toolbar {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.table-toolbar button {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.additional-toolbar {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.additional-toolbar button {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.ql-container {
|
|
background-color: #fff !important;
|
|
}
|
|
|
|
.ql-editor {
|
|
background-color: #fff !important;
|
|
}
|
|
</style>
|