Support basic formatting in the display of the description fields to locations, events and shifts by rendering them as Markdown using the micromark library.
107 lines
2.3 KiB
Vue
107 lines
2.3 KiB
Vue
<!--
|
||
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||
-->
|
||
<template>
|
||
<section class="eventSlot">
|
||
<hgroup>
|
||
<h3>{{ event?.name }}</h3>
|
||
<p>
|
||
{{ formatTime(slot.start) }} - {{ formatTime(slot.end) }}
|
||
</p>
|
||
</hgroup>
|
||
<p v-if=event?.host>
|
||
Host: {{ event.host }}
|
||
</p>
|
||
<div v-if="event?.notice" class="notice preWrap">
|
||
<div class="noticeIcon">
|
||
⚠️
|
||
</div>
|
||
<p>
|
||
{{ event.notice }}
|
||
</p>
|
||
</div>
|
||
<div
|
||
v-if="descriptionHtml !== undefined"
|
||
class="flow"
|
||
v-html="descriptionHtml"
|
||
/>
|
||
<p v-if="locations.length">
|
||
At {{ locations.map(location => location?.name ?? "unknown").join(" + ") }}
|
||
</p>
|
||
<p v-if="event?.interested">
|
||
{{ event?.interested }}
|
||
<template v-if="slot.interested">
|
||
+ {{ slot.interested }}
|
||
</template>
|
||
interested
|
||
</p>
|
||
<p v-if="slot.assigned.size">
|
||
Crew:
|
||
{{ [...slot.assigned].map(id => usersStore.users.get(id)?.name).join(", ") }}
|
||
</p>
|
||
</section>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { micromark } from 'micromark';
|
||
import { DateTime } from '~/shared/utils/luxon';
|
||
|
||
const props = defineProps<{
|
||
event?: ClientScheduleEvent,
|
||
slot: ClientScheduleEventSlot,
|
||
}>()
|
||
|
||
const descriptionHtml = computed(() => {
|
||
if (props.event?.description)
|
||
return micromark(props.event.description);
|
||
return undefined;
|
||
});
|
||
|
||
const scheduleStore = useSchedulesStore();
|
||
const schedule = scheduleStore.activeSchedule;
|
||
|
||
const usersStore = useUsersStore();
|
||
const locations = computed(() => [...props.slot.locationIds].map(id => schedule.value.locations.get(id)));
|
||
|
||
function formatTime(time: DateTime) {
|
||
return time.toFormat("yyyy-LL-dd HH:mm");
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.eventSlot {
|
||
background: color-mix(in oklab, var(--background), grey 20%);
|
||
padding: 0.5rem;
|
||
border-radius: 0.5rem;
|
||
}
|
||
.eventSlot h3 {
|
||
margin: 0;
|
||
}
|
||
.eventSlot + .eventSlot {
|
||
margin-block-start: 0.5rem;
|
||
}
|
||
|
||
.notice {
|
||
display: flex;
|
||
width: fit-content;
|
||
gap: 0.5rem;
|
||
padding: 0.5rem;
|
||
margin-block: 0.5rem;
|
||
border-radius: 0.25rem;
|
||
border: 1px solid color-mix(in oklab, CanvasText, orange 50%);
|
||
background-color: color-mix(in oklab, Canvas, orange 40%);
|
||
}
|
||
.noticeIcon {
|
||
flex: 0 0 auto;
|
||
align-self: center;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
button {
|
||
padding-inline: 0.2em;
|
||
}
|
||
button.active {
|
||
color: color-mix(in oklab, var(--foreground), green 50%);
|
||
}
|
||
</style>
|