Added rendering of Event Images
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,3 +26,4 @@ node_modules
|
|||||||
server.key
|
server.key
|
||||||
server.cert
|
server.cert
|
||||||
|
|
||||||
|
public/images/uploads/1ba24ea7-f52c-4179-896f-1909269cab58.jpg
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const filterEvents = async (req, res) => {
|
|||||||
{ model: Institution, as: 'institution' },
|
{ model: Institution, as: 'institution' },
|
||||||
{ model: EventPlace, as: 'eventPlace' },
|
{ model: EventPlace, as: 'eventPlace' },
|
||||||
{ model: EventType, as: 'eventType' },
|
{ model: EventType, as: 'eventType' },
|
||||||
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } }
|
{ model: ContactPerson, as: 'contactPersons', through: { attributes: [] } },
|
||||||
],
|
],
|
||||||
order: ['name', 'date', 'time']
|
order: ['name', 'date', 'time']
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ module.exports = (sequelize) => {
|
|||||||
alsoOnHomepage: {
|
alsoOnHomepage: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
|
},
|
||||||
|
relatedImage: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
tableName: 'events',
|
tableName: 'events',
|
||||||
@@ -66,6 +70,10 @@ module.exports = (sequelize) => {
|
|||||||
otherKey: 'contact_person_id',
|
otherKey: 'contact_person_id',
|
||||||
as: 'contactPersons'
|
as: 'contactPersons'
|
||||||
});
|
});
|
||||||
|
Event.belongsTo(models.Image, {
|
||||||
|
foreignKey: 'relatedImage',
|
||||||
|
as: 'relatedImageAssociation'
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
return Event;
|
return Event;
|
||||||
|
|||||||
@@ -94,6 +94,13 @@
|
|||||||
></multiselect>
|
></multiselect>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><label><input type="checkbox" v-model="onHomepage">Auf der Startseite anzeigen</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Zugewiesenes Bild:</td>
|
||||||
|
<td><img v-if="assignedImage != null" :src="getImagePath" /><button @click="removeImage">Bild entfernen</button></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><button type="submit">Speichern</button></td>
|
<td colspan="2"><button type="submit">Speichern</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -3,24 +3,33 @@
|
|||||||
<table v-if="events.length > 1" class="event-table">
|
<table v-if="events.length > 1" class="event-table">
|
||||||
<tr v-for="event in events" :key="event.id">
|
<tr v-for="event in events" :key="event.id">
|
||||||
<td>
|
<td>
|
||||||
|
<div v-if="hasImage(event)" class="event-image"><img v-if="imageMap[event.relatedImage]"
|
||||||
|
:src="imageMap[event.relatedImage]" /></div>
|
||||||
<div v-if="shouldDisplay('name')" class="event-name">{{ event.name }}</div>
|
<div v-if="shouldDisplay('name')" class="event-name">{{ event.name }}</div>
|
||||||
<div>{{ formatDateOrDay(event.date, event.dayOfWeek) }}</div>
|
<div>{{ formatDateOrDay(event.date, event.dayOfWeek) }}</div>
|
||||||
<div v-if="shouldDisplay('time')">{{ formatTime(event.time) }} <span v-if="event.endTime"> - {{ formatTime(event.endTime) }}</span> Uhr</div>
|
<div v-if="shouldDisplay('time')">{{ formatTime(event.time) }} <span v-if="event.endTime"> - {{
|
||||||
|
formatTime(event.endTime) }}</span> Uhr</div>
|
||||||
<div v-if="shouldDisplay('place')">{{ event.eventPlace?.name }}</div>
|
<div v-if="shouldDisplay('place')">{{ event.eventPlace?.name }}</div>
|
||||||
<div v-if="shouldDisplay('description')" class="description">{{ event.description }}</div>
|
<div v-if="shouldDisplay('description')" class="description">{{ event.description }}</div>
|
||||||
<div v-if="shouldDisplay('contactPerson')">{{ event.contactPersons.map(cp => cp.name).join(', ') }}</div>
|
<div v-if="shouldDisplay('contactPerson')">{{event.contactPersons.map(cp => cp.name).join(', ')}}
|
||||||
|
</div>
|
||||||
<div v-if="shouldDisplay('institution')">{{ event.institution?.name }}</div>
|
<div v-if="shouldDisplay('institution')">{{ event.institution?.name }}</div>
|
||||||
<div v-if="shouldDisplay('type')">{{ event.eventType?.caption }}</div>
|
<div v-if="shouldDisplay('type')">{{ event.eventType?.caption }}</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<div v-else-if="events.length === 1" :class="events[0].alsoOnHomepage && config.id === 'home' ? 'homepage' : ''">
|
<div v-else-if="events.length === 1"
|
||||||
|
:class="events[0].alsoOnHomepage && config.id === 'home' ? 'homepage' : ''">
|
||||||
|
<div v-if="hasImage(events[0])" class="event-image"><img v-if="imageMap[events[0].relatedImage]"
|
||||||
|
:src="imageMap[events[0].relatedImage]" /></div>
|
||||||
<div v-if="shouldDisplay('name')" class="event-name">{{ events[0].name }}</div>
|
<div v-if="shouldDisplay('name')" class="event-name">{{ events[0].name }}</div>
|
||||||
<div>{{ formatDateOrDay(events[0].date, events[0].dayOfWeek) }}</div>
|
<div>{{ formatDateOrDay(events[0].date, events[0].dayOfWeek) }}</div>
|
||||||
<div v-if="shouldDisplay('time')">{{ formatTime(events[0].time) }} <span v-if="events[0].endTime"> - {{ formatTime(events[0].endTime) }}</span> Uhr</div>
|
<div v-if="shouldDisplay('time')">{{ formatTime(events[0].time) }} <span v-if="events[0].endTime"> - {{
|
||||||
|
formatTime(events[0].endTime) }}</span> Uhr</div>
|
||||||
<div v-if="shouldDisplay('place')">{{ events[0].eventPlace?.name }}</div>
|
<div v-if="shouldDisplay('place')">{{ events[0].eventPlace?.name }}</div>
|
||||||
<div v-if="shouldDisplay('description')" class="description">{{ events[0].description }}</div>
|
<div v-if="shouldDisplay('description')" class="description">{{ events[0].description }}</div>
|
||||||
<div v-if="shouldDisplay('contactPerson')">{{ events[0].contactPersons.map(cp => cp.name).join(', ') }}</div>
|
<div v-if="shouldDisplay('contactPerson')">{{events[0].contactPersons.map(cp => cp.name).join(', ')}}
|
||||||
|
</div>
|
||||||
<div v-if="shouldDisplay('institution')">{{ events[0].institution?.name }}</div>
|
<div v-if="shouldDisplay('institution')">{{ events[0].institution?.name }}</div>
|
||||||
<div v-if="shouldDisplay('type')">{{ events[0].eventType?.caption }}</div>
|
<div v-if="shouldDisplay('type')">{{ events[0].eventType?.caption }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,7 +38,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from '@/axios';
|
import axios from '@/axios';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { formatTime } from '@/utils/strings';
|
import { formatTime } from '@/utils/strings';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -43,6 +52,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
events: [],
|
events: [],
|
||||||
|
imageMap: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
@@ -52,10 +62,22 @@ export default {
|
|||||||
formatTime,
|
formatTime,
|
||||||
async fetchEvents() {
|
async fetchEvents() {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post('/events/filter',
|
const response = await axios.post('/events/filter',
|
||||||
this.config
|
this.config
|
||||||
);
|
);
|
||||||
this.events = response.data.events;
|
this.events = response.data.events;
|
||||||
|
await Promise.all(
|
||||||
|
this.events
|
||||||
|
.filter(event => this.hasImage(event))
|
||||||
|
.map(async event => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('/image/' + event.relatedImage);
|
||||||
|
this.imageMap[event.relatedImage] = '/images/uploads/' + response.data.filename;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Bild konnte nicht geladen werden (ID ${event.relatedImage}):`, err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Fehler beim Abrufen der Events', error);
|
console.error('Fehler beim Abrufen der Events', error);
|
||||||
}
|
}
|
||||||
@@ -71,6 +93,15 @@ export default {
|
|||||||
return daysOfWeek[dayOfWeek];
|
return daysOfWeek[dayOfWeek];
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
},
|
||||||
|
hasImage(event) {
|
||||||
|
return event.relatedImage && event.relatedImage != '';
|
||||||
|
},
|
||||||
|
async imagePath(eventImage) {
|
||||||
|
const response = await axios.get('/image/' + eventImage);
|
||||||
|
const path = '/images/uploads/' + response.data.filename;
|
||||||
|
console.log(path);
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -80,18 +111,27 @@ export default {
|
|||||||
.event-name {
|
.event-name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-table {
|
.event-table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-table td {
|
.event-table td {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homepage {
|
.homepage {
|
||||||
border: 1px solid #9400ff;
|
border: 1px solid #9400ff;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.description {
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.event-image > img {
|
||||||
|
max-width: 8em;
|
||||||
|
max-height: 8em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ module.exports = defineConfig({
|
|||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': JSON.stringify(process.env)
|
'process.env.CUSTOM_VAR': JSON.stringify(process.env.CUSTOM_VAR)
|
||||||
}),
|
})
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user