Skip to content

Commit

Permalink
basic impementation of a calendar
Browse files Browse the repository at this point in the history
  • Loading branch information
CommanderStorm committed Jun 4, 2023
1 parent d00f2ae commit b67b4df
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 2 deletions.
3 changes: 2 additions & 1 deletion webclient/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"swagger-ui-dist": "^5.0.0-alpha.13",
"swaggerdark": "github:octycs/SwaggerDark#f02d394c8ff698cdd93e09c2188b058d2d686ca3",
"vue": "^3.2.45",
"vue-router": "^4.1.6"
"vue-router": "^4.1.6",
"vue-simple-calendar": "^6.3.1"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.11.0",
Expand Down
2 changes: 2 additions & 0 deletions webclient/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import AppSearchBar from "@/components/AppSearchBar.vue";
import CalendarModal from "@/components/CalendarModal.vue";
import AppLanguageToggler from "@/components/AppLanguageToggler.vue";
import AppThemeToggler from "@/components/AppThemeToggler.vue";
import { useGlobalStore } from "@/stores/global";
Expand Down Expand Up @@ -141,6 +142,7 @@ const global = useGlobalStore();
</div>
</footer>
<FeedbackModal v-if="global.feedback.open" />
<CalendarModal v-if="global.calendar.open" />
<!-- General message modal -->
<div class="modal active" v-if="global.information_modal?.body">
<a class="modal-overlay" :aria-label="$t('close')" @click="global.information_modal.body = null" />
Expand Down
116 changes: 116 additions & 0 deletions webclient/src/components/CalendarModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<script setup lang="ts">
import { CalendarView, CalendarViewHeader } from "vue-simple-calendar";
import { ref, computed, watch } from "vue";
import type { ICalendarItem } from "vue-simple-calendar/dist/src/ICalendarItem";
import { useGlobalStore } from "@/stores/global";
import { useRoute } from "vue-router";
import type { components } from "@/api_types";
type CalendarResponse = components["schemas"]["CalendarResponse"];
import "/node_modules/vue-simple-calendar/dist/style.css";
import "/node_modules/vue-simple-calendar/dist/css/default.css";
import { useFetch } from "@/composables/fetch";
const global = useGlobalStore();
const showDate = ref(new Date());
const tumonlineCalendarUrl = ref("https://campus.tum.de/tumonline");
const last_sync = ref("xx.xx.xxxx xx:xx");
const events = ref<ICalendarItem[]>([]);
const route = useRoute();
const start = computed(() => {
const start = new Date(showDate.value);
start.setDate(start.getDate() - 60);
return start.toISOString().replace("Z", "");
});
const end = computed(() => {
const start = new Date(showDate.value);
start.setDate(start.getDate() + 60);
return start.toISOString().replace("Z", "");
});
// called when the view is loaded
update();
// called when the view navigates to another view, but not when its initially loaded
watch(() => showDate.value, update);
watch(() => route.params.id, update);
function update() {
useFetch<CalendarResponse>(
`https://nav.tum.de/api/calendar/${route.params.id}?start=${start.value}&end=${end.value}`,
(d) => {
tumonlineCalendarUrl.value = d.calendar_url;
last_sync.value = new Date(d.last_sync).toLocaleString("de-DE", { timeStyle: "short", dateStyle: "short" });
events.value = d.events.map((e) => ({
id: e.id.toString(),
title: e.title,
startDate: new Date(e.start),
endDate: new Date(e.end),
classes: [e.entry_type],
}));
}
);
}
function setShowDate(d: Date) {
showDate.value = d;
}
</script>
<template>
<div class="modal modal-lg active" id="calendar-modal">
<a @click="global.calendar.open = false" class="modal-overlay" aria-label="Close"></a>
<div class="modal-container">
<div class="modal-header">
<a
@click="global.calendar.open = false"
class="btn btn-clear float-right"
v-bind:aria-label="$t('calendar.modal.close')"
></a>
<div class="modal-title h5">{{ $t("calendar.modal.title") }}</div>
</div>
<div class="modal-body">
<div class="modal-body">
<CalendarView
id="calendar-view"
:items="events"
:show-date="showDate"
:showTimes="true"
:timeFormatOptions="{ hour: '2-digit', minute: '2-digit' }"
:startingDayOfWeek="1"
class="theme-default"
>
<template #header="{ headerProps }">
<CalendarViewHeader :header-props="headerProps" @input="setShowDate" />
</template>
</CalendarView>
</div>
</div>
<div class="modal-footer">
{{ $t("calendar.modal.footer.disclaimer") }} <br />
{{ $t("calendar.modal.footer.please_check") }}
<a v-bind:href="tumonlineCalendarUrl">{{ $t("calendar.modal.footer.official_calendar") }}</a
>. {{ $t("calendar.modal.footer.last_sync") }}: {{ last_sync }}
</div>
</div>
</div>
</template>
<style lang="scss">
#calendar-modal {
.modal-container {
position: relative;
height: auto;
max-width: 97.5vw;
max-height: 90vh;
.modal-body {
padding: 0;
height: 40rem;
#calendar-view {
display: flex;
flex-direction: column;
flex-grow: 1;
}
}
}
}
</style>
9 changes: 9 additions & 0 deletions webclient/src/locales/de.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
calendar:
modal:
title: Kalendar
close: Schließen
footer:
disclaimer: Veranstaltungen werden täglich aktualisiert und identische Termine zusammengefasst.
please_check: Im Zweifelsfall prüfe bitte den
official_calendar: offiziellen TUMonline-Kalender
last_sync: Zuletzt aktualisiert
close: Schließen
core_js:
error:
Expand Down
9 changes: 9 additions & 0 deletions webclient/src/locales/en.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
calendar:
modal:
title: Calendar
close: Close
footer:
disclaimer: Events are updated daily and identical events are merged.
please_check: If in doubt, please check the
official_calendar: official calendar on TUMonline
last_sync: Last update
close: Close
core_js:
error:
Expand Down
3 changes: 3 additions & 0 deletions webclient/src/stores/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export const useGlobalStore = defineStore({
state: () => ({
search_focused: false,
error_message: null as string | null,
calendar: {
open: false,
},
information_modal: {
header: null as string | null,
body: null as string | null,
Expand Down
4 changes: 3 additions & 1 deletion webclient/src/views/DetailsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getLocalStorageWithExpiry, removeLocalStorage } from "@/composables/sto
import { setDescription, setTitle } from "@/composables/common";
import { useClipboard } from "@vueuse/core";
import { selectedMap, useDetailsStore } from "@/stores/details";
import { useGlobalStore } from "@/stores/global";
import { nextTick, onMounted, ref, watchEffect } from "vue";
import { useFetch } from "@/composables/fetch";
import { useRoute } from "vue-router";
Expand Down Expand Up @@ -68,6 +69,7 @@ watchEffect(() => {
});
});
const global = useGlobalStore();
const state = useDetailsStore();
const { copy, copied, isSupported: clipboardIsSupported } = useClipboard({ source: route.source });
// Coordinate picker states
Expand Down Expand Up @@ -252,7 +254,7 @@ onMounted(() => {
<a
class="btn btn-link btn-action btn-sm"
v-if="state.data?.props?.calendar_url"
:href="state.data.props.calendar_url"
@click="global.calendar.open = true"
target="_blank"
:title="$t('view_view.header.calendar')"
>
Expand Down

0 comments on commit b67b4df

Please sign in to comment.