Cleanup dates/appointments handling in app

This commit is contained in:
Daniel Egger 2024-04-19 11:00:00 +02:00
parent 905d7a5290
commit 4925c1a178
9 changed files with 92 additions and 216 deletions

View File

@ -1,45 +0,0 @@
<script setup lang="ts">
import DueDatesList from "@/components/dueDates/DueDatesList.vue";
import { useCourseSessionsStore } from "@/stores/courseSessions";
import { useDashboardStore } from "@/stores/dashboard";
import { getCockpitUrl } from "@/utils/utils";
const dashboardStore = useDashboardStore();
const courseSessionsStore = useCourseSessionsStore();
const allDueDates = courseSessionsStore.allDueDates();
</script>
<template>
<template v-if="dashboardStore.currentDashboardConfig">
<h4 class="mb-6 text-xl font-bold">{{ $t("a.Aktueller Lehrgang") }}</h4>
<div class="mb-6 border border-gray-300 p-6">
<h3 class="mb-6">{{ dashboardStore.currentDashboardConfig.name }}</h3>
<router-link
class="btn-blue"
target="_blank"
:to="getCockpitUrl(dashboardStore.currentDashboardConfig.slug)"
>
{{ $t("a.Cockpit anschauen") }}
</router-link>
</div>
</template>
<router-link
v-if="dashboardStore.dashboardConfigs.length > 1"
class="block text-sm underline"
to="/statistic/list"
>
{{ $t("a.Alle Lehrgänge anzeigen") }}
</router-link>
<h3 class="mb-6 mt-16 text-xl font-bold">{{ $t("a.AlleTermine") }}</h3>
<DueDatesList
:due-dates="allDueDates"
:max-count="13"
:show-top-border="true"
:show-all-due-dates-link="true"
:show-bottom-border="true"
:show-course-session="true"
></DueDatesList>
</template>

View File

@ -1,19 +0,0 @@
<script setup lang="ts">
import DueDatesList from "@/components/dueDates/DueDatesList.vue";
import { useCourseSessionsStore } from "@/stores/courseSessions";
const courseSessionsStore = useCourseSessionsStore();
const allDueDates = courseSessionsStore.allDueDates();
</script>
<template>
<h4 class="mb-6 text-xl font-bold">{{ $t("a.AlleTermine") }}</h4>
<DueDatesList
:due-dates="allDueDates"
:max-count="13"
:show-top-border="true"
:show-all-due-dates-link="true"
:show-bottom-border="true"
:show-course-session="true"
></DueDatesList>
</template>

View File

@ -1,12 +1,11 @@
<script lang="ts" setup>
import type { CourseSession, DueDate } from "@/types";
import { useCourseSessionsStore } from "@/stores/courseSessions";
import { useTranslation } from "i18next-vue";
import type { DashboardDueDate } from "@/services/dashboard";
import { computed } from "vue";
import dayjs from "dayjs";
const props = defineProps<{
dueDate: DueDate;
dueDate: DashboardDueDate;
singleLine?: boolean;
showCourseSession?: boolean;
}>();
@ -15,27 +14,28 @@ const { t } = useTranslation();
const dateType = t(props.dueDate.date_type_translation_key);
const assignmentType = t(props.dueDate.assignment_type_translation_key);
const courseSessionsStore = useCourseSessionsStore();
const courseSession = courseSessionsStore.allCourseSessions.find(
(cs: CourseSession) => cs.id === props.dueDate.course_session_id
);
if (!courseSession) {
throw new Error("Course session not found");
const urlText = computed(() => {
let result = "";
if (dateType) {
result += dateType;
}
const url = courseSession.actions.includes("expert-cockpit")
? props.dueDate.url_expert
: props.dueDate.url;
const courseSessionTitle = computed(() => {
if (props.dueDate.course_session_id) {
return (
courseSessionsStore.getCourseSessionById(props.dueDate.course_session_id)
?.title ?? ""
);
if (assignmentType && !props.dueDate.title.startsWith(assignmentType)) {
result += " " + assignmentType;
}
return "";
if (props.dueDate.title) {
result += " " + props.dueDate.title;
}
return result.trim();
});
const url = computed(() => {
if (["SUPERVISOR", "EXPERT"].includes(props.dueDate.course_session.my_role)) {
return props.dueDate.url_expert;
}
return props.dueDate.url;
});
</script>
@ -46,29 +46,23 @@ const courseSessionTitle = computed(() => {
>
<div class="space-y-1">
<div>
<a class="underline" :href="url">
<span class="text-bold">
<a :href="url">
<span class="text-bold text-gray-900">
{{ dayjs(props.dueDate.start).format("dddd D. MMMM YYYY") }}
</span>
</a>
</div>
<div class="flex gap-1">
<div v-if="dateType">
{{ dateType }}
</div>
<div v-if="assignmentType && !props.dueDate.title.startsWith(assignmentType)">
{{ assignmentType }}
</div>
<div v-if="props.dueDate.title">
{{ props.dueDate.title }}
</div>
<div>
<a class="underline" :href="url">
<span class="text-bold">
{{ urlText }}
</span>
</a>
</div>
<div class="text-small text-gray-900">
<div>
<span v-if="props.showCourseSession ?? courseSessionTitle">
{{ courseSessionTitle }}:
<span v-if="props.dueDate.course_session.is_uk">
{{ props.dueDate.course_session.session_title }}:
</span>
{{ $t("a.Circle") }} «{{ props.dueDate.circle?.title }}»
</div>

View File

@ -1,11 +1,11 @@
<script lang="ts" setup>
import DueDateSingle from "@/components/dueDates/DueDateSingle.vue";
import type { DueDate } from "@/types";
import { computed } from "vue";
import type { DashboardDueDate } from "@/services/dashboard";
const props = defineProps<{
maxCount: number;
dueDates: DueDate[];
dueDates: DashboardDueDate[];
showTopBorder: boolean;
showBottomBorder: boolean;
showAllDueDatesLink: boolean;

View File

@ -1,37 +0,0 @@
<script lang="ts" setup>
import { useTranslation } from "i18next-vue";
import type { DashboardDueDate } from "@/services/dashboard";
import dayjs from "dayjs";
const props = defineProps<{
dueDate: DashboardDueDate;
}>();
const { t } = useTranslation();
const dateType = t(props.dueDate.date_type_translation_key);
const assignmentType = t(props.dueDate.assignment_type_translation_key);
</script>
<template>
<article class="my-4">
<div class="text-bold text-gray-900">
{{ dayjs(props.dueDate.start).format("dd. DD. MMMM YYYY") }}
</div>
<div v-if="dateType" class="text-bold">
{{ dateType }}
<span v-if="assignmentType && !props.dueDate.title.startsWith(assignmentType)">
{{ assignmentType }}
</span>
</div>
<div v-if="props.dueDate.title">
{{ props.dueDate.title }}
</div>
<div v-if="props.dueDate.course_session.is_uk" class="text-gray-900">
{{ props.dueDate.course_session.session_title }}
{{ props.dueDate.circle?.title ?? "" }}
</div>
</article>
</template>

View File

@ -4,7 +4,7 @@ import log from "loglevel";
import { useDashboardPersons } from "@/composables";
import { computed } from "vue";
import _ from "lodash";
import DashboardAsideDueDate from "@/pages/dashboard/DashboardAsideDueDate.vue";
import DueDateSingle from "@/components/dueDates/DueDateSingle.vue";
log.debug("DashboardAsideWidget created");
@ -34,7 +34,7 @@ const displayDueDates = computed(() => {
<div v-for="dueDate in displayDueDates" :key="dueDate.id">
<div class="border-b">
<DashboardAsideDueDate :due-date="dueDate" />
<DueDateSingle :due-date="dueDate" />
</div>
</div>

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
import log from "loglevel";
import { useCourseData, useDashboardPersons } from "@/composables";
import { useDashboardPersons } from "@/composables";
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import { computed, ref, watch } from "vue";
import { useTranslation } from "i18next-vue";
@ -117,30 +117,54 @@ const filtersVisible = computed(() => {
);
});
const initialItemCircle: DropboxItem = {
const circles = computed(() => {
const dueDatesBySelectedCourse = dashboardDueDates.value.filter((dueDate) => {
if (selectedCourse.value.id === UNFILTERED) {
return true;
}
return dueDate.course_session.course_id === selectedCourse.value.id;
});
const circleList = _(dueDatesBySelectedCourse)
.filter((dueDate) => {
return !!dueDate.circle;
})
.map((dueDate) => {
return {
name: dueDate.circle?.title ?? "",
id: dueDate.circle?.id ?? "",
};
})
.uniqBy("id")
.orderBy("name")
.value();
return [
{
id: UNFILTERED,
name: t("a.AlleCircle"),
};
const circles = ref<DropboxItem[]>([initialItemCircle]);
},
...circleList,
];
});
const selectedCircle = ref<DropboxItem>(circles.value[0]);
async function loadCircleValues() {
if (selectedCourse.value && selectedCourse.value.slug) {
const learningPathQuery = useCourseData(selectedCourse.value.slug);
await learningPathQuery.resultPromise;
circles.value = [
initialItemCircle,
...(learningPathQuery.circles.value ?? []).map((circle) => ({
id: circle.id,
name: circle.title,
})),
];
} else {
circles.value = [initialItemCircle];
}
selectedCircle.value = circles.value[0];
}
// async function loadCircleValues() {
// if (selectedCourse.value && selectedCourse.value.slug) {
// const learningPathQuery = useCourseData(selectedCourse.value.slug);
// await learningPathQuery.resultPromise;
// circles.value = [
// initialItemCircle,
// ...(learningPathQuery.circles.value ?? []).map((circle) => ({
// id: circle.id,
// name: circle.title,
// })),
// ];
// } else {
// circles.value = [initialItemCircle];
// }
//
// selectedCircle.value = circles.value[0];
// }
const dueDateTypes = computed(() => {
const types = _(dashboardDueDates.value)
@ -167,7 +191,7 @@ const selectedType = ref<DropboxItem>(dueDateTypes.value[0]);
watch(selectedCourse, async () => {
selectedSession.value = courseSessions.value[0];
await loadCircleValues();
selectedCircle.value = circles.value[0];
});
</script>
@ -194,7 +218,6 @@ watch(selectedCourse, async () => {
class="flex flex-col space-x-0 border-b bg-white lg:flex-row lg:space-x-3"
>
<ItDropdownSelect
v-if="courses.length > 2"
v-model="selectedCourse"
data-cy="session-select"
:items="courses"
@ -202,7 +225,6 @@ watch(selectedCourse, async () => {
></ItDropdownSelect>
<ItDropdownSelect
v-if="courseSessions.length > 2"
v-model="selectedSession"
data-cy="session-select"
:items="courseSessions"
@ -210,7 +232,6 @@ watch(selectedCourse, async () => {
></ItDropdownSelect>
<ItDropdownSelect
v-if="circles.length > 2"
v-model="selectedCircle"
data-cy="appointments-circle-select"
:items="circles"
@ -218,7 +239,6 @@ watch(selectedCourse, async () => {
></ItDropdownSelect>
<ItDropdownSelect
v-if="dueDateTypes.length > 2"
v-model="selectedType"
data-cy="appointments-type-select"
:items="dueDateTypes"

View File

@ -1,36 +1,15 @@
<script setup lang="ts">
import type { Component } from "vue";
import { onMounted } from "vue";
import StatisticPage from "@/pages/dashboard/StatisticPage.vue";
import ProgressPage from "@/pages/dashboard/ProgressPage.vue";
import SimpleDates from "@/components/dashboard/SimpleDates.vue";
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
import { useDashboardStore } from "@/stores/dashboard";
import type { DashboardType } from "@/gql/graphql";
import type { DashboardCourseConfigType } from "@/services/dashboard";
import SimpleCoursePage from "@/pages/dashboard/SimpleCoursePage.vue";
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
import NoCourseSession from "@/components/dashboard/NoCourseSession.vue";
import MentorPage from "@/pages/dashboard/MentorPage.vue";
import CoursePanel from "@/components/dashboard/CoursePanel.vue";
import DashboardAsideWidget from "@/pages/dashboard/DashboardAsideWidget.vue";
const dashboardStore = useDashboardStore();
interface DashboardPage {
main: Component;
aside: Component;
}
const boards: Record<DashboardType, DashboardPage> = {
PROGRESS_DASHBOARD: { main: ProgressPage, aside: SimpleDates },
SIMPLE_DASHBOARD: { main: SimpleCoursePage, aside: SimpleDates },
STATISTICS_DASHBOARD: { main: StatisticPage, aside: CourseDetailDates },
MENTOR_DASHBOARD: { main: MentorPage, aside: SimpleDates },
PRAXISBILDNER_DASHBOARD: { main: CoursePanel, aside: SimpleDates },
};
onMounted(async () => {
await dashboardStore.loadDashboardDetails();
});
@ -68,23 +47,6 @@ function newDashboardConfigForId(id: string): DashboardCourseConfigType | undefi
<CoursePanel :course-config="newDashboardConfigForId(config.course_id)" />
</li>
</ul>
<!-- end of new way of dashboard -->
<!-- keep until we unify the dashboard -->
<!-- <CoursePanel-->
<!-- v-if="-->
<!-- ['PRAXISBILDNER_DASHBOARD', 'PROGRESS_DASHBOARD'].includes(-->
<!-- dashboardStore.currentDashboardConfig.dashboard_type-->
<!-- )-->
<!-- "-->
<!-- :course-config="-->
<!-- newDashboardConfigForId(dashboardStore.currentDashboardConfig.id)-->
<!-- "-->
<!-- />-->
<!-- <component-->
<!-- :is="boards[dashboardStore.currentDashboardConfig.dashboard_type].main"-->
<!-- v-else-->
<!-- ></component>-->
<!-- end of old way of dashboard -->
</div>
</main>
<aside class="lg:order-2 lg:w-[384px] xl:w-[512px]">

View File

@ -248,12 +248,13 @@ def get_dashboard_due_dates(request):
due_dates = []
today = date.today()
for due_date in all_due_dates:
if due_date.end:
if due_date.end.date() >= today:
due_dates.append(due_date)
elif due_date.start:
if due_date.start.date() >= today:
due_dates.append(due_date)
# if due_date.end:
# if due_date.end.date() >= today:
# due_dates.append(due_date)
# elif due_date.start:
# if due_date.start.date() >= today:
# due_dates.append(due_date)
due_dates.sort(key=lambda x: x.start)