forked from potsda.mn/mobilizon
Fix Calendar View style and add features
- create ICSCalendar component - create ICSAgenda component (for mobile view) - temporary add rotes.potsda.mn ics feed for testing
This commit is contained in:
parent
69717f26f3
commit
4ceee2efc7
137
src/components/FullCalendar/ICSAgenda.vue
Normal file
137
src/components/FullCalendar/ICSAgenda.vue
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
<template>
|
||||||
|
<FullCalendar :options="calendarOptions" class="agenda-view" />
|
||||||
|
|
||||||
|
<div v-if="listOfEventsByDate.date" class="my-4">
|
||||||
|
<b v-text="formatDateString(listOfEventsByDate.date)" />
|
||||||
|
|
||||||
|
<div v-for="(event, index) in listOfEventsByDate.events" v-bind:key="index">
|
||||||
|
<a :href="event.event.url">
|
||||||
|
<div
|
||||||
|
class="text-violet-3 dark:text-white bg-mbz-yellow dark:bg-mbz-purple my-2 p-2 rounded"
|
||||||
|
>
|
||||||
|
<div class="mb-1">
|
||||||
|
<Clock class="clock-icon" />
|
||||||
|
<b class="ml-1 time">
|
||||||
|
{{ formatTimeString(event.event.startStr, undefined) }}
|
||||||
|
{{
|
||||||
|
event.event.endStr
|
||||||
|
? "- " + formatTimeString(event.event.endStr, undefined)
|
||||||
|
: ""
|
||||||
|
}}
|
||||||
|
</b>
|
||||||
|
</div>
|
||||||
|
<span class="font-bold line-clamp-4">
|
||||||
|
{{ event.event.title }}
|
||||||
|
</span>
|
||||||
|
<div class="mt-1">
|
||||||
|
<small>
|
||||||
|
{{
|
||||||
|
t("Organized by {name}", {
|
||||||
|
name: event.event.extendedProps.organizer,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { locale } from "@/utils/i18n";
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import Clock from "vue-material-design-icons/ClockTimeTenOutline.vue";
|
||||||
|
import FullCalendar from "@fullcalendar/vue3";
|
||||||
|
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||||
|
import iCalendarPlugin from "@fullcalendar/icalendar";
|
||||||
|
import interactionPlugin from "@fullcalendar/interaction";
|
||||||
|
import { formatDateString, formatTimeString } from "@/filters/datetime";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
icsFeedUrl: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { t } = useI18n({ useScope: "global" });
|
||||||
|
|
||||||
|
const listOfEventsByDate = ref<{ events: object[]; date?: string }>({
|
||||||
|
events: [],
|
||||||
|
date: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const calendarOptions = computed((): object => {
|
||||||
|
return {
|
||||||
|
plugins: [dayGridPlugin, iCalendarPlugin, interactionPlugin],
|
||||||
|
initialView: "dayGridMonth",
|
||||||
|
events: {
|
||||||
|
url: props.icsFeedUrl,
|
||||||
|
format: "ics",
|
||||||
|
},
|
||||||
|
nextDayThreshold: "09:00:00",
|
||||||
|
dayMaxEventRows: 0,
|
||||||
|
moreLinkClassNames: "bg-mbz-yellow dark:bg-mbz-purple dark:text-white p-2",
|
||||||
|
moreLinkContent: (arg: { num: number; text: string }) => {
|
||||||
|
return "+" + arg.num.toString();
|
||||||
|
},
|
||||||
|
moreLinkClick: (info: {
|
||||||
|
date: Date;
|
||||||
|
allSegs: object[];
|
||||||
|
hiddenSegs: [];
|
||||||
|
jsEvent: object;
|
||||||
|
}) => {
|
||||||
|
listOfEventsByDate.value = {
|
||||||
|
events: info.allSegs,
|
||||||
|
date: info.date.toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return "none";
|
||||||
|
},
|
||||||
|
dateClick: (info: { dateStr: string }) => {
|
||||||
|
const moreLinkElement = document.querySelectorAll(
|
||||||
|
`td[data-date='${info.dateStr}'] a.fc-more-link`
|
||||||
|
)[0] as undefined | HTMLElement;
|
||||||
|
moreLinkElement?.click();
|
||||||
|
},
|
||||||
|
contentHeight: 350,
|
||||||
|
eventClassNames: "line-clamp-3 bg-mbz-yellow dark:bg-mbz-purple",
|
||||||
|
headerToolbar: {
|
||||||
|
left: "prev,next,today",
|
||||||
|
center: "",
|
||||||
|
right: "title",
|
||||||
|
},
|
||||||
|
locale: locale,
|
||||||
|
firstDay: 1,
|
||||||
|
buttonText: {
|
||||||
|
today: t("Today"),
|
||||||
|
month: t("Month"),
|
||||||
|
week: t("Week"),
|
||||||
|
day: t("Day"),
|
||||||
|
list: t("List"),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.agenda-view .fc-button {
|
||||||
|
font-size: 0.8rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agenda-view .fc-toolbar-title {
|
||||||
|
font-size: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agenda-view .fc-daygrid-day-events {
|
||||||
|
min-height: 1.1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clock-icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 0.95rem !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -31,6 +31,11 @@ const calendarOptions = computed((): object => {
|
||||||
url: props.icsFeedUrl,
|
url: props.icsFeedUrl,
|
||||||
format: "ics",
|
format: "ics",
|
||||||
},
|
},
|
||||||
|
nextDayThreshold: "09:00:00",
|
||||||
|
moreLinkClassNames: "bg-mbz-yellow dark:bg-mbz-purple dark:text-white p-2",
|
||||||
|
moreLinkContent: (arg: { num: number; text: string }) => {
|
||||||
|
return "+" + arg.num.toString();
|
||||||
|
},
|
||||||
eventClassNames: "line-clamp-3 bg-mbz-yellow dark:bg-mbz-purple",
|
eventClassNames: "line-clamp-3 bg-mbz-yellow dark:bg-mbz-purple",
|
||||||
headerToolbar: {
|
headerToolbar: {
|
||||||
left: "prev,next,today",
|
left: "prev,next,today",
|
|
@ -1,17 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container mx-auto px-1 mb-6">
|
<div class="container mx-auto px-1 mb-6">
|
||||||
<h1>
|
<h1 v-if="!isMobile">
|
||||||
{{ t("Calendar") }}
|
{{ t("Calendar") }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
<FullCalendar ics-feed-url="/feed/instance/ics" />
|
<ICSCalendar
|
||||||
|
v-if="!isMobile"
|
||||||
|
ics-feed-url="https://rotes.potsda.mn/feed/instance/ics"
|
||||||
|
/>
|
||||||
|
<ICSAgenda
|
||||||
|
v-else
|
||||||
|
ics-feed-url="https://rotes.potsda.mn/feed/instance/ics"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import FullCalendar from "@/components/FullCalendar.vue";
|
import ICSCalendar from "@/components/FullCalendar/ICSCalendar.vue";
|
||||||
|
import ICSAgenda from "@/components/FullCalendar/ICSAgenda.vue";
|
||||||
|
|
||||||
const { t } = useI18n({ useScope: "global" });
|
const { t } = useI18n({ useScope: "global" });
|
||||||
|
|
||||||
|
const isMobile = window.innerWidth < 760;
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue