Some fixes, added Events in edit

This commit is contained in:
Torsten Schulz
2024-06-22 17:56:26 +02:00
parent 97c72540cf
commit 692e989861
11 changed files with 450 additions and 17 deletions

View File

@@ -0,0 +1,224 @@
<template>
<div>
<div v-if="isOpen" class="dialog-overlay">
<div class="dialog-content">
<h3>Kontaktperson hinzufügen</h3>
<div>
<label for="type-select">Typen:</label>
<multiselect id="type-select" v-model="selectedTypes" :options="typeOptions" :multiple="true"
label="caption" track-by="id" @select="onTypeSelect" />
</div>
<div v-if="selectedTypes.some(type => type.id === 'places')">
<label for="places-select">Wählen Sie Orte:</label>
<multiselect id="places-select" v-model="selectedPlaces" :options="places" :multiple="true"
label="name" track-by="id" />
</div>
<div v-if="selectedTypes.some(type => type.id === 'types')">
<label for="types-select">Wählen Sie Typen:</label>
<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 === 'specific')">
<label for="contact-select">Wählen Sie eine Kontaktperson:</label>
<multiselect id="contact-select" v-model="selectedContact" :options="contacts" :multiple="false"
label="name" track-by="id" />
</div>
<div>
<label>Wählen Sie welche Elemente angezeigt werden sollen:</label>
<div class="display-options">
<label><input type="checkbox" v-model="displayOptions.phone" /> Telefon</label>
<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.email" /> E-Mail</label>
<label><input type="checkbox" v-model="displayOptions.positions" /> Positionen</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="confirmAddContactConfiguration">Bestätigen</button>
<button @click="closeAddContactDialog">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: 'AddContactDialog',
components: {
Multiselect,
},
emits: ['confirm'],
setup(props, { emit }) {
const isOpen = ref(false);
const contacts = ref([]);
const eventTypes = ref([]);
const places = ref([]);
const selectedContact = ref(null);
const selectedTypes = ref([]);
const selectedEventTypes = ref([]);
const selectedPlaces = ref([]);
const displayStyle = ref('float');
const displayOptions = ref({
phone: false,
street: false,
zipcode: false,
city: false,
email: false,
positions: false,
});
const typeOptions = ref([
{ id: 'all', caption: 'Alle' },
{ id: 'specific', caption: 'Eine Person' },
{ id: 'places', caption: 'Für bestimmte Orte' },
{ id: 'types', caption: 'Für bestimmte Typen' },
]);
const displayStyles = ref([
{ id: 'float', label: 'Durchlaufender Text' },
{ id: 'box', label: 'Textbox' },
]);
const openAddContactDialog = () => {
isOpen.value = true;
fetchContacts();
fetchEventTypes();
fetchPlaces();
};
const closeAddContactDialog = () => {
isOpen.value = false;
};
const onTypeSelect = () => {
if (selectedTypes.value.some(type => type.id === 'all')) {
selectedTypes.value = [{ id: 'all', caption: 'Alle' }];
selectedContact.value = null;
selectedEventTypes.value = [];
selectedPlaces.value = [];
} else if (selectedTypes.value.some(type => type.id === 'specific')) {
selectedTypes.value = [{ id: 'specific', caption: 'Eine Person' }];
selectedEventTypes.value = [];
selectedPlaces.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 = [];
}
};
const confirmAddContactConfiguration = () => {
let configString = '';
const displayArray = Object.keys(displayOptions.value).filter((key) => displayOptions.value[key]);
let selection = {};
if (selectedTypes.value.some(type => type.id === 'all')) {
selection['id'] = 'all';
} 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('|');
}
const contact = {
selection: selection,
display: displayArray,
style: displayStyle.value
}
configString = '{{ contact:' + JSON.stringify(contact) + ' }}';
emit('confirm', configString);
closeAddContactDialog();
};
const fetchContacts = async () => {
try {
const response = await axios.get('/contact-persons');
contacts.value = response.data;
} catch (error) {
console.error('Fehler beim Laden der Kontaktpersonen:', error);
}
};
const fetchEventTypes = async () => {
try {
const response = await axios.get('/event-types');
eventTypes.value = response.data;
} catch (error) {
console.error('Fehler beim Laden der Event-Typen:', error);
}
};
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);
}
};
return {
isOpen,
contacts,
selectedContact,
selectedTypes,
selectedEventTypes,
selectedPlaces,
displayOptions,
displayStyle,
displayStyles,
typeOptions,
openAddContactDialog,
closeAddContactDialog,
confirmAddContactConfiguration,
onTypeSelect,
places,
eventTypes,
};
},
};
</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>

View File

@@ -0,0 +1,70 @@
<template>
<div v-if="config && config.style === 'box' && contacts && contacts.length && contacts.length > 0">
<div v-for="contact in contacts" :key="contact.id">
<h3>{{ contact.name }}</h3>
<p v-if="displayOptions.includes('phone')">Telefon: {{ contact.phone }}</p>
<p v-if="displayOptions.includes('street')">Straße: {{ contact.street }}</p>
<p v-if="displayOptions.includes('zipcode')">Postleitzahl: {{ contact.zipcode }}</p>
<p v-if="displayOptions.includes('city')">Stadt: {{ contact.city }}</p>
<p v-if="displayOptions.includes('email')">E-Mail: {{ contact.email }}</p>
<p v-if="displayOptions.includes('positions')">Positionen: {{ contact.positions.map(pos =>
pos.caption).join(', ') }}</p>
</div>
</div>
<span v-else-if="config.style === 'float' && contacts && contacts.length && contacts.length > 0">
<span v-for="contact in contacts" :key="contact.id">
{{ contact.name }}
<span v-if="displayOptions.includes('phone')">, Telefon: {{ contact.phone }}</span>
<span v-if="displayOptions.includes('street')">, Straße: {{ contact.street }}</span>
<span v-if="displayOptions.includes('zipcode')">, Postleitzahl: {{ contact.zipcode }}</span>
<span v-if="displayOptions.includes('city')">, Stadt: {{ contact.city }}</span>
<span v-if="displayOptions.includes('email')">, E-Mail: {{ contact.email }}</span>
<span v-if="displayOptions.includes('positions')">, Positionen: {{ contact.positions.map(pos =>
pos.caption).join(', ') }}</span>
</span>
</span>
</template>
<script>
import axios from '@/axios';
export default {
name: 'ContactRender',
props: {
config: {
type: Object,
required: true,
},
},
data() {
return {
contacts: [],
loading: true,
error: null,
displayOptions: [],
};
},
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);
this.error = 'Fehler beim Laden der Kontaktpersonen';
this.loading = false;
}
},
};
</script>
<style scoped>
/* Add styles if needed */
</style>

View File

@@ -193,7 +193,7 @@ export default {
event_place_id: this.selectedEventPlace ? this.selectedEventPlace.id : null,
contactPersonIds: this.selectedContactPersons.map(person => person.id)
};
payload.dayOfWeek = payload.dayOfWeek.value;
payload.dayOfWeek = payload.dayOfWeek ? payload.dayOfWeek.value ?? -1 : -1;
let response;
if (this.eventData.id) {
response = await axios.put(`/events/${this.eventData.id}`, payload);

View File

@@ -7,7 +7,7 @@ import { createApp, h, ref, watch } from 'vue';
import WorshipRender from './WorshipRender.vue';
import ImageRender from './ImageRender.vue';
import EventRender from './EventRender.vue';
import DownloadLink from './DownloadLink.vue';
import ContactRender from './ContactRender.vue'; // Neue Komponente importieren
export default {
name: 'RenderContentComponent',
@@ -24,7 +24,7 @@ export default {
let result = renderWorship(content);
result = renderImage(result);
result = renderEvent(result);
result = renderDownload(result);
result = renderContact(result); // Neuer Filter
return result;
};
@@ -93,23 +93,25 @@ export default {
return result;
};
const renderDownload = (content) => {
const downloadPattern = /{{ download title="(.*?)" hash="(.*?)" extension="(.*?)" }}/g;
const renderContact = (content) => {
const contactPattern = /{{ contact:(.*?) }}/g;
let result = content;
result = result.replace(downloadPattern, (match, title, hash, extension) => {
const placeholderId = `download-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
result = result.replace(contactPattern, (match, config) => {
const props = JSON.parse(config);
const placeholderId = `contact-render-placeholder-${Math.random().toString(36).substr(2, 9)}`;
setTimeout(() => {
const placeholder = document.getElementById(placeholderId);
if (placeholder) {
const app = createApp({
render() {
return h(DownloadLink, { title, hash, extension });
return h(ContactRender, { config: props });
},
});
app.mount(placeholder);
}
}, 0);
return `<div id="${placeholderId}"></div>`;
const tag = props.style === 'box' ? 'div' : 'span'
return `<${tag} id="${placeholderId}"></${tag}>`;
});
return result;
};