| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- <template>
- <div class="flex justify-end items-center">
- <button
- v-for="lang in availableLanguages"
- :key="lang"
- class="language-button"
- :disabled="lang == activeLang"
- :title="`Modulabhängigkeits-Sprache ändern auf ${lang}`"
- @click="activeLang = lang"
- >
- {{ lang }}
- </button>
- <div
- v-if="hasData && availableLanguages.length > 0"
- :title="`Die ${SCHOOL_NAME} hat teils Modulbeschreibungen in Deutsch & Englisch. Je nach Sprache des Unterrichts, können sich die Abhängigkeiten ändern. Standardmässig wir die Sprache des Unterrichts ausgewählt, sonst die erst verfügbare Sprache.`"
- class="mx-2 w-5 h-5 text-xs aspect-square rounded-full bg-gray-200 dark:bg-gray-400 inline-flex items-center justify-center cursor-help"
- >
- <font-awesome-icon icon="fa-solid fa-info" />
- </div>
- </div>
- <div class="mt-5">
- <div
- v-if="module && hasEnablers"
- class="flex justify-center flex-wrap gap-3"
- >
- <button
- v-for="dep in module.enablingModules[activeLang]"
- :key="dep"
- class="module-box"
- title="Modulinformationen anzeigen"
- :class="[rowStyling(moduleStore.fromModuleShort(dep), defaultActionBG)]"
- @click="stateStore.inspectingModule = moduleStore.fromModuleShort(dep)"
- >
- {{ dep }}
- </button>
- </div>
- <div
- v-else
- class="flex justify-center flex-wrap gap-3"
- >
- <span class="text-gray-500">Keine Nachfolgemodule</span>
- </div>
- <div class="flex justify-center mt-3">
- <font-awesome-icon icon="fa-solid fa-arrow-up" />
- </div>
- <div class="flex justify-center mt-3">
- <button
- class="module-box font-bold"
- :class="[rowStyling(module, defaultActionBG)]"
- title="Modulinformationen anzeigen"
- @click="stateStore.inspectingModule = module"
- >
- {{ module?.short ?? moduleName }}
- </button>
- </div>
- <div class="flex justify-center mt-3">
- <font-awesome-icon icon="fa-solid fa-arrow-up" />
- </div>
- <div
- v-if="module && hasDeps"
- class="flex justify-center flex-wrap gap-3 mt-3"
- >
- <button
- v-for="dep in module.dependencies[activeLang]"
- :key="dep"
- class="module-box"
- title="Modulinformationen anzeigen"
- :class="[rowStyling(moduleStore.fromModuleShort(dep), defaultActionBG)]"
- @click="stateStore.inspectingModule = moduleStore.fromModuleShort(dep)"
- >
- {{ dep }}
- </button>
- </div>
- <div
- v-else
- class="flex justify-center flex-wrap gap-3 mt-3"
- >
- <span class="text-gray-500">Keine Abhängigkeiten</span>
- </div>
- </div>
- </template>
- <script lang="ts">
- import { PropType } from "vue";
- import { useModulesStore } from "../../stores/modules";
- import { useStateStore } from "../../stores/state";
- import { Module, ModuleLanguages } from "../../types";
- import { rowStyling, SCHOOL_NAME } from "../../helpers";
- function availableLanguages(module: Module): string[] {
- const deps = module.dependencies;
- const langs = Object.keys(deps).filter((o) => deps[o].length > 0);
- const eDeps = module.enablingModules;
- langs.push(...Object.keys(eDeps).filter((o) => eDeps[o].length > 0));
- return [...new Set(langs)];
- }
- export default {
- name: "DependencyTree",
- props: {
- module: {
- required: true,
- type: Object as PropType<Module | null>,
- },
- moduleName: {
- required: true,
- type: String,
- },
- classLanguage: {
- required: false,
- type: String,
- default: ModuleLanguages.DE,
- },
- },
- setup() {
- const stateStore = useStateStore();
- const moduleStore = useModulesStore();
- return {
- stateStore,
- moduleStore,
- rowStyling,
- defaultActionBG: "bg-gray-200 dark:bg-gray-600",
- SCHOOL_NAME,
- };
- },
- data() {
- let lang = this.classLanguage ?? "";
- if (this.module !== null) {
- const available = availableLanguages(this.module);
- if (available.length > 0 && !available.includes(lang))
- lang = available[0];
- }
- return {
- activeLang: lang,
- };
- },
- computed: {
- availableLanguages(): string[] {
- if (this.module === null) return [];
- return availableLanguages(this.module);
- },
- hasDeps(): boolean {
- return (
- this.module !== null &&
- this.module.dependencies[this.activeLang]?.length > 0
- );
- },
- hasEnablers(): boolean {
- return (
- this.module !== null &&
- (this.module.enablingModules[this.activeLang]?.length ?? 0) > 0
- );
- },
- hasData(): boolean {
- return this.hasDeps || this.hasEnablers;
- },
- },
- };
- </script>
- <style scoped>
- .module-box {
- @apply w-28
- py-2
- rounded
- text-center
- hover:bg-gray-300
- active:bg-gray-400
- dark:hover:bg-gray-700
- dark:active:bg-gray-900
- cursor-pointer
- transition-all
- duration-200;
- }
- .language-button {
- @apply text-center
- bg-gray-200
- hover:bg-gray-300
- active:bg-gray-400
- dark:bg-gray-600
- dark:hover:bg-gray-700
- dark:active:bg-gray-900
- rounded
- cursor-pointer
- px-2
- py-0.5
- ml-2
- transition-all
- duration-200
- disabled:dark:bg-blue-600
- disabled:dark:text-gray-300
- disabled:text-gray-400
- disabled:bg-gray-100
- disabled:pointer-events-none;
- }
- </style>
|