mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender.git
synced 2025-08-03 18:29:14 +02:00
added frontend and updated backend with docker, wrote some initial instructions
This commit is contained in:
10
frontend/src/App.vue
Normal file
10
frontend/src/App.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import MenuBar from "./components/MenuBar.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MenuBar />
|
||||
<router-view></router-view>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
20
frontend/src/api/createFeed.ts
Normal file
20
frontend/src/api/createFeed.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Module } from "../model/module.ts";
|
||||
|
||||
export async function createIndividualFeed(modules: Module[]): Promise<string> {
|
||||
let token = "";
|
||||
|
||||
await fetch("/api/createFeed", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(modules),
|
||||
})
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((response) => {
|
||||
token = response;
|
||||
});
|
||||
return token;
|
||||
}
|
45
frontend/src/api/fetchCourse.ts
Normal file
45
frontend/src/api/fetchCourse.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// function to fetch course data from the API
|
||||
|
||||
import { Module } from "../model/module.ts";
|
||||
|
||||
export async function fetchCourse(): Promise<string[]> {
|
||||
const courses: string[] = [];
|
||||
await fetch("/api/courses")
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((coursesResponse) => {
|
||||
coursesResponse.forEach((course: string) => courses.push(course));
|
||||
});
|
||||
return courses;
|
||||
}
|
||||
|
||||
export async function fetchModulesByCourseAndSemester(
|
||||
course: string,
|
||||
semester: string,
|
||||
): Promise<Module[]> {
|
||||
const modules: Module[] = [];
|
||||
await fetch("/api/course/modules?course=" + course + "&semester=" + semester)
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((modulesResponse) => {
|
||||
modulesResponse.forEach((module: string) =>
|
||||
modules.push(new Module(module, course)),
|
||||
);
|
||||
});
|
||||
return modules;
|
||||
}
|
||||
|
||||
export async function fetchAllModules(): Promise<Module[]> {
|
||||
let modules: Module[] = [];
|
||||
await fetch("/api/modules")
|
||||
.then((response) => {
|
||||
return response.json() as Promise<Module[]>;
|
||||
})
|
||||
.then((responseModules: Module[]) => {
|
||||
modules = responseModules as Module[];
|
||||
});
|
||||
|
||||
return modules;
|
||||
}
|
1
frontend/src/assets/vue.svg
Normal file
1
frontend/src/assets/vue.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
After Width: | Height: | Size: 496 B |
106
frontend/src/components/AdditionalModules.vue
Normal file
106
frontend/src/components/AdditionalModules.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, Ref } from "vue";
|
||||
import { Module } from "../model/module.ts";
|
||||
import { fetchAllModules } from "../api/fetchCourse.ts";
|
||||
import moduleStore from "../store/moduleStore.ts";
|
||||
import { createIndividualFeed } from "../api/createFeed.ts";
|
||||
import { MultiSelectAllChangeEvent } from "primevue/multiselect";
|
||||
import tokenStore from "../store/tokenStore.ts";
|
||||
import router from "../router";
|
||||
|
||||
const fetchedModules = async () => {
|
||||
return await fetchAllModules();
|
||||
};
|
||||
|
||||
const modules: Ref<Module[]> = ref([]);
|
||||
|
||||
const selectedModules: Ref<Module[]> = ref([] as Module[]);
|
||||
|
||||
fetchedModules().then(
|
||||
(data) =>
|
||||
(modules.value = data.map((module: Module) => {
|
||||
return module;
|
||||
})),
|
||||
);
|
||||
|
||||
async function finalStep() {
|
||||
selectedModules.value.forEach((module: Module) => {
|
||||
moduleStore().addModule(module);
|
||||
});
|
||||
|
||||
const token: string = await createIndividualFeed(moduleStore().modules);
|
||||
tokenStore().setToken(token);
|
||||
await router.push("/calendar-link");
|
||||
}
|
||||
|
||||
const display = (module: Module) => module.Name + " (" + module.Course + ")";
|
||||
|
||||
const selectAll = ref(false);
|
||||
|
||||
const onSelectAllChange = (event: MultiSelectAllChangeEvent) => {
|
||||
selectedModules.value = event.checked
|
||||
? modules.value.map((module) => module)
|
||||
: [];
|
||||
selectAll.value = event.checked;
|
||||
};
|
||||
|
||||
function selectChange() {
|
||||
selectAll.value = selectedModules.value.length === modules.value.length;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
<div class="flex align-items-center justify-content-center h-4rem m-2">
|
||||
<h3>
|
||||
Select additional Modules that are not listed in the regular semester
|
||||
for your Course
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card flex align-items-center justify-content-center m-2">
|
||||
<MultiSelect
|
||||
v-model="selectedModules"
|
||||
:max-selected-labels="1"
|
||||
:option-label="display"
|
||||
:options="modules"
|
||||
:select-all="selectAll"
|
||||
:virtual-scroller-options="{ itemSize: 70 }"
|
||||
class="custom-multiselect"
|
||||
filter
|
||||
placeholder="Select additional modules"
|
||||
@change="selectChange()"
|
||||
@selectall-change="onSelectAllChange($event)"
|
||||
>
|
||||
<template #option="slotProps">
|
||||
<div class="flex align-items-center">
|
||||
<p class="text-1xl white-space-normal">
|
||||
{{ display(slotProps.option) }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="py-2 px-3">
|
||||
<b>{{ selectedModules ? selectedModules.length : 0 }}</b>
|
||||
item{{
|
||||
(selectedModules ? selectedModules.length : 0) > 1 ? "s" : ""
|
||||
}}
|
||||
selected.
|
||||
</div>
|
||||
</template>
|
||||
</MultiSelect>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center h-4rem m-2">
|
||||
<Button @click="finalStep()"> Create Calendar</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.custom-multiselect) {
|
||||
width: 50rem;
|
||||
}
|
||||
|
||||
:deep(.custom-multiselect li) {
|
||||
height: unset;
|
||||
}
|
||||
</style>
|
49
frontend/src/components/CalendarLink.vue
Normal file
49
frontend/src/components/CalendarLink.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<script lang="ts" setup>
|
||||
import tokenStore from "../store/tokenStore.ts";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import { onMounted } from "vue";
|
||||
import router from "../router";
|
||||
const toast = useToast();
|
||||
|
||||
const show = () => {
|
||||
toast.add({
|
||||
severity: "info",
|
||||
summary: "Info",
|
||||
detail: "Link copied to clipboard",
|
||||
life: 3000,
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
rerouteIfTokenIsEmpty();
|
||||
});
|
||||
|
||||
function rerouteIfTokenIsEmpty() {
|
||||
if (tokenStore().token == "") {
|
||||
router.push("/");
|
||||
}
|
||||
}
|
||||
|
||||
function copyToClipboard() {
|
||||
const text = "http://localhost:8090/api/feed?token=" + tokenStore().token;
|
||||
// Copy the text inside the text field
|
||||
navigator.clipboard.writeText(text);
|
||||
show();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Toast />
|
||||
<div class="flex flex-column">
|
||||
<div class="flex align-items-center justify-content-center h-4rem m-2">
|
||||
<h2>
|
||||
{{ "http://localhost:8090/api/feed?token=" + tokenStore().token }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center h-4rem m-2">
|
||||
<Button @click="copyToClipboard">Copy iCal Link</Button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
84
frontend/src/components/CourseSelection.vue
Normal file
84
frontend/src/components/CourseSelection.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<script lang="ts" setup>
|
||||
import { Ref, ref } from "vue";
|
||||
import {
|
||||
fetchCourse,
|
||||
fetchModulesByCourseAndSemester,
|
||||
} from "../api/fetchCourse";
|
||||
import ModuleSelection from "./ModuleSelection.vue";
|
||||
import { Module } from "../model/module.ts";
|
||||
|
||||
const courses = async () => {
|
||||
return await fetchCourse();
|
||||
};
|
||||
|
||||
const selectedCourse: Ref<{ name: string }> = ref({ name: "" });
|
||||
const countries: Ref<{ name: string }[]> = ref([]);
|
||||
const semesters: Ref<{ name: string; value: string }[]> = ref([
|
||||
{ name: "Wintersemester", value: "ws" },
|
||||
{ name: "Sommersemester", value: "ss" },
|
||||
]);
|
||||
|
||||
const selectedSemester: Ref<{ name: string; value: string }> = ref(
|
||||
semesters.value[0],
|
||||
);
|
||||
|
||||
courses().then(
|
||||
(data) =>
|
||||
(countries.value = data.map((course) => {
|
||||
return { name: course };
|
||||
})),
|
||||
);
|
||||
|
||||
const modules: Ref<Module[]> = ref([]);
|
||||
|
||||
async function getModules() {
|
||||
modules.value = await fetchModulesByCourseAndSemester(
|
||||
selectedCourse.value.name,
|
||||
selectedSemester.value.value,
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
<div class="flex align-items-center justify-content-center h-4rem m-2">
|
||||
<h3 class="text-4xl">Welcome to the Course Calendar</h3>
|
||||
</div>
|
||||
<div
|
||||
class="flex align-items-center justify-content-center h-4rem border-round m-2"
|
||||
>
|
||||
<h5 class="text-2xl">Please select a course</h5>
|
||||
</div>
|
||||
<div
|
||||
class="flex align-items-center justify-content-center border-round m-2"
|
||||
>
|
||||
<Dropdown
|
||||
v-model="selectedCourse"
|
||||
:options="countries"
|
||||
class="w-full md:w-25rem mx-2"
|
||||
filter
|
||||
option-label="name"
|
||||
placeholder="Select a Course"
|
||||
@change="getModules()"
|
||||
></Dropdown>
|
||||
<Dropdown
|
||||
v-model="selectedSemester"
|
||||
:options="semesters"
|
||||
class="w-full md:w-25rem mx-2"
|
||||
option-label="name"
|
||||
placeholder="Select a Semester"
|
||||
@change="getModules()"
|
||||
></Dropdown>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex align-items-center justify-content-center border-round m-2"
|
||||
>
|
||||
<div class="flex flex-wrap justify-content-center">
|
||||
<div class="flex align-items-center">
|
||||
<ModuleSelection :modules="modules" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
11
frontend/src/components/FaqPage.vue
Normal file
11
frontend/src/components/FaqPage.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
<div class="flex align-items-center justify-content-center h-4rem m-2">
|
||||
<h2>FAQ</h2>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
11
frontend/src/components/Impress.vue
Normal file
11
frontend/src/components/Impress.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<div class="flex align-items-center justify-content-center flex-column">
|
||||
<div class="flex align-items-center justify-content-center h-4rem mt-2">
|
||||
<h3 class="text-4xl">Impress</h3>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
39
frontend/src/components/MenuBar.vue
Normal file
39
frontend/src/components/MenuBar.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
|
||||
const items = ref([
|
||||
{
|
||||
label: "Create Calendar",
|
||||
icon: "pi pi-fw pi-plus",
|
||||
url: "/",
|
||||
},
|
||||
{
|
||||
label: "FAQ",
|
||||
icon: "pi pi-fw pi-book",
|
||||
url: "/faq",
|
||||
},
|
||||
{
|
||||
label: "Impress",
|
||||
icon: "pi pi-fw pi-id-card",
|
||||
url: "/impress",
|
||||
},
|
||||
{
|
||||
label: "Privacy",
|
||||
url: "/privacy-policy",
|
||||
icon: "pi pi-fw pi-exclamation-triangle",
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Menubar :model="items" class="menubar justify-content-center">
|
||||
<template #start></template>
|
||||
</Menubar>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.menubar {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
138
frontend/src/components/ModuleSelection.vue
Normal file
138
frontend/src/components/ModuleSelection.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, PropType, Ref, ref, watch } from "vue";
|
||||
import { Module } from "../model/module.ts";
|
||||
import moduleStore from "../store/moduleStore";
|
||||
import router from "../router";
|
||||
|
||||
const props = defineProps({
|
||||
modules: {
|
||||
type: Array as PropType<Module[]>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// array of modules with boolean if selected with getter and setter
|
||||
const modulesWithSelection: Ref<{ module: Module; selected: boolean }[]> = ref(
|
||||
props.modules.map((module) => {
|
||||
return { module: module, selected: false };
|
||||
}),
|
||||
);
|
||||
|
||||
//watch for changes in modules prop and update modulesWithSelection
|
||||
|
||||
function selectedModules(): Module[] {
|
||||
return modulesWithSelection.value
|
||||
.filter((module) => module.selected)
|
||||
.map((module) => module.module);
|
||||
}
|
||||
|
||||
const currentModules = computed(() => props.modules);
|
||||
|
||||
function selectAllModules(selection: boolean) {
|
||||
modulesWithSelection.value.forEach((module) => {
|
||||
module.selected = selection;
|
||||
});
|
||||
}
|
||||
|
||||
const allSelected: Ref<boolean> = ref(true);
|
||||
|
||||
computed(() => {
|
||||
return modulesWithSelection.value.every((module) => module.selected);
|
||||
});
|
||||
|
||||
watch(currentModules, (newValue: Module[]) => {
|
||||
modulesWithSelection.value = newValue.map((module) => {
|
||||
return { module: module, selected: false };
|
||||
});
|
||||
});
|
||||
|
||||
function nextStep() {
|
||||
console.log("next step");
|
||||
selectedModules().forEach((module) => {
|
||||
moduleStore().addModule(module);
|
||||
});
|
||||
|
||||
console.debug(moduleStore().modules);
|
||||
|
||||
router.push("/additional-modules");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-column card-container">
|
||||
<div class="flex align-items-center justify-content-center mb-3">
|
||||
<Button
|
||||
:disabled="selectedModules().length < 1"
|
||||
class="col-4 justify-content-center"
|
||||
@click="nextStep()"
|
||||
>Next Step
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<DataView :value="modulesWithSelection" data-key="name">
|
||||
<template #header>
|
||||
<div class="flex justify-content-between flex-wrap">
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<h3>Selected Modules - {{ selectedModules().length }}</h3>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center">
|
||||
<ToggleButton
|
||||
v-model="allSelected"
|
||||
class="w-12rem"
|
||||
off-icon="pi pi-times"
|
||||
off-label="Unselect All"
|
||||
on-icon="pi pi-check"
|
||||
on-label="Select All"
|
||||
@click="selectAllModules(!allSelected)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<p class="p-4 text-2xl font-bold text-900 empty-message">
|
||||
No Modules found for this course
|
||||
</p>
|
||||
</template>
|
||||
<template #list="slotProps">
|
||||
<div class="col-12">
|
||||
<div
|
||||
class="flex flex-column xl:flex-row xl:align-items-start p-4 gap-4"
|
||||
>
|
||||
<div
|
||||
class="flex flex-column sm:flex-row justify-content-between align-items-center xl:align-items-start flex-1 gap-4"
|
||||
>
|
||||
<div
|
||||
class="flex flex-column align-items-center sm:align-items-start gap-3"
|
||||
>
|
||||
<div class="text-2xl">
|
||||
{{ slotProps.data.module.Name }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex sm:flex-column align-items-center sm:align-items-end gap-3 sm:gap-2"
|
||||
>
|
||||
<ToggleButton
|
||||
v-model="modulesWithSelection[slotProps.index].selected"
|
||||
class="w-9rem"
|
||||
off-icon="pi pi-times"
|
||||
off-label="Unselected"
|
||||
on-icon="pi pi-check"
|
||||
on-label="Selected"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</DataView>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@media screen and (min-width: 962px) {
|
||||
.empty-message {
|
||||
width: 50rem;
|
||||
}
|
||||
}
|
||||
</style>
|
537
frontend/src/components/PrivacyPolicy.vue
Normal file
537
frontend/src/components/PrivacyPolicy.vue
Normal file
@@ -0,0 +1,537 @@
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<div class="flex align-items-center justify-content-center flex-column">
|
||||
<div class="flex align-items-center justify-content-center h-4rem mt-2">
|
||||
<h3 class="text-4xl">Privacy policy</h3>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-center h-4rem">
|
||||
<p>https://github.com/primefaces/primevue/blob/master/LICENSE.md</p>
|
||||
</div>
|
||||
<div class="flex flex-column col-7">
|
||||
<h1>Datenschutzerklärung</h1>
|
||||
<p>Stand: 19. September 2023</p>
|
||||
<h2>Inhaltsübersicht</h2>
|
||||
<ul class="index">
|
||||
<li><a class="index-link" href="#m3">Verantwortlicher</a></li>
|
||||
<li>
|
||||
<a class="index-link" href="#mOverview"
|
||||
>Übersicht der Verarbeitungen</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="index-link" href="#m2427">Maßgebliche Rechtsgrundlagen</a>
|
||||
</li>
|
||||
<li><a class="index-link" href="#m27">Sicherheitsmaßnahmen</a></li>
|
||||
<li>
|
||||
<a class="index-link" href="#m25"
|
||||
>Übermittlung von personenbezogenen Daten</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="index-link" href="#m24">Internationale Datentransfers</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="index-link" href="#m10">Rechte der betroffenen Personen</a>
|
||||
</li>
|
||||
<li><a class="index-link" href="#m134">Einsatz von Cookies</a></li>
|
||||
<li>
|
||||
<a class="index-link" href="#m225"
|
||||
>Bereitstellung des Onlineangebotes und Webhosting</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a class="index-link" href="#m182">Kontakt- und Anfragenverwaltung</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="m3">Verantwortlicher</h2>
|
||||
<p>
|
||||
Elmar Kresse<br />Philipp-Rosenthal-Straße 33<br />04103, Leipzig,
|
||||
Deutschland
|
||||
</p>
|
||||
E-Mail-Adresse:
|
||||
<p><a href="mailto:support@kresse.dev">support@kresse.dev</a></p>
|
||||
|
||||
<h2 id="mOverview">Übersicht der Verarbeitungen</h2>
|
||||
<p>
|
||||
Die nachfolgende Übersicht fasst die Arten der verarbeiteten Daten und
|
||||
die Zwecke ihrer Verarbeitung zusammen und verweist auf die betroffenen
|
||||
Personen.
|
||||
</p>
|
||||
<h3>Arten der verarbeiteten Daten</h3>
|
||||
<ul>
|
||||
<li>Kontaktdaten.</li>
|
||||
<li>Inhaltsdaten.</li>
|
||||
<li>Nutzungsdaten.</li>
|
||||
<li>Meta-, Kommunikations- und Verfahrensdaten.</li>
|
||||
</ul>
|
||||
<h3>Kategorien betroffener Personen</h3>
|
||||
<ul>
|
||||
<li>Kommunikationspartner.</li>
|
||||
<li>Nutzer.</li>
|
||||
</ul>
|
||||
<h3>Zwecke der Verarbeitung</h3>
|
||||
<ul>
|
||||
<li>Kontaktanfragen und Kommunikation.</li>
|
||||
<li>Sicherheitsmaßnahmen.</li>
|
||||
<li>Verwaltung und Beantwortung von Anfragen.</li>
|
||||
<li>Feedback.</li>
|
||||
<li>
|
||||
Bereitstellung unseres Onlineangebotes und Nutzerfreundlichkeit.
|
||||
</li>
|
||||
<li>Informationstechnische Infrastruktur.</li>
|
||||
</ul>
|
||||
<h2 id="m2427">Maßgebliche Rechtsgrundlagen</h2>
|
||||
<p>
|
||||
<strong>Maßgebliche Rechtsgrundlagen nach der DSGVO: </strong>Im
|
||||
Folgenden erhalten Sie eine Übersicht der Rechtsgrundlagen der DSGVO,
|
||||
auf deren Basis wir personenbezogene Daten verarbeiten. Bitte nehmen Sie
|
||||
zur Kenntnis, dass neben den Regelungen der DSGVO nationale
|
||||
Datenschutzvorgaben in Ihrem bzw. unserem Wohn- oder Sitzland gelten
|
||||
können. Sollten ferner im Einzelfall speziellere Rechtsgrundlagen
|
||||
maßgeblich sein, teilen wir Ihnen diese in der Datenschutzerklärung mit.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Einwilligung (Art. 6 Abs. 1 S. 1 lit. a) DSGVO)</strong> - Die
|
||||
betroffene Person hat ihre Einwilligung in die Verarbeitung der sie
|
||||
betreffenden personenbezogenen Daten für einen spezifischen Zweck oder
|
||||
mehrere bestimmte Zwecke gegeben.
|
||||
</li>
|
||||
<li>
|
||||
<strong
|
||||
>Berechtigte Interessen (Art. 6 Abs. 1 S. 1 lit. f) DSGVO)</strong
|
||||
>
|
||||
- Die Verarbeitung ist zur Wahrung der berechtigten Interessen des
|
||||
Verantwortlichen oder eines Dritten erforderlich, sofern nicht die
|
||||
Interessen oder Grundrechte und Grundfreiheiten der betroffenen
|
||||
Person, die den Schutz personenbezogener Daten erfordern, überwiegen.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong>Nationale Datenschutzregelungen in Deutschland: </strong
|
||||
>Zusätzlich zu den Datenschutzregelungen der DSGVO gelten nationale
|
||||
Regelungen zum Datenschutz in Deutschland. Hierzu gehört insbesondere
|
||||
das Gesetz zum Schutz vor Missbrauch personenbezogener Daten bei der
|
||||
Datenverarbeitung (Bundesdatenschutzgesetz – BDSG). Das BDSG enthält
|
||||
insbesondere Spezialregelungen zum Recht auf Auskunft, zum Recht auf
|
||||
Löschung, zum Widerspruchsrecht, zur Verarbeitung besonderer Kategorien
|
||||
personenbezogener Daten, zur Verarbeitung für andere Zwecke und zur
|
||||
Übermittlung sowie automatisierten Entscheidungsfindung im Einzelfall
|
||||
einschließlich Profiling. Ferner können Landesdatenschutzgesetze der
|
||||
einzelnen Bundesländer zur Anwendung gelangen.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Hinweis auf Geltung DSGVO und Schweizer DSG: </strong>Diese
|
||||
Datenschutzhinweise dienen sowohl der Informationserteilung nach dem
|
||||
schweizerischen Bundesgesetz über den Datenschutz (Schweizer DSG) als
|
||||
auch nach der Datenschutzgrundverordnung (DSGVO). Aus diesem Grund
|
||||
bitten wir Sie zu beachten, dass aufgrund der breiteren räumlichen
|
||||
Anwendung und Verständlichkeit die Begriffe der DSGVO verwendet werden.
|
||||
Insbesondere statt der im Schweizer DSG verwendeten Begriffe
|
||||
„Bearbeitung" von „Personendaten", "überwiegendes Interesse" und
|
||||
"besonders schützenswerte Personendaten" werden die in der DSGVO
|
||||
verwendeten Begriffe „Verarbeitung" von „personenbezogenen Daten" sowie
|
||||
"berechtigtes Interesse" und "besondere Kategorien von Daten" verwendet.
|
||||
Die gesetzliche Bedeutung der Begriffe wird jedoch im Rahmen der Geltung
|
||||
des Schweizer DSG weiterhin nach dem Schweizer DSG bestimmt.
|
||||
</p>
|
||||
|
||||
<h2 id="m27">Sicherheitsmaßnahmen</h2>
|
||||
<p>
|
||||
Wir treffen nach Maßgabe der gesetzlichen Vorgaben unter
|
||||
Berücksichtigung des Stands der Technik, der Implementierungskosten und
|
||||
der Art, des Umfangs, der Umstände und der Zwecke der Verarbeitung sowie
|
||||
der unterschiedlichen Eintrittswahrscheinlichkeiten und des Ausmaßes der
|
||||
Bedrohung der Rechte und Freiheiten natürlicher Personen geeignete
|
||||
technische und organisatorische Maßnahmen, um ein dem Risiko
|
||||
angemessenes Schutzniveau zu gewährleisten.
|
||||
</p>
|
||||
<p>
|
||||
Zu den Maßnahmen gehören insbesondere die Sicherung der Vertraulichkeit,
|
||||
Integrität und Verfügbarkeit von Daten durch Kontrolle des physischen
|
||||
und elektronischen Zugangs zu den Daten als auch des sie betreffenden
|
||||
Zugriffs, der Eingabe, der Weitergabe, der Sicherung der Verfügbarkeit
|
||||
und ihrer Trennung. Des Weiteren haben wir Verfahren eingerichtet, die
|
||||
eine Wahrnehmung von Betroffenenrechten, die Löschung von Daten und
|
||||
Reaktionen auf die Gefährdung der Daten gewährleisten. Ferner
|
||||
berücksichtigen wir den Schutz personenbezogener Daten bereits bei der
|
||||
Entwicklung bzw. Auswahl von Hardware, Software sowie Verfahren
|
||||
entsprechend dem Prinzip des Datenschutzes, durch Technikgestaltung und
|
||||
durch datenschutzfreundliche Voreinstellungen.
|
||||
</p>
|
||||
<p>
|
||||
TLS-Verschlüsselung (https): Um Ihre via unserem Online-Angebot
|
||||
übermittelten Daten zu schützen, nutzen wir eine TLS-Verschlüsselung.
|
||||
Sie erkennen derart verschlüsselte Verbindungen an dem Präfix https://
|
||||
in der Adresszeile Ihres Browsers.
|
||||
</p>
|
||||
|
||||
<h2 id="m25">Übermittlung von personenbezogenen Daten</h2>
|
||||
<p>
|
||||
Im Rahmen unserer Verarbeitung von personenbezogenen Daten kommt es vor,
|
||||
dass die Daten an andere Stellen, Unternehmen, rechtlich selbstständige
|
||||
Organisationseinheiten oder Personen übermittelt oder sie ihnen
|
||||
gegenüber offengelegt werden. Zu den Empfängern dieser Daten können
|
||||
z. B. mit IT-Aufgaben beauftragte Dienstleister oder Anbieter von
|
||||
Diensten und Inhalten, die in eine Webseite eingebunden werden, gehören.
|
||||
In solchen Fällen beachten wir die gesetzlichen Vorgaben und schließen
|
||||
insbesondere entsprechende Verträge bzw. Vereinbarungen, die dem Schutz
|
||||
Ihrer Daten dienen, mit den Empfängern Ihrer Daten ab.
|
||||
</p>
|
||||
|
||||
<h2 id="m24">Internationale Datentransfers</h2>
|
||||
<p>
|
||||
Datenverarbeitung in Drittländern: Sofern wir Daten in einem Drittland
|
||||
(d. h., außerhalb der Europäischen Union (EU), des Europäischen
|
||||
Wirtschaftsraums (EWR)) verarbeiten oder die Verarbeitung im Rahmen der
|
||||
Inanspruchnahme von Diensten Dritter oder der Offenlegung bzw.
|
||||
Übermittlung von Daten an andere Personen, Stellen oder Unternehmen
|
||||
stattfindet, erfolgt dies nur im Einklang mit den gesetzlichen Vorgaben.
|
||||
Sofern das Datenschutzniveau in dem Drittland mittels eines
|
||||
Angemessenheitsbeschlusses anerkannt wurde (Art. 45 DSGVO), dient dieser
|
||||
als Grundlage des Datentransfers. Im Übrigen erfolgen Datentransfers nur
|
||||
dann, wenn das Datenschutzniveau anderweitig gesichert ist, insbesondere
|
||||
durch Standardvertragsklauseln (Art. 46 Abs. 2 lit. c) DSGVO),
|
||||
ausdrückliche Einwilligung oder im Fall vertraglicher oder gesetzlich
|
||||
erforderlicher Übermittlung (Art. 49 Abs. 1 DSGVO). Im Übrigen teilen
|
||||
wir Ihnen die Grundlagen der Drittlandübermittlung bei den einzelnen
|
||||
Anbietern aus dem Drittland mit, wobei die Angemesenheitsbeschlüsse als
|
||||
Grundlagen vorrangig gelten. Informationen zu Drittlandtransfers und
|
||||
vorliegenden Angemessenheitsbeschlüssen können dem Informationsangebot
|
||||
der EU-Kommission entnommen werden:
|
||||
<a
|
||||
href="https://ec.europa.eu/info/law/law-topic/data-protection/international-dimension-data-protection_de"
|
||||
target="_blank"
|
||||
>https://ec.europa.eu/info/law/law-topic/data-protection/international-dimension-data-protection_de.</a
|
||||
>
|
||||
</p>
|
||||
<p>
|
||||
EU-US Trans-Atlantic Data Privacy Framework: Im Rahmen des sogenannten
|
||||
„Data Privacy Framework" (DPF) hat die EU-Kommission das
|
||||
Datenschutzniveau ebenfalls für bestimmte Unternehmen aus den USA im
|
||||
Rahmen der Angemessenheitsbeschlusses vom 10.07.2023 als sicher
|
||||
anerkannt. Die Liste der zertifizierten Unternehmen als auch weitere
|
||||
Informationen zu dem DPF können Sie der Webseite des Handelsministeriums
|
||||
der USA unter
|
||||
<a href="https://www.dataprivacyframework.gov/" target="_blank"
|
||||
>https://www.dataprivacyframework.gov/</a
|
||||
>
|
||||
(in Englisch) entnehmen. Wir informieren Sie im Rahmen der
|
||||
Datenschutzhinweise welche von uns eingesetzten Diensteanbieter unter
|
||||
dem Data Privacy Framework zertifiziert sind.
|
||||
</p>
|
||||
|
||||
<h2 id="m10">Rechte der betroffenen Personen</h2>
|
||||
<p>
|
||||
Rechte der betroffenen Personen aus der DSGVO: Ihnen stehen als
|
||||
Betroffene nach der DSGVO verschiedene Rechte zu, die sich insbesondere
|
||||
aus Art. 15 bis 21 DSGVO ergeben:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong
|
||||
>Widerspruchsrecht: Sie haben das Recht, aus Gründen, die sich aus
|
||||
Ihrer besonderen Situation ergeben, jederzeit gegen die Verarbeitung
|
||||
der Sie betreffenden personenbezogenen Daten, die aufgrund von Art.
|
||||
6 Abs. 1 lit. e oder f DSGVO erfolgt, Widerspruch einzulegen; dies
|
||||
gilt auch für ein auf diese Bestimmungen gestütztes Profiling.
|
||||
Werden die Sie betreffenden personenbezogenen Daten verarbeitet, um
|
||||
Direktwerbung zu betreiben, haben Sie das Recht, jederzeit
|
||||
Widerspruch gegen die Verarbeitung der Sie betreffenden
|
||||
personenbezogenen Daten zum Zwecke derartiger Werbung einzulegen;
|
||||
dies gilt auch für das Profiling, soweit es mit solcher
|
||||
Direktwerbung in Verbindung steht.</strong
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Widerrufsrecht bei Einwilligungen:</strong> Sie haben das
|
||||
Recht, erteilte Einwilligungen jederzeit zu widerrufen.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Auskunftsrecht:</strong> Sie haben das Recht, eine Bestätigung
|
||||
darüber zu verlangen, ob betreffende Daten verarbeitet werden und auf
|
||||
Auskunft über diese Daten sowie auf weitere Informationen und Kopie
|
||||
der Daten entsprechend den gesetzlichen Vorgaben.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Recht auf Berichtigung:</strong> Sie haben entsprechend den
|
||||
gesetzlichen Vorgaben das Recht, die Vervollständigung der Sie
|
||||
betreffenden Daten oder die Berichtigung der Sie betreffenden
|
||||
unrichtigen Daten zu verlangen.
|
||||
</li>
|
||||
<li>
|
||||
<strong
|
||||
>Recht auf Löschung und Einschränkung der Verarbeitung:</strong
|
||||
>
|
||||
Sie haben nach Maßgabe der gesetzlichen Vorgaben das Recht, zu
|
||||
verlangen, dass Sie betreffende Daten unverzüglich gelöscht werden,
|
||||
bzw. alternativ nach Maßgabe der gesetzlichen Vorgaben eine
|
||||
Einschränkung der Verarbeitung der Daten zu verlangen.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Recht auf Datenübertragbarkeit:</strong> Sie haben das Recht,
|
||||
Sie betreffende Daten, die Sie uns bereitgestellt haben, nach Maßgabe
|
||||
der gesetzlichen Vorgaben in einem strukturierten, gängigen und
|
||||
maschinenlesbaren Format zu erhalten oder deren Übermittlung an einen
|
||||
anderen Verantwortlichen zu fordern.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Beschwerde bei Aufsichtsbehörde:</strong> Sie haben
|
||||
unbeschadet eines anderweitigen verwaltungsrechtlichen oder
|
||||
gerichtlichen Rechtsbehelfs das Recht auf Beschwerde bei einer
|
||||
Aufsichtsbehörde, insbesondere in dem Mitgliedstaat ihres gewöhnlichen
|
||||
Aufenthaltsorts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen
|
||||
Verstoßes, wenn Sie der Ansicht sind, dass die Verarbeitung der Sie
|
||||
betreffenden personenbezogenen Daten gegen die Vorgaben der DSGVO
|
||||
verstößt.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="m134">Einsatz von Cookies</h2>
|
||||
<p>
|
||||
Cookies sind kleine Textdateien, bzw. sonstige Speichervermerke, die
|
||||
Informationen auf Endgeräten speichern und Informationen aus den
|
||||
Endgeräten auslesen. Z. B. um den Login-Status in einem Nutzerkonto,
|
||||
einen Warenkorbinhalt in einem E-Shop, die aufgerufenen Inhalte oder
|
||||
verwendete Funktionen eines Onlineangebotes speichern. Cookies können
|
||||
ferner zu unterschiedlichen Zwecken eingesetzt werden, z. B. zu Zwecken
|
||||
der Funktionsfähigkeit, Sicherheit und Komfort von Onlineangeboten sowie
|
||||
der Erstellung von Analysen der Besucherströme.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Hinweise zur Einwilligung: </strong>Wir setzen Cookies im
|
||||
Einklang mit den gesetzlichen Vorschriften ein. Daher holen wir von den
|
||||
Nutzern eine vorhergehende Einwilligung ein, außer wenn diese gesetzlich
|
||||
nicht gefordert ist. Eine Einwilligung ist insbesondere nicht notwendig,
|
||||
wenn das Speichern und das Auslesen der Informationen, also auch von
|
||||
Cookies, unbedingt erforderlich sind, um dem den Nutzern einen von ihnen
|
||||
ausdrücklich gewünschten Telemediendienst (also unser Onlineangebot) zur
|
||||
Verfügung zu stellen. Zu den unbedingt erforderlichen Cookies gehören in
|
||||
der Regel Cookies mit Funktionen, die der Anzeige und Lauffähigkeit des
|
||||
Onlineangebotes , dem Lastausgleich, der Sicherheit, der Speicherung der
|
||||
Präferenzen und Auswahlmöglichkeiten der Nutzer oder ähnlichen mit der
|
||||
Bereitstellung der Haupt- und Nebenfunktionen des von den Nutzern
|
||||
angeforderten Onlineangebotes zusammenhängenden Zwecken dienen. Die
|
||||
widerrufliche Einwilligung wird gegenüber den Nutzern deutlich
|
||||
kommuniziert und enthält die Informationen zu der jeweiligen
|
||||
Cookie-Nutzung.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Hinweise zu datenschutzrechtlichen Rechtsgrundlagen: </strong
|
||||
>Auf welcher datenschutzrechtlichen Rechtsgrundlage wir die
|
||||
personenbezogenen Daten der Nutzer mit Hilfe von Cookies verarbeiten,
|
||||
hängt davon ab, ob wir Nutzer um eine Einwilligung bitten. Falls die
|
||||
Nutzer einwilligen, ist die Rechtsgrundlage der Verarbeitung Ihrer Daten
|
||||
die erklärte Einwilligung. Andernfalls werden die mithilfe von Cookies
|
||||
verarbeiteten Daten auf Grundlage unserer berechtigten Interessen (z. B.
|
||||
an einem betriebswirtschaftlichen Betrieb unseres Onlineangebotes und
|
||||
Verbesserung seiner Nutzbarkeit) verarbeitet oder, wenn dies im Rahmen
|
||||
der Erfüllung unserer vertraglichen Pflichten erfolgt, wenn der Einsatz
|
||||
von Cookies erforderlich ist, um unsere vertraglichen Verpflichtungen zu
|
||||
erfüllen. Zu welchen Zwecken die Cookies von uns verarbeitet werden,
|
||||
darüber klären wir im Laufe dieser Datenschutzerklärung oder im Rahmen
|
||||
von unseren Einwilligungs- und Verarbeitungsprozessen auf.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Speicherdauer: </strong>Im Hinblick auf die Speicherdauer werden
|
||||
die folgenden Arten von Cookies unterschieden:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong
|
||||
>Temporäre Cookies (auch: Session- oder Sitzungs-Cookies):</strong
|
||||
> Temporäre Cookies werden spätestens gelöscht, nachdem ein Nutzer ein
|
||||
Online-Angebot verlassen und sein Endgerät (z. B. Browser oder mobile
|
||||
Applikation) geschlossen hat.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Permanente Cookies:</strong> Permanente Cookies bleiben auch
|
||||
nach dem Schließen des Endgerätes gespeichert. So können
|
||||
beispielsweise der Login-Status gespeichert oder bevorzugte Inhalte
|
||||
direkt angezeigt werden, wenn der Nutzer eine Website erneut besucht.
|
||||
Ebenso können die mit Hilfe von Cookies erhobenen Daten der Nutzer zur
|
||||
Reichweitenmessung verwendet werden. Sofern wir Nutzern keine
|
||||
expliziten Angaben zur Art und Speicherdauer von Cookies mitteilen
|
||||
(z. B. im Rahmen der Einholung der Einwilligung), sollten Nutzer davon
|
||||
ausgehen, dass Cookies permanent sind und die Speicherdauer bis zu
|
||||
zwei Jahre betragen kann.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong
|
||||
>Allgemeine Hinweise zum Widerruf und Widerspruch (sog. "Opt-Out"): </strong
|
||||
>Nutzer können die von ihnen abgegebenen Einwilligungen jederzeit
|
||||
widerrufen und der Verarbeitung entsprechend den gesetzlichen Vorgaben
|
||||
widersprechen. Hierzu können Nutzer unter anderem die Verwendung von
|
||||
Cookies in den Einstellungen ihres Browsers einschränken (wobei dadurch
|
||||
auch die Funktionalität unseres Onlineangebotes eingeschränkt sein
|
||||
kann). Ein Widerspruch gegen die Verwendung von Cookies zu
|
||||
Online-Marketing-Zwecken kann auch über die Websites
|
||||
<a href="https://optout.aboutads.info/" target="_new"
|
||||
>https://optout.aboutads.info</a
|
||||
>
|
||||
und
|
||||
<a href="https://www.youronlinechoices.com/" target="_new"
|
||||
>https://www.youronlinechoices.com/</a
|
||||
>
|
||||
erklärt werden.
|
||||
</p>
|
||||
<ul class="m-elements">
|
||||
<li class="">
|
||||
<strong>Rechtsgrundlagen:</strong> Berechtigte Interessen (Art. 6 Abs.
|
||||
1 S. 1 lit. f) DSGVO). Einwilligung (Art. 6 Abs. 1 S. 1 lit. a)
|
||||
DSGVO).
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong
|
||||
>Weitere Hinweise zu Verarbeitungsprozessen, Verfahren und
|
||||
Diensten:</strong
|
||||
>
|
||||
</p>
|
||||
<ul class="m-elements">
|
||||
<li>
|
||||
<strong
|
||||
>Verarbeitung von Cookie-Daten auf Grundlage einer Einwilligung: </strong
|
||||
>Wir setzen ein Verfahren zum Cookie-Einwilligungs-Management ein, in
|
||||
dessen Rahmen die Einwilligungen der Nutzer in den Einsatz von
|
||||
Cookies, bzw. der im Rahmen des
|
||||
Cookie-Einwilligungs-Management-Verfahrens genannten Verarbeitungen
|
||||
und Anbieter eingeholt sowie von den Nutzern verwaltet und widerrufen
|
||||
werden können. Hierbei wird die Einwilligungserklärung gespeichert, um
|
||||
deren Abfrage nicht erneut wiederholen zu müssen und die Einwilligung
|
||||
entsprechend der gesetzlichen Verpflichtung nachweisen zu können. Die
|
||||
Speicherung kann serverseitig und/oder in einem Cookie (sogenanntes
|
||||
Opt-In-Cookie, bzw. mithilfe vergleichbarer Technologien) erfolgen, um
|
||||
die Einwilligung einem Nutzer, bzw. dessen Gerät zuordnen zu können.
|
||||
Vorbehaltlich individueller Angaben zu den Anbietern von
|
||||
Cookie-Management-Diensten, gelten die folgenden Hinweise: Die Dauer
|
||||
der Speicherung der Einwilligung kann bis zu zwei Jahren betragen.
|
||||
Hierbei wird ein pseudonymer Nutzer-Identifikator gebildet und mit dem
|
||||
Zeitpunkt der Einwilligung, Angaben zur Reichweite der Einwilligung
|
||||
(z. B. welche Kategorien von Cookies und/oder Diensteanbieter) sowie
|
||||
dem Browser, System und verwendeten Endgerät gespeichert;
|
||||
<span class=""
|
||||
><strong>Rechtsgrundlagen:</strong> Einwilligung (Art. 6 Abs. 1 S. 1
|
||||
lit. a) DSGVO).</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="m225">Bereitstellung des Onlineangebotes und Webhosting</h2>
|
||||
<p>
|
||||
Wir verarbeiten die Daten der Nutzer, um ihnen unsere Online-Dienste zur
|
||||
Verfügung stellen zu können. Zu diesem Zweck verarbeiten wir die
|
||||
IP-Adresse des Nutzers, die notwendig ist, um die Inhalte und Funktionen
|
||||
unserer Online-Dienste an den Browser oder das Endgerät der Nutzer zu
|
||||
übermitteln.
|
||||
</p>
|
||||
<ul class="m-elements">
|
||||
<li>
|
||||
<strong>Verarbeitete Datenarten:</strong> Nutzungsdaten (z. B.
|
||||
besuchte Webseiten, Interesse an Inhalten, Zugriffszeiten); Meta-,
|
||||
Kommunikations- und Verfahrensdaten (z. .B. IP-Adressen, Zeitangaben,
|
||||
Identifikationsnummern, Einwilligungsstatus).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Betroffene Personen:</strong> Nutzer (z. .B.
|
||||
Webseitenbesucher, Nutzer von Onlinediensten).
|
||||
</li>
|
||||
<li>
|
||||
<strong>Zwecke der Verarbeitung:</strong> Bereitstellung unseres
|
||||
Onlineangebotes und Nutzerfreundlichkeit; Informationstechnische
|
||||
Infrastruktur (Betrieb und Bereitstellung von Informationssystemen und
|
||||
technischen Geräten (Computer, Server etc.).). Sicherheitsmaßnahmen.
|
||||
</li>
|
||||
<li class="">
|
||||
<strong>Rechtsgrundlagen:</strong> Berechtigte Interessen (Art. 6 Abs.
|
||||
1 S. 1 lit. f) DSGVO).
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<strong
|
||||
>Weitere Hinweise zu Verarbeitungsprozessen, Verfahren und
|
||||
Diensten:</strong
|
||||
>
|
||||
</p>
|
||||
<ul class="m-elements">
|
||||
<li>
|
||||
<strong
|
||||
>Bereitstellung Onlineangebot auf eigener/ dedizierter
|
||||
Serverhardware: </strong
|
||||
>Für die Bereitstellung unseres Onlineangebotes nutzen wir von uns
|
||||
betriebene Serverhardware sowie den damit verbundenen Speicherplatz,
|
||||
die Rechenkapazität und die Software;
|
||||
<span class=""
|
||||
><strong>Rechtsgrundlagen:</strong> Berechtigte Interessen (Art. 6
|
||||
Abs. 1 S. 1 lit. f) DSGVO).</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Erhebung von Zugriffsdaten und Logfiles: </strong>Der Zugriff
|
||||
auf unser Onlineangebot wird in Form von so genannten
|
||||
"Server-Logfiles" protokolliert. Zu den Serverlogfiles können die
|
||||
Adresse und Name der abgerufenen Webseiten und Dateien, Datum und
|
||||
Uhrzeit des Abrufs, übertragene Datenmengen, Meldung über
|
||||
erfolgreichen Abruf, Browsertyp nebst Version, das Betriebssystem des
|
||||
Nutzers, Referrer URL (die zuvor besuchte Seite) und im Regelfall
|
||||
IP-Adressen und der anfragende Provider gehören. Die Serverlogfiles
|
||||
können zum einen zu Zwecken der Sicherheit eingesetzt werden, z. B.,
|
||||
um eine Überlastung der Server zu vermeiden (insbesondere im Fall von
|
||||
missbräuchlichen Angriffen, sogenannten DDoS-Attacken) und zum
|
||||
anderen, um die Auslastung der Server und ihre Stabilität
|
||||
sicherzustellen;
|
||||
<span class=""
|
||||
><strong>Rechtsgrundlagen:</strong> Berechtigte Interessen (Art. 6
|
||||
Abs. 1 S. 1 lit. f) DSGVO). </span
|
||||
><strong>Löschung von Daten:</strong> Logfile-Informationen werden für
|
||||
die Dauer von maximal 30 Tagen gespeichert und danach gelöscht oder
|
||||
anonymisiert. Daten, deren weitere Aufbewahrung zu Beweiszwecken
|
||||
erforderlich ist, sind bis zur endgültigen Klärung des jeweiligen
|
||||
Vorfalls von der Löschung ausgenommen.
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="m182">Kontakt- und Anfragenverwaltung</h2>
|
||||
<p>
|
||||
Bei der Kontaktaufnahme mit uns (z. B. per Post, Kontaktformular,
|
||||
E-Mail, Telefon oder via soziale Medien) sowie im Rahmen bestehender
|
||||
Nutzer- und Geschäftsbeziehungen werden die Angaben der anfragenden
|
||||
Personen verarbeitet soweit dies zur Beantwortung der Kontaktanfragen
|
||||
und etwaiger angefragter Maßnahmen erforderlich ist.
|
||||
</p>
|
||||
<ul class="m-elements">
|
||||
<li>
|
||||
<strong>Verarbeitete Datenarten:</strong> Kontaktdaten (z. B. E-Mail,
|
||||
Telefonnummern); Inhaltsdaten (z. B. Eingaben in Onlineformularen);
|
||||
Nutzungsdaten (z. B. besuchte Webseiten, Interesse an Inhalten,
|
||||
Zugriffszeiten); Meta-, Kommunikations- und Verfahrensdaten (z. .B.
|
||||
IP-Adressen, Zeitangaben, Identifikationsnummern,
|
||||
Einwilligungsstatus).
|
||||
</li>
|
||||
<li><strong>Betroffene Personen:</strong> Kommunikationspartner.</li>
|
||||
<li>
|
||||
<strong>Zwecke der Verarbeitung:</strong> Kontaktanfragen und
|
||||
Kommunikation; Verwaltung und Beantwortung von Anfragen; Feedback
|
||||
(z.B. Sammeln von Feedback via Online-Formular). Bereitstellung
|
||||
unseres Onlineangebotes und Nutzerfreundlichkeit.
|
||||
</li>
|
||||
<li class="">
|
||||
<strong>Rechtsgrundlagen:</strong> Berechtigte Interessen (Art. 6 Abs.
|
||||
1 S. 1 lit. f) DSGVO).
|
||||
</li>
|
||||
</ul>
|
||||
<p class="seal">
|
||||
<a
|
||||
href="https://datenschutz-generator.de/"
|
||||
rel="noopener noreferrer nofollow"
|
||||
target="_blank"
|
||||
title="Rechtstext von Dr. Schwenke - für weitere Informationen bitte anklicken."
|
||||
>Erstellt mit kostenlosem Datenschutz-Generator.de von Dr. Thomas
|
||||
Schwenke</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
41
frontend/src/main.ts
Normal file
41
frontend/src/main.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { createApp } from "vue";
|
||||
import "./style.css";
|
||||
import App from "./App.vue";
|
||||
import PrimeVue from "primevue/config";
|
||||
import Button from "primevue/button";
|
||||
import Dropdown from "primevue/dropdown";
|
||||
import Menubar from "primevue/menubar";
|
||||
import InputText from "primevue/inputtext";
|
||||
import Card from "primevue/card";
|
||||
import DataView from "primevue/dataview";
|
||||
import ToggleButton from "primevue/togglebutton";
|
||||
import "primevue/resources/themes/viva-dark/theme.css";
|
||||
import "primeicons/primeicons.css";
|
||||
import "primeflex/primeflex.css";
|
||||
import router from "./router";
|
||||
import TabView from "primevue/tabview";
|
||||
import TabPanel from "primevue/tabpanel";
|
||||
import { createPinia } from "pinia";
|
||||
import MultiSelect from "primevue/multiselect";
|
||||
import ToastService from "primevue/toastservice";
|
||||
import Toast from "primevue/toast";
|
||||
|
||||
const app = createApp(App);
|
||||
const pinia = createPinia();
|
||||
|
||||
app.use(PrimeVue);
|
||||
app.use(router);
|
||||
app.use(ToastService);
|
||||
app.use(pinia);
|
||||
app.component("Button", Button);
|
||||
app.component("Menubar", Menubar);
|
||||
app.component("Dropdown", Dropdown);
|
||||
app.component("InputText", InputText);
|
||||
app.component("Card", Card);
|
||||
app.component("DataView", DataView);
|
||||
app.component("ToggleButton", ToggleButton);
|
||||
app.component("TabView", TabView);
|
||||
app.component("TabPanel", TabPanel);
|
||||
app.component("MultiSelect", MultiSelect);
|
||||
app.component("Toast", Toast);
|
||||
app.mount("#app");
|
6
frontend/src/model/module.ts
Normal file
6
frontend/src/model/module.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export class Module {
|
||||
constructor(
|
||||
public Name: string,
|
||||
public Course: string,
|
||||
) {}
|
||||
}
|
49
frontend/src/router/index.ts
Normal file
49
frontend/src/router/index.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import Faq from "../components/FaqPage.vue";
|
||||
import CourseSelection from "../components/CourseSelection.vue";
|
||||
import AdditionalModules from "../components/AdditionalModules.vue";
|
||||
import CalendarLink from "../components/CalendarLink.vue";
|
||||
import Impress from "../components/Impress.vue";
|
||||
import PrivacyPolicy from "../components/PrivacyPolicy.vue";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: "/",
|
||||
name: "course-selection",
|
||||
component: CourseSelection,
|
||||
},
|
||||
{
|
||||
path: "/faq",
|
||||
name: "faq",
|
||||
component: Faq,
|
||||
},
|
||||
{
|
||||
path: "/additional-modules",
|
||||
name: "additional-modules",
|
||||
component: AdditionalModules,
|
||||
},
|
||||
{
|
||||
path: "/calendar-link",
|
||||
name: "calendar-link",
|
||||
component: CalendarLink,
|
||||
},
|
||||
{
|
||||
path: "/privacy-policy",
|
||||
name: "privacy-policy",
|
||||
component: PrivacyPolicy,
|
||||
},
|
||||
{
|
||||
path: "/impress",
|
||||
name: "impress",
|
||||
component: Impress,
|
||||
},
|
||||
{
|
||||
path: "/:catchAll(.*)",
|
||||
redirect: "/",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export default router;
|
18
frontend/src/store/moduleStore.ts
Normal file
18
frontend/src/store/moduleStore.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Module } from "../model/module.ts";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
const moduleStore = defineStore("moduleStore", {
|
||||
state: () => ({
|
||||
modules: [] as Module[],
|
||||
}),
|
||||
actions: {
|
||||
addModule(module: Module) {
|
||||
this.modules.push(module);
|
||||
},
|
||||
removeModule(module: Module) {
|
||||
this.modules.splice(this.modules.indexOf(module), 1);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default moduleStore;
|
17
frontend/src/store/tokenStore.ts
Normal file
17
frontend/src/store/tokenStore.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
const tokenStore = defineStore("tokenStore", {
|
||||
state: () => ({
|
||||
token: "",
|
||||
}),
|
||||
actions: {
|
||||
setToken(token: string) {
|
||||
this.token = token;
|
||||
},
|
||||
removeToken() {
|
||||
this.token = "";
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default tokenStore;
|
3
frontend/src/style.css
Normal file
3
frontend/src/style.css
Normal file
@@ -0,0 +1,3 @@
|
||||
body {
|
||||
font-family: var(--font-family);
|
||||
}
|
1
frontend/src/vite-env.d.ts
vendored
Normal file
1
frontend/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
Reference in New Issue
Block a user