Skip to content

Commit

Permalink
Glob import fix (#285)
Browse files Browse the repository at this point in the history
* fix: glob imports

* chore: linting
  • Loading branch information
EwoutV authored Apr 10, 2024
1 parent ab02dc0 commit 97b2116
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 57 deletions.
12 changes: 3 additions & 9 deletions frontend/src/components/courses/CourseDetailCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Button from 'primevue/button';
import { type Course } from '@/types/Course.ts';
import { PrimeIcons } from 'primevue/api';
import { useI18n } from 'vue-i18n';
import { useGlob } from '@/composables/glob.ts';
/* Component props */
defineProps<{
Expand All @@ -12,14 +13,7 @@ defineProps<{
/* Composable injections */
const { t } = useI18n();
/* Default image thumbnails */
const images = Object.keys(
import.meta.glob('@/assets/img/placeholders/*', {
eager: true,
query: 'url',
}),
);
const { getRandomImport } = useGlob(import.meta.glob('@/assets/img/placeholders/*.png', { eager: true }));
</script>

<template>
Expand All @@ -29,7 +23,7 @@ const images = Object.keys(
class="w-full h-12rem border-round-top"
style="object-fit: cover; margin-bottom: -4px"
:alt="course.name ?? ''"
:src="images[Math.ceil(Math.random() * images.length) % images.length]"
:src="getRandomImport()"
/>
</template>
<template #title>
Expand Down
24 changes: 3 additions & 21 deletions frontend/src/components/courses/CourseGeneralCard.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup lang="ts">
import StudentCourseJoinButton from '@/components/courses/students/StudentCourseJoinButton.vue';
import type { Course } from '@/types/Course.ts';
import { type Faculty } from '@/types/Faculty.ts';
import { useAuthStore } from '@/store/authentication.store.ts';
import { storeToRefs } from 'pinia';
import { type Student } from '@/types/users/Student.ts';
import { useGlob } from '@/composables/glob.ts';
/* Props */
defineProps<{
Expand All @@ -15,31 +15,13 @@ defineProps<{
const { user } = storeToRefs(useAuthStore());
/* State */
const images = Object.keys(
import.meta.glob('@/assets/img/faculties/*', {
eager: true,
query: 'url',
}),
);
/**
* Get the faculty icon based on the faculty id.
* @param faculty
*/
function getFacultyIcon(faculty: Faculty): string {
return (
images.find((image) => {
image = image.replace('/src/assets/img/faculties/', '');
return image === faculty.id + '.png';
}) ?? ''
);
}
const { getImport } = useGlob(import.meta.glob('@/assets/img/faculties/*.png', { eager: true }));
</script>

<template>
<div class="surface-300 pl-7 p-4 relative">
<img
:src="getFacultyIcon(course.faculty)"
:src="getImport(course.faculty.id + '.png')"
:alt="course.faculty.name"
class="absolute top-0 left-0 w-3rem"
v-if="course.faculty !== null"
Expand Down
77 changes: 51 additions & 26 deletions frontend/src/components/projects/ProjectList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import { useProject } from '@/composables/services/project.service.ts';
import ProjectCard from '@/components/projects/ProjectCard.vue';
import { useI18n } from 'vue-i18n';
import moment from 'moment';
import Skeleton from 'primevue/skeleton';
/* Props */
const props = withDefaults(
defineProps<{
courses: Course[];
courses: Course[] | null;
showPast?: boolean;
cols?: number;
}>(),
{
courses: () => [],
showPast: false,
cols: 4,
},
);
Expand All @@ -25,34 +28,39 @@ const { projects, getProjectsByCourse } = useProject();
/* State */
// The merged projects from all courses
const allProjects = computed(() => props.courses.flatMap((course) => course.projects));
const allProjects = computed(() => props.courses?.flatMap((course) => course.projects) ?? null);
/**
* Sorts the projects by deadline
*/
const sortedProjects = computed(() => {
const projects = allProjects.value.filter((project) =>
!props.showPast ? moment(project.deadline).isAfter() : true,
);
const projects =
allProjects.value?.filter((project) => (!props.showPast ? moment(project.deadline).isAfter() : true)) ?? null;
if (projects === null) {
return projects;
}
return [...projects].sort((a, b) => new Date(a.deadline).getTime() - new Date(b.deadline).getTime());
});
/* Watchers */
watch(
() => props.courses,
async (courses: Course[]) => {
for (const course of courses) {
// Fetch the projects for the course
await getProjectsByCourse(course.id);
async (courses: Course[] | null) => {
if (courses !== null) {
for (const course of courses) {
// Fetch the projects for the course
await getProjectsByCourse(course.id);
// Assign the course to the projects
projects.value?.forEach((project) => {
project.course = course;
});
// Assign the course to the projects
projects.value?.forEach((project) => {
project.course = course;
});
// Assign the projects to the course
course.projects = projects.value ?? [];
// Assign the projects to the course
course.projects = projects.value ?? [];
}
}
},
{
Expand All @@ -62,18 +70,35 @@ watch(
</script>

<template>
<template v-if="allProjects.length > 0">
<div class="grid align-items-stretch">
<div class="col-12 md:col-6 lg:col-4 xl:col-3" v-for="project in sortedProjects" :key="project.id">
<ProjectCard class="h-100" :project="project" :course="project.course" v-if="project.course !== null" />
<div class="grid align-items-stretch">
<template v-if="sortedProjects !== null">
<template v-if="sortedProjects.length > 0">
<div
class="col-12 md:col-6 lg:col-4"
:class="'xl:col-' + 12 / cols"
v-for="project in sortedProjects"
:key="project.id"
>
<ProjectCard
class="h-100"
:project="project"
:course="project.course"
v-if="project.course !== null"
/>
</div>
</template>
<template v-else>
<div class="col-12">
<p>{{ t('views.dashboard.no_projects') }}</p>
</div>
</template>
</template>
<template v-else>
<div class="col-12 md:col-6 lg:col-4" :class="'xl:col-' + 12 / cols" v-for="index in cols" :key="index">
<Skeleton height="25rem" />
</div>
</div>
</template>
<template v-else>
<div class="col-12">
<p>{{ t('views.dashboard.no_projects') }}</p>
</div>
</template>
</template>
</div>
</template>

<style scoped lang="scss"></style>
42 changes: 42 additions & 0 deletions frontend/src/composables/glob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export interface GlobModule {
default: any;
}

export interface GlobState {
getRandomImport: () => any;
getImport: (key: string) => any;
}

export function useGlob(glob: Record<string, GlobModule>): GlobState {
/**
* Get a random import from the glob.
*
* @returns A random import from the glob.
*/
function getRandomImport(): any {
const keys = Object.keys(glob);
const randomKey = keys[Math.floor(Math.random() * keys.length)];
return glob[randomKey].default;
}

/**
* Get an import from the glob.
*
* @param key
*/
function getImport(key: string): any {
if (key in glob) {
return glob[key].default;
}

return Object.values(glob).find((module) => {
const parts = module.default.split('/');
return parts[parts.length - 1] === key;
})?.default;
}

return {
getRandomImport,
getImport,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const selectedYear = ref(User.getAcademicYear());
const showPast = ref(false);
const filteredCourses = computed(
() => courses.value?.filter((course) => course.academic_startyear === selectedYear.value) ?? [],
() => courses.value?.filter((course) => course.academic_startyear === selectedYear.value) ?? null,
);
/* Watchers */
Expand Down

0 comments on commit 97b2116

Please sign in to comment.