31 add page labels and meta information

This commit is contained in:
survellow
2024-05-21 17:03:45 +02:00
parent 3c89c917a3
commit d4a248bc5d
8 changed files with 167 additions and 10 deletions

View File

@@ -15,6 +15,7 @@
"@fullcalendar/vue3": "^6.1.11", "@fullcalendar/vue3": "^6.1.11",
"@tanstack/vue-query": "^5.28.9", "@tanstack/vue-query": "^5.28.9",
"@tanstack/vue-query-devtools": "^5.28.10", "@tanstack/vue-query-devtools": "^5.28.10",
"@unhead/vue": "^1.9.10",
"@vueuse/core": "^10.9.0", "@vueuse/core": "^10.9.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"primeflex": "^3.3.1", "primeflex": "^3.3.1",
@@ -1260,6 +1261,58 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"dev": true "dev": true
}, },
"node_modules/@unhead/dom": {
"version": "1.9.10",
"resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.9.10.tgz",
"integrity": "sha512-F4sBrmd8kG8MEqcVTGL0Y6tXbJMdWK724pznUzefpZTs1GaVypFikLluaLt4EnICcVhOBSe4TkGrc8N21IJJzQ==",
"dependencies": {
"@unhead/schema": "1.9.10",
"@unhead/shared": "1.9.10"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/schema": {
"version": "1.9.10",
"resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.9.10.tgz",
"integrity": "sha512-3ROh0doKfA7cIcU0zmjYVvNOiJuxSOcjInL+7iOFIxQovEWr1PcDnrnbEWGJsXrLA8eqjrjmhuDqAr3JbMGsLg==",
"dependencies": {
"hookable": "^5.5.3",
"zhead": "^2.2.4"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/shared": {
"version": "1.9.10",
"resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.9.10.tgz",
"integrity": "sha512-LBXxm/8ahY4FZ0FbWVaM1ANFO5QpPzvaYwjAQhgHANsrqFP2EqoGcOv1CfhdQbxg8vpGXkjI7m0r/8E9d3JoDA==",
"dependencies": {
"@unhead/schema": "1.9.10"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@unhead/vue": {
"version": "1.9.10",
"resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.9.10.tgz",
"integrity": "sha512-Zi65eTU5IIaqqXAVOVJ4fnwJRR751FZIFlzYOjIekf1eNkISy+A4xyz3NIEQWSlXCrOiDNgDhT0YgKUcx5FfHQ==",
"dependencies": {
"@unhead/schema": "1.9.10",
"@unhead/shared": "1.9.10",
"hookable": "^5.5.3",
"unhead": "1.9.10"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
},
"peerDependencies": {
"vue": ">=2.7 || >=3"
}
},
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
@@ -2897,6 +2950,11 @@
"he": "bin/he" "he": "bin/he"
} }
}, },
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
},
"node_modules/human-signals": { "node_modules/human-signals": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
@@ -4338,6 +4396,20 @@
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true "dev": true
}, },
"node_modules/unhead": {
"version": "1.9.10",
"resolved": "https://registry.npmjs.org/unhead/-/unhead-1.9.10.tgz",
"integrity": "sha512-Y3w+j1x1YFig2YuE+W2sER+SciRR7MQktYRHNqvZJ0iUNCCJTS8Z/SdSMUEeuFV28daXeASlR3fy7Ry3O2indg==",
"dependencies": {
"@unhead/dom": "1.9.10",
"@unhead/schema": "1.9.10",
"@unhead/shared": "1.9.10",
"hookable": "^5.5.3"
},
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.0.13", "version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
@@ -4789,6 +4861,14 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
},
"node_modules/zhead": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz",
"integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==",
"funding": {
"url": "https://github.com/sponsors/harlan-zw"
}
} }
} }
} }

View File

@@ -20,6 +20,7 @@
"@fullcalendar/vue3": "^6.1.11", "@fullcalendar/vue3": "^6.1.11",
"@tanstack/vue-query": "^5.28.9", "@tanstack/vue-query": "^5.28.9",
"@tanstack/vue-query-devtools": "^5.28.10", "@tanstack/vue-query-devtools": "^5.28.10",
"@unhead/vue": "^1.9.10",
"@vueuse/core": "^10.9.0", "@vueuse/core": "^10.9.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"primeflex": "^3.3.1", "primeflex": "^3.3.1",

View File

@@ -0,0 +1,2 @@
User-agent: *
Allow: /

View File

@@ -18,11 +18,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
<script lang="ts" setup> <script lang="ts" setup>
import MenuBar from "./components/MenuBar.vue"; import MenuBar from "./components/MenuBar.vue";
import { RouteRecordName, RouterView } from "vue-router"; import { RouteRecordName, RouterView, useRoute, useRouter } from "vue-router";
import { useHead } from "@unhead/vue";
import CalendarPreview from "./components/CalendarPreview.vue"; import CalendarPreview from "./components/CalendarPreview.vue";
import moduleStore from "./store/moduleStore.ts"; import moduleStore from "./store/moduleStore.ts";
import { provide, ref } from "vue"; import { computed, provide, ref } from "vue";
import { VueQueryDevtools } from "@tanstack/vue-query-devtools"; import { VueQueryDevtools } from "@tanstack/vue-query-devtools";
import { useI18n } from "vue-i18n";
const { t } = useI18n({ useScope: "global" });
const disabledPages = [ const disabledPages = [
"room-finder", "room-finder",
@@ -36,6 +39,33 @@ const disabledPages = [
"room-schedule", "room-schedule",
]; ];
// Provide canonical link for SEO
const router = useRouter();
const route = useRoute();
const baseUri = "https://cal.htwk-leipzig.de"; // could be stored in .env
const canonical = computed(() => `${baseUri}${router.resolve(route.name ? { name: route.name } : route).path}`);
const title = computed(() => route.meta.label?
`HTWKalender - ${t(String(route.meta.label))}`:
"HTWKalender"
);
useHead({
title: title,
link: [
{ rel: "canonical", href: canonical},
],
meta: [
{
name: "description",
content: "Dein individueller Stundenplan mit Sportevents und Prüfungen. Finde kommende Veranstaltungen oder freie Räume zum Lernen und Arbeiten.",
},
{
name: "keywords",
content: "HTWK Leipzig, Stundenplan, iCal, freie Räume, Lerngruppen, Sport, Prüfungen",
}
]
});
const store = moduleStore(); const store = moduleStore();
const mobilePage = ref(true); const mobilePage = ref(true);
provide("mobilePage", mobilePage); provide("mobilePage", mobilePage);

View File

@@ -102,12 +102,13 @@ function handleDarkModeToggled(isDarkVar: boolean) {
" "
v-bind="props.action" v-bind="props.action"
@click="navigate" @click="navigate"
:href="item.route"
> >
<span :class="item.icon" /> <span :class="item.icon" />
<span class="ml-2 p-menuitem-label">{{ item.label }}</span> <span class="ml-2 p-menuitem-label">{{ item.label }}</span>
</a> </a>
</router-link> </router-link>
<a <span
v-else v-else
:class=" :class="
$route.path.includes(item.info) $route.path.includes(item.info)
@@ -115,11 +116,10 @@ function handleDarkModeToggled(isDarkVar: boolean) {
: 'flex align-items-center' : 'flex align-items-center'
" "
v-bind="props.action" v-bind="props.action"
:href="item.url"
> >
<span :class="item.icon" /> <span :class="item.icon" />
<span class="ml-2 p-menuitem-label">{{ item.label }}</span> <span class="ml-2 p-menuitem-label">{{ item.label }}</span>
</a> </span>
</template> </template>
<template #end> <template #end>
<div class="flex align-items-stretch justify-content-center"> <div class="flex align-items-stretch justify-content-center">

View File

@@ -17,6 +17,7 @@
import "source-sans/source-sans-3.css"; import "source-sans/source-sans-3.css";
import { createApp } from "vue"; import { createApp } from "vue";
import { createHead } from "@unhead/vue";
import "./style.css"; import "./style.css";
import App from "./App.vue"; import App from "./App.vue";
import PrimeVue from "primevue/config"; import PrimeVue from "primevue/config";
@@ -69,6 +70,9 @@ app.use(VueQueryPlugin, {
}, },
}); });
const head = createHead();
app.use(head);
app.use(PrimeVue); app.use(PrimeVue);
app.use(router); app.use(router);
app.use(ToastService); app.use(ToastService);

View File

@@ -37,46 +37,73 @@ const router = createRouter({
path: "/", path: "/",
name: "course-selection", name: "course-selection",
component: CourseSelection, component: CourseSelection,
meta: {
label: "",
},
}, },
{ {
path: "/rooms/occupancy", path: "/rooms/occupancy",
name: "room-schedule", name: "room-schedule",
component: RoomFinder, component: RoomFinder,
meta: {
label: "roomFinderPage.roomSchedule",
},
}, },
{ {
path: "/rooms/free", path: "/rooms/free",
name: "free-rooms", name: "free-rooms",
component: FreeRooms, component: FreeRooms,
meta: {
label: "freeRooms.freeRooms",
}
}, },
{ {
path: "/faq", path: "/faq",
name: "faq", name: "faq",
component: Faq, component: Faq,
meta: {
label: "faq",
}
}, },
{ {
path: "/additional-modules", path: "/additional-modules",
name: "additional-modules", name: "additional-modules",
component: AdditionalModules, component: AdditionalModules,
meta: {
label: "createCalendar",
}
}, },
{ {
path: "/edit-additional-modules", path: "/edit-additional-modules",
name: "edit-additional-modules", name: "edit-additional-modules",
component: EditAdditionalModules, component: EditAdditionalModules,
meta: {
label: "editCalendar",
}
}, },
{ {
path: "/edit-calendar", path: "/edit-calendar",
name: "edit-calendar", name: "edit-calendar",
component: EditModules, component: EditModules,
meta: {
label: "editCalendar",
}
}, },
{ {
path: "/calendar-link", path: "/calendar-link",
name: "calendar-link", name: "calendar-link",
component: CalendarLink, component: CalendarLink,
meta: {
label: "createCalendar"
}
}, },
{ {
path: "/edit", path: "/edit",
name: "edit", name: "edit",
component: EditCalendarView, component: EditCalendarView,
meta: {
label: "editCalendar",
}
}, },
{ {
path: "/privacy-policy", path: "/privacy-policy",
@@ -86,6 +113,9 @@ const router = createRouter({
window.location.href = window.location.href =
"https://www.htwk-leipzig.de/hochschule/kontakt/datenschutzerklaerung/"; "https://www.htwk-leipzig.de/hochschule/kontakt/datenschutzerklaerung/";
}, },
meta: {
label: "privacy"
}
}, },
{ {
path: "/imprint", path: "/imprint",
@@ -95,11 +125,17 @@ const router = createRouter({
window.location.href = window.location.href =
"https://www.htwk-leipzig.de/hochschule/kontakt/impressum/"; "https://www.htwk-leipzig.de/hochschule/kontakt/impressum/";
}, },
meta: {
label: "imprint"
}
}, },
{ {
path: "/rename-modules", path: "/rename-modules",
name: "rename-modules", name: "rename-modules",
component: RenameModules, component: RenameModules,
meta: {
label: "createCalendar"
}
}, },
], ],
}); });

View File

@@ -42,18 +42,18 @@ const hasContent = computed(() => {
</script> </script>
<template> <template>
<div class="flex flex-column align-items-center mt-0"> <heading class="flex flex-column align-items-center mt-0">
<div <div
class="flex align-items-center justify-content-center gap-3 mx-2 mb-4 transition-rolldown" class="flex align-items-center justify-content-center gap-3 mx-2 mb-4 transition-rolldown"
:class="{ 'md:mt-8': hideContent }" :class="{ 'md:mt-8': hideContent }"
> >
<h3 class="text-4xl"> <h1 class="text-4xl">
{{ headline }} {{ headline }}
</h3> </h1>
<i v-if="icon" :class="icon" style="font-size: 2rem"></i> <i v-if="icon" :class="icon" style="font-size: 2rem"></i>
</div> </div>
<div v-if="subTitle" class="flex justify-content-center"> <div v-if="subTitle" class="flex justify-content-center">
<h5 class="text-2xl m-2">{{ subTitle }}</h5> <p class="subtitle text-2xl m-2">{{ subTitle }}</p>
</div> </div>
<div class="flex flex-wrap mx-0 gap-2 my-4 w-full lg:w-8"> <div class="flex flex-wrap mx-0 gap-2 my-4 w-full lg:w-8">
<slot name="selection" flex-specs="flex-1 m-0"></slot> <slot name="selection" flex-specs="flex-1 m-0"></slot>
@@ -87,11 +87,15 @@ const hasContent = computed(() => {
> >
<slot name="content"></slot> <slot name="content"></slot>
</div> </div>
</div> </heading>
</template> </template>
<style scoped> <style scoped>
.transition-rolldown { .transition-rolldown {
transition: margin-top 0.5s ease-in-out; transition: margin-top 0.5s ease-in-out;
} }
.subtitle {
font-weight: 100;
font-size: 1.5rem;
}
</style> </style>