Fixed format of events
This commit is contained in:
@@ -21,7 +21,7 @@ const getAllEvents = async (req, res) => {
|
||||
|
||||
const filterEvents = async (req, res) => {
|
||||
try {
|
||||
const { id, 'event-places': eventPlaces, 'event-types': eventTypes, display } = req.query;
|
||||
const request = req.body;
|
||||
const where = {
|
||||
[Op.or]: [
|
||||
{
|
||||
@@ -36,7 +36,7 @@ const filterEvents = async (req, res) => {
|
||||
]
|
||||
};
|
||||
|
||||
if (id === 'all') {
|
||||
if (request.id === 'all') {
|
||||
const events = await Event.findAll({
|
||||
where,
|
||||
include: [
|
||||
@@ -49,7 +49,7 @@ const filterEvents = async (req, res) => {
|
||||
return res.json({ events });
|
||||
}
|
||||
|
||||
if (id === 'home') {
|
||||
if (request.id === 'home') {
|
||||
const events = await Event.findAll({
|
||||
where: {
|
||||
alsoOnHomepage: 1,
|
||||
@@ -65,23 +65,23 @@ const filterEvents = async (req, res) => {
|
||||
return res.json({ events });
|
||||
}
|
||||
|
||||
if (!id && !eventPlaces && !eventTypes) {
|
||||
return res.json({ events: [], eventPlaces: [], eventTypes: [], contactPersons: [] });
|
||||
if (!request.id && !request.places && !request.types) {
|
||||
return res.json({ events: [], places: [], types: [], contactPersons: [] });
|
||||
}
|
||||
|
||||
if (id) {
|
||||
where.id = id;
|
||||
if (request.id) {
|
||||
where.id = request.id;
|
||||
}
|
||||
|
||||
if (eventPlaces) {
|
||||
if (request.places && request.places.length > 0) {
|
||||
where.event_place_id = {
|
||||
[Op.in]: eventPlaces.split('|').map(id => parseInt(id))
|
||||
[Op.in]: request.places.map(id => parseInt(id))
|
||||
};
|
||||
}
|
||||
|
||||
if (eventTypes) {
|
||||
if (request.types && request.types.length > 0) {
|
||||
where.eventTypeId = {
|
||||
[Op.in]: eventTypes.split('|').map(id => parseInt(id))
|
||||
[Op.in]: request.types.map(id => parseInt(id))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -94,8 +94,7 @@ const filterEvents = async (req, res) => {
|
||||
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } }
|
||||
]
|
||||
});
|
||||
|
||||
const displayFields = display ? display.split('|') : [];
|
||||
const displayFields = request.display ? request.display : [];
|
||||
|
||||
const filteredEvents = events.map(event => {
|
||||
const filteredEvent = { ...event.toJSON() };
|
||||
|
||||
@@ -18,6 +18,28 @@ const getAllInstitutions = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getInstitutionById = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const institution = await Institution.findByPk(id, {
|
||||
include: [
|
||||
{
|
||||
model: ContactPerson,
|
||||
as: 'contactPersons',
|
||||
through: { attributes: [] }
|
||||
}
|
||||
]
|
||||
});
|
||||
if (!institution) {
|
||||
return res.status(404).json({ error: 'Institution not found' });
|
||||
}
|
||||
res.json(institution);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to fetch institution' });
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const createInstitution = async (req, res) => {
|
||||
try {
|
||||
const { contactPersonIds, ...institutionData } = req.body;
|
||||
@@ -70,6 +92,7 @@ const deleteInstitution = async (req, res) => {
|
||||
|
||||
module.exports = {
|
||||
getAllInstitutions,
|
||||
getInstitutionById,
|
||||
createInstitution,
|
||||
updateInstitution,
|
||||
deleteInstitution
|
||||
|
||||
@@ -49,24 +49,21 @@ exports.deleteWorship = async (req, res) => {
|
||||
};
|
||||
|
||||
exports.getFilteredWorships = async (req, res) => {
|
||||
const { location, orderBy } = req.query;
|
||||
const { location, order } = req.query;
|
||||
const where = {};
|
||||
|
||||
if (location && location !== '-1') {
|
||||
if (location.includes('|')) {
|
||||
const locationsArray = location.split('|');
|
||||
const locations = JSON.parse(location);
|
||||
if (location && locations.length > 0) {
|
||||
where.eventPlaceId = {
|
||||
[Sequelize.Op.in]: locationsArray
|
||||
[Sequelize.Op.in]: locations
|
||||
}
|
||||
} else {
|
||||
where.eventPlaceId = location;
|
||||
}
|
||||
}
|
||||
|
||||
where.date = {
|
||||
[Op.gte]: new Date(), // Only include events from today onwards
|
||||
};
|
||||
|
||||
console.log(where, order);
|
||||
try {
|
||||
const worships = await Worship.findAll({
|
||||
where,
|
||||
@@ -74,7 +71,7 @@ exports.getFilteredWorships = async (req, res) => {
|
||||
model: EventPlace,
|
||||
as: 'eventPlace',
|
||||
},
|
||||
order: [orderBy.split(' ')],
|
||||
order: [order.split(' ')],
|
||||
});
|
||||
res.status(200).json(worships);
|
||||
} catch (error) {
|
||||
|
||||
@@ -26,7 +26,7 @@ module.exports = (sequelize) => {
|
||||
pageId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: true
|
||||
}
|
||||
},
|
||||
}, {
|
||||
tableName: 'images',
|
||||
timestamps: false
|
||||
|
||||
@@ -37,7 +37,11 @@ module.exports = (sequelize) => {
|
||||
page_title: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
},
|
||||
image: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
},
|
||||
}, {
|
||||
tableName: 'menu_items',
|
||||
timestamps: false
|
||||
|
||||
BIN
public/images/uploads/0cf0624e-8394-49fc-a44d-3d2f4d876061.jpg
Normal file
BIN
public/images/uploads/0cf0624e-8394-49fc-a44d-3d2f4d876061.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 KiB |
@@ -7,6 +7,6 @@ router.get('/', authMiddleware, getAllEvents);
|
||||
router.post('/', authMiddleware, createEvent);
|
||||
router.put('/:id', authMiddleware, updateEvent);
|
||||
router.delete('/:id', authMiddleware, deleteEvent);
|
||||
router.get('/filter', filterEvents);
|
||||
router.post('/filter', filterEvents);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const institutionController = require('../controllers/institutionController');
|
||||
const authMiddleware = require('../middleware/authMiddleware')
|
||||
const authMiddleware = require('../middleware/authMiddleware');
|
||||
|
||||
router.get('/', authMiddleware, institutionController.getAllInstitutions);
|
||||
router.get('/', institutionController.getAllInstitutions);
|
||||
router.get('/:id', institutionController.getInstitutionById); // Neuer Endpunkt
|
||||
router.post('/', authMiddleware, institutionController.createInstitution);
|
||||
router.put('/:id', authMiddleware, institutionController.updateInstitution);
|
||||
router.delete('/:id', authMiddleware, institutionController.deleteInstitution);
|
||||
|
||||
@@ -24,10 +24,12 @@ export default {
|
||||
await this.loadMenuData();
|
||||
this.$router.push({ path: '/' }); // Zurück zur Startseite oder eine andere Seite, um sicherzustellen, dass der Router neu geladen wird
|
||||
const routes = this.$store.state.menuData.map(item => {
|
||||
return {
|
||||
path: item.link,
|
||||
component: () => import(`../components/${item.component}.vue`)
|
||||
};
|
||||
if (item.component) {
|
||||
return {
|
||||
path: item.link,
|
||||
component: () => import(`../components/${item.component}.vue`)
|
||||
};
|
||||
}
|
||||
});
|
||||
routes.forEach(route => router.addRoute(route)); // Neue Routen hinzufügen
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
<multiselect id="types-select" v-model="selectedEventTypes" :options="eventTypes" :multiple="true"
|
||||
label="caption" track-by="id" />
|
||||
</div>
|
||||
<div v-if="selectedTypes.some(type => type.id === 'position')">
|
||||
<label for="contact-select">Wählen Sie eine Position:</label>
|
||||
<multiselect id="contact-select" v-model="selectedPositions" :options="positions" :multiple="false"
|
||||
label="caption" track-by="id" />
|
||||
</div>
|
||||
<div v-if="selectedTypes.some(type => type.id === 'specific')">
|
||||
<label for="contact-select">Wählen Sie eine Kontaktperson:</label>
|
||||
<multiselect id="contact-select" v-model="selectedContact" :options="contacts" :multiple="false"
|
||||
@@ -66,9 +71,11 @@ export default {
|
||||
const contacts = ref([]);
|
||||
const eventTypes = ref([]);
|
||||
const places = ref([]);
|
||||
const positions = ref([]);
|
||||
const selectedContact = ref(null);
|
||||
const selectedTypes = ref([]);
|
||||
const selectedEventTypes = ref([]);
|
||||
const selectedPositions = ref([]);
|
||||
const selectedPlaces = ref([]);
|
||||
const displayStyle = ref('float');
|
||||
|
||||
@@ -86,6 +93,7 @@ export default {
|
||||
{ id: 'specific', caption: 'Eine Person' },
|
||||
{ id: 'places', caption: 'Für bestimmte Orte' },
|
||||
{ id: 'types', caption: 'Für bestimmte Typen' },
|
||||
{ id: 'position', caption: 'Für bestimmte Positionen'}
|
||||
]);
|
||||
|
||||
const displayStyles = ref([
|
||||
@@ -98,6 +106,7 @@ export default {
|
||||
fetchContacts();
|
||||
fetchEventTypes();
|
||||
fetchPlaces();
|
||||
fetchPositions();
|
||||
};
|
||||
|
||||
const closeAddContactDialog = () => {
|
||||
@@ -110,16 +119,18 @@ export default {
|
||||
selectedContact.value = null;
|
||||
selectedEventTypes.value = [];
|
||||
selectedPlaces.value = [];
|
||||
selectedPositions.value = [];
|
||||
} else if (selectedTypes.value.some(type => type.id === 'specific')) {
|
||||
selectedTypes.value = [{ id: 'specific', caption: 'Eine Person' }];
|
||||
selectedEventTypes.value = [];
|
||||
selectedPlaces.value = [];
|
||||
selectedPositions.value = [];
|
||||
} else if (selectedTypes.value.some(type => type.id === 'places')) {
|
||||
selectedContact.value = null;
|
||||
selectedEventTypes.value = [];
|
||||
} else if (selectedTypes.value.some(type => type.id === 'types')) {
|
||||
selectedContact.value = null;
|
||||
selectedPlaces.value = [];
|
||||
} else if (selectedPositions.value.some(type => type.id === 'position')) {
|
||||
selectedContact.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,8 +143,9 @@ export default {
|
||||
} else if (selectedTypes.value.some(type => type.id === 'specific') && selectedContact.value) {
|
||||
selection['id'] = selectedContact.value.id;
|
||||
} else {
|
||||
selection['types'] = selectedEventTypes.value.map((type) => type.id).join('|');
|
||||
selection['places'] = selectedPlaces.value.map((place) => place.id).join('|');
|
||||
selection['types'] = selectedEventTypes.value.map((type) => type.id);
|
||||
selection['places'] = selectedPlaces.value.map((place) => place.id);
|
||||
selection['positions'] = selectedPositions.value((postion) => postion.id);
|
||||
}
|
||||
const contact = {
|
||||
selection: selection,
|
||||
@@ -166,13 +178,21 @@ export default {
|
||||
const fetchPlaces = async () => {
|
||||
try {
|
||||
const response = await axios.get('/event-places');
|
||||
console.log(response);
|
||||
places.value = response.data;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Orte:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchPositions = async () => {
|
||||
try {
|
||||
const response = await axios.get('/positions');
|
||||
positions.value = response.data;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Positionen:', error)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
contacts,
|
||||
@@ -190,6 +210,8 @@ export default {
|
||||
onTypeSelect,
|
||||
places,
|
||||
eventTypes,
|
||||
positions,
|
||||
selectedPositions,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
},
|
||||
confirm() {
|
||||
if (this.selectedFile) {
|
||||
this.$emit('confirm', this.selectedFile.hash);
|
||||
console.log(this.selectedFile.hash);
|
||||
this.$emit('confirm', { hash: this.selectedFile.hash });
|
||||
this.closeDialog();
|
||||
} else {
|
||||
alert('Bitte wählen Sie eine Datei aus.');
|
||||
|
||||
@@ -102,23 +102,21 @@ export default {
|
||||
};
|
||||
|
||||
const confirmAddEventConfiguration = () => {
|
||||
let configString = '';
|
||||
const displayString = Object.keys(displayOptions.value)
|
||||
.filter(key => displayOptions.value[key])
|
||||
.join('|');
|
||||
const event = {};
|
||||
event.display = Object.keys(displayOptions.value)
|
||||
.filter(key => displayOptions.value[key]);
|
||||
|
||||
if (isHomepage.value) {
|
||||
configString = `{{ events:id=home,display=${displayString} }}`
|
||||
event.id = "home";
|
||||
} else if (selectedTypes.value.includes('Alle')) {
|
||||
configString = `{{ events:id=all,display=${displayString} }}`;
|
||||
event.id = "all"
|
||||
} else if (selectedTypes.value.includes('Ein bestimmtes')) {
|
||||
configString = `{{ events:id=${selectedEvent.value.id},display=${displayString} }}`;
|
||||
event.id = selectedEvent.value.id;
|
||||
} else {
|
||||
const placesString = selectedPlaces.value.map(place => place.id).join('|');
|
||||
const eventTypesString = selectedEventTypes.value.map(eventType => eventType.id).join('|');
|
||||
configString = `{{ events:${placesString ? `event-places=${placesString},` : ''}${eventTypesString ? `event-types=${eventTypesString},` : ''}display=${displayString} }}`;
|
||||
event.types = selectedEventTypes.value.map(eventType => eventType.id);
|
||||
event.places = selectedPlaces.value.map(place => place.id);
|
||||
}
|
||||
emit('confirm', configString);
|
||||
emit('confirm', '{{ events:' + JSON.stringify(event) + ' }}');
|
||||
closeAddEventDialog();
|
||||
};
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ export default {
|
||||
|
||||
const confirmAddImageConfiguration = () => {
|
||||
if (selectedImage.value) {
|
||||
console.log('->', selectImage.value);
|
||||
emit('confirm', `${selectedImage.value.id}`);
|
||||
}
|
||||
closeAddImageDialog();
|
||||
|
||||
154
src/components/AddInstitutionDialog.vue
Normal file
154
src/components/AddInstitutionDialog.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="isOpen" class="dialog-overlay">
|
||||
<div class="dialog-content">
|
||||
<h3>Institution hinzufügen</h3>
|
||||
<div>
|
||||
<label for="institution-select">Wählen Sie eine Institution:</label>
|
||||
<multiselect id="institution-select" v-model="selectedInstitution" :options="institutionOptions" :multiple="false" label="name" track-by="id" @select="onInstitutionSelect" />
|
||||
</div>
|
||||
<div>
|
||||
<label>Wählen Sie welche Elemente angezeigt werden sollen:</label>
|
||||
<div class="display-options">
|
||||
<label><input type="checkbox" v-model="displayOptions.street" /> Straße</label>
|
||||
<label><input type="checkbox" v-model="displayOptions.zipcode" /> Postleitzahl</label>
|
||||
<label><input type="checkbox" v-model="displayOptions.city" /> Stadt</label>
|
||||
<label><input type="checkbox" v-model="displayOptions.phone" /> Telefon</label>
|
||||
<label><input type="checkbox" v-model="displayOptions.fax" /> Fax</label>
|
||||
<label><input type="checkbox" v-model="displayOptions.email" /> E-Mail</label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="displayStyle">Anzeigen als</label>
|
||||
<select id="displayStyle" v-model="displayStyle">
|
||||
<option v-for="style in displayStyles" :value="style.id" :key="style.id">{{ style.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button @click="confirmAddInstitutionConfiguration">Bestätigen</button>
|
||||
<button @click="closeAddInstitutionDialog">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
import axios from '@/axios';
|
||||
import Multiselect from 'vue-multiselect';
|
||||
|
||||
export default {
|
||||
name: 'AddInstitutionDialog',
|
||||
components: {
|
||||
Multiselect,
|
||||
},
|
||||
emits: ['confirm'],
|
||||
setup(props, { emit }) {
|
||||
const isOpen = ref(false);
|
||||
const institutions = ref([]);
|
||||
const selectedInstitution = ref(null);
|
||||
const displayStyle = ref('float');
|
||||
|
||||
const displayOptions = ref({
|
||||
street: false,
|
||||
zipcode: false,
|
||||
city: false,
|
||||
phone: false,
|
||||
fax: false,
|
||||
email: false,
|
||||
});
|
||||
|
||||
const institutionOptions = ref([
|
||||
{ id: 'all', name: 'Alle' },
|
||||
...institutions.value,
|
||||
]);
|
||||
|
||||
const displayStyles = ref([
|
||||
{ id: 'float', label: 'Durchlaufender Text' },
|
||||
{ id: 'box', label: 'Textbox' },
|
||||
]);
|
||||
|
||||
const openAddInstitutionDialog = () => {
|
||||
isOpen.value = true;
|
||||
fetchInstitutions();
|
||||
};
|
||||
|
||||
const closeAddInstitutionDialog = () => {
|
||||
isOpen.value = false;
|
||||
};
|
||||
|
||||
const onInstitutionSelect = () => {
|
||||
if (selectedInstitution.value && selectedInstitution.value.id === 'all') {
|
||||
institutionOptions.value = [{ id: 'all', name: 'Alle' }];
|
||||
selectedInstitution.value = { id: 'all', name: 'Alle' };
|
||||
}
|
||||
};
|
||||
|
||||
const confirmAddInstitutionConfiguration = () => {
|
||||
const displayArray = Object.keys(displayOptions.value).filter((key) => displayOptions.value[key]);
|
||||
const institutionConfig = {
|
||||
id: selectedInstitution.value.id,
|
||||
display: displayArray,
|
||||
style: displayStyle.value
|
||||
};
|
||||
const configString = `{{ institution:${JSON.stringify(institutionConfig)} }}`;
|
||||
emit('confirm', configString);
|
||||
closeAddInstitutionDialog();
|
||||
};
|
||||
|
||||
const fetchInstitutions = async () => {
|
||||
try {
|
||||
const response = await axios.get('/institutions');
|
||||
institutions.value = response.data;
|
||||
institutionOptions.value = [{ id: 'all', name: 'Alle' }, ...institutions.value];
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Institutionen:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
institutions,
|
||||
selectedInstitution,
|
||||
displayOptions,
|
||||
displayStyle,
|
||||
displayStyles,
|
||||
institutionOptions,
|
||||
openAddInstitutionDialog,
|
||||
closeAddInstitutionDialog,
|
||||
confirmAddInstitutionConfiguration,
|
||||
onInstitutionSelect,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dialog-content {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.multiselect {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.display-options label {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -46,15 +46,11 @@ export default {
|
||||
},
|
||||
async created() {
|
||||
try {
|
||||
console.log('Initial config:', JSON.stringify(this.config));
|
||||
this.displayOptions = this.config.display || [];
|
||||
console.log('Display options:', this.displayOptions);
|
||||
const response = await axios.post('/contact-persons/filter', {
|
||||
config: JSON.stringify(this.config),
|
||||
});
|
||||
this.contacts = response.data;
|
||||
console.log('Fetched contacts:', JSON.stringify(this.contacts));
|
||||
console.log('Config style:', this.config.style);
|
||||
this.loading = false;
|
||||
} catch (error) {
|
||||
console.error('Error loading contacts:', error);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<span @click="downloadFile">{{ title }}</span>
|
||||
<span v-if="title" @click="downloadFile">{{ title }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -8,20 +8,33 @@ import axios from 'axios';
|
||||
export default {
|
||||
name: 'DownloadLink',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
hash: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
extension: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
link: '',
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
await this.fetchFile();
|
||||
},
|
||||
methods: {
|
||||
async fetchFile() {
|
||||
try {
|
||||
console.log(this.hash);
|
||||
const response = await axios.get('/files/hash/' + this.hash);
|
||||
this.title = response.data.title;
|
||||
console.log('Fetched files:', response.data.events);
|
||||
this.events = response.data.events;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Events', error);
|
||||
}
|
||||
},
|
||||
|
||||
async downloadFile() {
|
||||
const response = await axios.get(`/files/download/${this.hash}`, {
|
||||
responseType: 'blob'
|
||||
|
||||
@@ -49,19 +49,18 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async fetchEvents() {
|
||||
console.log(this.config);
|
||||
try {
|
||||
const response = await axios.get('/events/filter', {
|
||||
params: this.config
|
||||
});
|
||||
console.log('Fetched events:', response.data.events);
|
||||
const response = await axios.post('/events/filter',
|
||||
this.config
|
||||
);
|
||||
this.events = response.data.events;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Abrufen der Events', error);
|
||||
}
|
||||
},
|
||||
shouldDisplay(field) {
|
||||
const displayFields = this.config.display.split('|');
|
||||
return displayFields.includes(field);
|
||||
return this.config.display.includes(field);
|
||||
},
|
||||
formatDateOrDay(date, dayOfWeek) {
|
||||
if (date) {
|
||||
|
||||
64
src/components/InstitutionRender.vue
Normal file
64
src/components/InstitutionRender.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div v-if="config && config.style === 'box' && institution">
|
||||
<h3>{{ institution.name }}</h3>
|
||||
<span v-if="displayOptions.includes('street')">Straße: {{ institution.street }}<br></span>
|
||||
<span v-if="displayOptions.includes('zipcode')">Postleitzahl: {{ institution.zipcode }}<br></span>
|
||||
<span v-if="displayOptions.includes('city')">Stadt: {{ institution.city }}<br></span>
|
||||
<span v-if="displayOptions.includes('email')">E-Mail: {{ institution.email }}<br></span>
|
||||
<span v-if="displayOptions.includes('phone')">Telefon: {{ institution.phone }}<br></span>
|
||||
</div>
|
||||
<span v-else-if="config.style === 'float' && institution">
|
||||
{{ institution.name }}
|
||||
<span v-if="displayOptions.includes('street')">, Straße: {{ institution.street }}</span>
|
||||
<span v-if="displayOptions.includes('zipcode')">, Postleitzahl: {{ institution.zipcode }}</span>
|
||||
<span v-if="displayOptions.includes('city')">, Stadt: {{ institution.city }}</span>
|
||||
<span v-if="displayOptions.includes('email')">, E-Mail: {{ institution.email }}</span>
|
||||
<span v-if="displayOptions.includes('phone')">, Telefon: {{ institution.phone }}</span>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ config }}<br/>
|
||||
---
|
||||
{{ institution }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from '@/axios';
|
||||
|
||||
export default {
|
||||
name: 'InstitutionRender',
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
institution: null,
|
||||
loading: true,
|
||||
error: null,
|
||||
displayOptions: [],
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
try {
|
||||
this.displayOptions = this.config.display || [];
|
||||
const response = await axios.get('/institutions/' + this.config.id, {
|
||||
config: JSON.stringify(this.config),
|
||||
});
|
||||
this.institution = response.data;
|
||||
this.loading = false;
|
||||
} catch (error) {
|
||||
console.error('Error loading institutions:', error);
|
||||
this.error = 'Fehler beim Laden der Institutionen';
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Add styles if needed */
|
||||
</style>
|
||||
|
||||
@@ -7,7 +7,9 @@ import { createApp, h, ref, watch } from 'vue';
|
||||
import WorshipRender from './WorshipRender.vue';
|
||||
import ImageRender from './ImageRender.vue';
|
||||
import EventRender from './EventRender.vue';
|
||||
import ContactRender from './ContactRender.vue'; // Neue Komponente importieren
|
||||
import ContactRender from './ContactRender.vue'; // Importiere die neue Komponente
|
||||
import InstitutionRender from './InstitutionRender.vue'; // Importiere die neue Komponente
|
||||
import DownloadLink from './DownloadLink.vue';
|
||||
|
||||
export default {
|
||||
name: 'RenderContentComponent',
|
||||
@@ -23,8 +25,10 @@ export default {
|
||||
const renderContent = (content) => {
|
||||
let result = renderWorship(content);
|
||||
result = renderImage(result);
|
||||
result = renderDownload(result);
|
||||
result = renderEvent(result);
|
||||
result = renderContact(result); // Neuer Filter
|
||||
result = renderContact(result);
|
||||
result = renderInstitution(result);
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -32,14 +36,13 @@ export default {
|
||||
const worshipsPattern = /{{ worshipslist:(.*?) }}/g;
|
||||
let result = content;
|
||||
result = result.replace(worshipsPattern, (match, config) => {
|
||||
const props = parseConfig(config);
|
||||
const placeholderId = `worship-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
|
||||
setTimeout(() => {
|
||||
const placeholder = document.getElementById(placeholderId);
|
||||
if (placeholder) {
|
||||
const app = createApp({
|
||||
render() {
|
||||
return h(WorshipRender, props);
|
||||
return h(WorshipRender, {config: JSON.parse(config) });
|
||||
},
|
||||
});
|
||||
app.mount(placeholder);
|
||||
@@ -71,18 +74,39 @@ export default {
|
||||
return result;
|
||||
};
|
||||
|
||||
const renderDownload = (content) => {
|
||||
const downloadPattern = /{{ download:(.*?) }}/g;
|
||||
let result = content;
|
||||
result = result.replace(downloadPattern, (match, config) => {
|
||||
const placeholderId = `image-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
|
||||
setTimeout(() => {
|
||||
const placeholder = document.getElementById(placeholderId);
|
||||
if (placeholder) {
|
||||
const app = createApp({
|
||||
render() {
|
||||
return h(DownloadLink, { hash: config });
|
||||
},
|
||||
});
|
||||
app.mount(placeholder);
|
||||
}
|
||||
}, 0);
|
||||
return `<span id="${placeholderId}"></span>`;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const renderEvent = (content) => {
|
||||
const eventsPattern = /{{ events:(.*?) }}/g;
|
||||
let result = content;
|
||||
result = result.replace(eventsPattern, (match, config) => {
|
||||
const props = parseConfig(config);
|
||||
const placeholderId = `event-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
|
||||
setTimeout(() => {
|
||||
const placeholder = document.getElementById(placeholderId);
|
||||
if (placeholder) {
|
||||
const app = createApp({
|
||||
render() {
|
||||
return h(EventRender, { id: props.id, config: props });
|
||||
console.log('RC', config)
|
||||
return h(EventRender, {config: JSON.parse(config) });
|
||||
},
|
||||
});
|
||||
app.mount(placeholder);
|
||||
@@ -97,7 +121,7 @@ export default {
|
||||
const contactPattern = /{{ contact:(.*?) }}/g;
|
||||
let result = content;
|
||||
result = result.replace(contactPattern, (match, config) => {
|
||||
const props = JSON.parse(config);
|
||||
const props = parseConfig(config);
|
||||
const placeholderId = `contact-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
|
||||
setTimeout(() => {
|
||||
const placeholder = document.getElementById(placeholderId);
|
||||
@@ -110,22 +134,42 @@ export default {
|
||||
app.mount(placeholder);
|
||||
}
|
||||
}, 0);
|
||||
const tag = props.style === 'box' ? 'div' : 'span'
|
||||
return `<${tag} id="${placeholderId}"></${tag}>`;
|
||||
return `<div id="${placeholderId}"></div>`;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const renderInstitution = (content) => {
|
||||
const institutionPattern = /{{ institution:(.*?) }}/g;
|
||||
let result = content;
|
||||
result = result.replace(institutionPattern, (match, config) => {
|
||||
const props = parseConfig(config);
|
||||
const placeholderId = `institution-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
|
||||
setTimeout(() => {
|
||||
const placeholder = document.getElementById(placeholderId);
|
||||
if (placeholder) {
|
||||
const app = createApp({
|
||||
render() {
|
||||
return h(InstitutionRender, { config: props });
|
||||
},
|
||||
});
|
||||
app.mount(placeholder);
|
||||
}
|
||||
}, 0);
|
||||
return `<div id="${placeholderId}"></div>`;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const parseConfig = (configString) => {
|
||||
const config = {};
|
||||
const configArray = configString.split(',');
|
||||
configArray.forEach((item) => {
|
||||
const [key, value] = item.split('=');
|
||||
if (key && value !== undefined) {
|
||||
config[key.trim()] = isNaN(value) ? value.trim() : Number(value);
|
||||
}
|
||||
});
|
||||
return config;
|
||||
try {
|
||||
const config = JSON.parse(configString);
|
||||
return config;
|
||||
} catch (error) {
|
||||
console.error('Error parsing config:', error);
|
||||
console.log(configString);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
|
||||
@@ -66,7 +66,7 @@ export default {
|
||||
};
|
||||
|
||||
const confirmWorshipConfiguration = () => {
|
||||
const selectedLocationIds = selectedLocations.value.map(location => location.id).join('|');
|
||||
const selectedLocationIds = JSON.stringify(selectedLocations.value.map(location => location.id));
|
||||
emit('confirm', selectedLocationIds);
|
||||
closeWorshipDialog();
|
||||
};
|
||||
|
||||
@@ -32,14 +32,10 @@ import { formatTime, formatDate } from '@/utils/strings';
|
||||
export default {
|
||||
name: 'WorshipRender',
|
||||
props: {
|
||||
location: {
|
||||
type: Number,
|
||||
config: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
orderBy: {
|
||||
type: String,
|
||||
default: 'date ASC'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -55,10 +51,7 @@ export default {
|
||||
async fetchWorships() {
|
||||
try {
|
||||
const response = await axios.get('/worships/filtered', {
|
||||
params: {
|
||||
location: this.location,
|
||||
orderBy: this.orderBy
|
||||
}
|
||||
params: this.config
|
||||
});
|
||||
this.worships = response.data;
|
||||
} catch (error) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { menuData } from '../../config/menuData';
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'ImageContent',
|
||||
@@ -15,6 +15,9 @@ export default {
|
||||
currentImage: '/images/homepage1.png'
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(['menuData']),
|
||||
},
|
||||
watch: {
|
||||
$route: {
|
||||
immediate: true,
|
||||
@@ -26,6 +29,7 @@ export default {
|
||||
methods: {
|
||||
updateImage() {
|
||||
const routePath = this.$route.path;
|
||||
const menuData = this.menuData;
|
||||
const menuItem = this.findMenuItemByPath(menuData, routePath);
|
||||
if (menuItem && menuItem.image) {
|
||||
this.currentImage = `/images/${menuItem.image}`;
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<div class="additional-toolbar">
|
||||
<button @click="openAddEventsDialog">Events</button>
|
||||
<button @click="openAddContactDialog">Kontaktpersonen</button>
|
||||
<button>Institutionen</button>
|
||||
<button @click="openAddInstitutionDialog">Institutionen</button>
|
||||
<button @click="openWorshipDialog">Gottesdienste</button>
|
||||
</div>
|
||||
<div :class="['htmleditor']">
|
||||
@@ -90,7 +90,7 @@
|
||||
<AddEventDialog ref="addEventDialog" @confirm="insertEvent" />
|
||||
<AddLinkDialog ref="addLinkDialog" @confirm="insertLink" />
|
||||
<AddDownloadDialog ref="addDownloadDialog" @confirm="insertDownload" />
|
||||
<AddContactDialog ref="addContactDialog" @confirm="insertContact" />
|
||||
<AddInstitutionDialog ref="addInstitutionDialog" @confirm="insertInstitution" />
|
||||
<input type="color" ref="colorPicker" @input="setColor" style="display: none;" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -119,8 +119,7 @@ import AddImageDialog from '@/components/AddImageDialog.vue';
|
||||
import AddEventDialog from '@/components/AddEventDialog.vue';
|
||||
import AddLinkDialog from '@/components/AddLinkDialog.vue';
|
||||
import AddDownloadDialog from '@/components/AddDownloadDialog.vue';
|
||||
import AddContactDialog from '@/components/AddContactDialog.vue';
|
||||
|
||||
import AddInstitutionDialog from '@/components/AddInstitutionDialog.vue';
|
||||
import { BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, ListIcon, NumberedListLeftIcon, TableIcon,
|
||||
Table2ColumnsIcon, ArrowDownIcon, ArrowRightIcon, TableRowsIcon, AlignTopBoxIcon, AlignLeftBoxIcon, StatsReportIcon,
|
||||
OpenInWindowIcon, DownloadIcon
|
||||
@@ -149,7 +148,7 @@ export default {
|
||||
AddEventDialog,
|
||||
AddLinkDialog,
|
||||
AddDownloadDialog,
|
||||
AddContactDialog,
|
||||
AddInstitutionDialog,
|
||||
OpenInWindowIcon,
|
||||
DownloadIcon,
|
||||
},
|
||||
@@ -163,7 +162,7 @@ export default {
|
||||
const addEventDialog = ref(null);
|
||||
const addLinkDialog = ref(null);
|
||||
const addDownloadDialog = ref(null);
|
||||
const addContactDialog = ref(null);
|
||||
const addInstitutionDialog = ref(null);
|
||||
const colorPicker = ref(null);
|
||||
|
||||
const editor = useEditor({
|
||||
@@ -280,8 +279,11 @@ export default {
|
||||
|
||||
const insertWorshipList = (selectedLocations) => {
|
||||
if (editor.value) {
|
||||
const configuration = `location=${selectedLocations},order:"date asc"`;
|
||||
editor.value.chain().focus().insertContent(`{{ worshipslist:${configuration} }}`).run();
|
||||
const configuration = {
|
||||
location: selectedLocations,
|
||||
order: "date asc",
|
||||
}
|
||||
editor.value.chain().focus().insertContent('{{ worshipslist:' + JSON.stringify(configuration) + ' }}').run();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -315,18 +317,18 @@ export default {
|
||||
addDownloadDialog.value.openAddDownloadDialog();
|
||||
};
|
||||
|
||||
const insertDownload = ({ title, hash, extension }) => {
|
||||
if (title && hash && extension && editor.value) {
|
||||
const url = `/files/download/${hash}`;
|
||||
editor.value.chain().focus().extendMarkRange('link').setLink({ href: url }).insertContent(title).run();
|
||||
const insertDownload = ({ hash }) => {
|
||||
if (hash && editor.value) {
|
||||
const downloadString = '{{ download:' + hash + ' }}'
|
||||
editor.value.chain().focus().insertContent(downloadString).run();
|
||||
}
|
||||
};
|
||||
|
||||
const openAddContactDialog = () => {
|
||||
addContactDialog.value.openAddContactDialog();
|
||||
const openAddInstitutionDialog = () => {
|
||||
addInstitutionDialog.value.openAddInstitutionDialog();
|
||||
};
|
||||
|
||||
const insertContact = (configString) => {
|
||||
const insertInstitution = (configString) => {
|
||||
if (editor.value) {
|
||||
editor.value.chain().focus().insertContent(configString).run();
|
||||
}
|
||||
@@ -375,38 +377,6 @@ export default {
|
||||
editor.value.chain().focus().toggleOrderedList().run();
|
||||
};
|
||||
|
||||
const addColumnBefore = () => {
|
||||
editor.value.chain().focus().addColumnBefore().run();
|
||||
};
|
||||
|
||||
const addColumnAfter = () => {
|
||||
editor.value.chain().focus().addColumnAfter().run();
|
||||
};
|
||||
|
||||
const addRowBefore = () => {
|
||||
editor.value.chain().focus().addRowBefore().run();
|
||||
};
|
||||
|
||||
const addRowAfter = () => {
|
||||
editor.value.chain().focus().addRowAfter().run();
|
||||
};
|
||||
|
||||
const deleteColumn = () => {
|
||||
editor.value.chain().focus().deleteColumn().run();
|
||||
};
|
||||
|
||||
const deleteRow = () => {
|
||||
editor.value.chain().focus().deleteRow().run();
|
||||
};
|
||||
|
||||
const toggleHeaderColumn = () => {
|
||||
editor.value.chain().focus().toggleHeaderColumn().run();
|
||||
};
|
||||
|
||||
const toggleHeaderRow = () => {
|
||||
editor.value.chain().focus().toggleHeaderRow().run();
|
||||
};
|
||||
|
||||
return {
|
||||
pages,
|
||||
sortedPages,
|
||||
@@ -430,9 +400,9 @@ export default {
|
||||
addDownloadDialog,
|
||||
openAddDownloadDialog,
|
||||
insertDownload,
|
||||
addContactDialog,
|
||||
openAddContactDialog,
|
||||
insertContact,
|
||||
addInstitutionDialog,
|
||||
openAddInstitutionDialog,
|
||||
insertInstitution,
|
||||
colorPicker,
|
||||
openColorPicker,
|
||||
setColor,
|
||||
@@ -444,14 +414,6 @@ export default {
|
||||
insertTable,
|
||||
toggleBulletList,
|
||||
toggleOrderedList,
|
||||
addColumnBefore,
|
||||
addColumnAfter,
|
||||
addRowBefore,
|
||||
addRowAfter,
|
||||
deleteColumn,
|
||||
deleteRow,
|
||||
toggleHeaderColumn,
|
||||
toggleHeaderRow,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
11
src/content/meetingpoint/ChildrensChurchContent.vue
Normal file
11
src/content/meetingpoint/ChildrensChurchContent.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>Kindergottesdiest</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ChildrensWorshipContent',
|
||||
};
|
||||
</script>
|
||||
11
src/content/music/FlootChildrenContent.vue
Normal file
11
src/content/music/FlootChildrenContent.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>Flötenkinder</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FlootChildrenContent',
|
||||
};
|
||||
</script>
|
||||
@@ -35,6 +35,7 @@ function buildMenuStructure(menuItems) {
|
||||
requiresAuth: item.requires_auth,
|
||||
order_id: item.order_id,
|
||||
pageTitle: item.page_title,
|
||||
image: item.image,
|
||||
submenu: []
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user