Skip to content

Commit

Permalink
Merge pull request #300 from SELab-2/responsive
Browse files Browse the repository at this point in the history
Responsive design improvements
  • Loading branch information
francisvaut committed Apr 12, 2024
2 parents d228e03 + 741d616 commit b2120e1
Show file tree
Hide file tree
Showing 20 changed files with 382 additions and 255 deletions.
2 changes: 1 addition & 1 deletion backend/api/management/commands/make_teacher.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ def handle(self, *args, **options):
return

user = user.get()
Teacher(user_ptr=user).save_base(raw=True)
Teacher.create(user)

self.stdout.write(self.style.SUCCESS('Successfully made the user teacher!'))
Binary file added frontend/src/assets/img/logo-tiny.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 6 additions & 4 deletions frontend/src/assets/lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,13 @@
}
},
"components": {
"buttons": {
"academic_year": "Academiejaar {0}"
"button": {
"academic_year": "Academiejaar {0}",
"createProject": "Maak een nieuw project"
},
"card": {
"open": "Details"
"open": "Details",
"newProject": "Nieuw Project"
},
"submission" : "Indienen"
},
Expand Down Expand Up @@ -147,7 +149,7 @@
"am": "voormiddag",
"apply": "Toepassen",
"cancel": "Annuleer",
"choose": "Kies",
"choose": "Kies een bestand",
"chooseDate": "Kies datum",
"chooseMonth": "Kies maand",
"chooseYear": "Kies jaar",
Expand Down
13 changes: 10 additions & 3 deletions frontend/src/components/courses/CourseDetailCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,16 @@ const { getRandomImport } = useGlob(import.meta.glob('@/assets/img/placeholders/
{{ course.getExcerpt() }}
</template>
<template #footer>
<RouterLink :to="{ name: 'course', params: { courseId: course.id } }">
<Button :icon="PrimeIcons.ARROW_RIGHT" :label="t('components.card.open')" icon-pos="right" outlined />
</RouterLink>
<slot :course="course" name="footer">
<RouterLink :to="{ name: 'course', params: { courseId: course.id } }">
<Button
:icon="PrimeIcons.ARROW_RIGHT"
:label="t('components.card.open')"
icon-pos="right"
outlined
/>
</RouterLink>
</slot>
</template>
</Card>
</template>
Expand Down
24 changes: 17 additions & 7 deletions frontend/src/components/courses/CourseList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import CourseDetailCard from '@/components/courses/CourseDetailCard.vue';
import CourseGeneralCard from '@/components/courses/CourseGeneralCard.vue';
import { type Course } from '@/types/Course.ts';
import { useI18n } from 'vue-i18n';
import { PrimeIcons } from 'primevue/api';
import Button from 'primevue/button';
/* Props */
interface Props {
Expand All @@ -25,13 +27,21 @@ const { t } = useI18n();
<div class="grid align-items-stretch">
<template v-if="courses !== null">
<template v-if="courses.length > 0">
<div
class="col-12 md:col-6 lg:col-4"
:class="'xl:col-' + 12 / cols"
v-for="course in courses"
:key="course.id"
>
<CourseDetailCard :course="course" v-if="detail" />
<div class="col-12 md:col-6" :class="'xl:col-' + 12 / cols" v-for="course in courses" :key="course.id">
<CourseDetailCard :course="course" v-if="detail">
<template #footer="{ course }">
<slot name="footer" :course="course">
<RouterLink :to="{ name: 'course', params: { courseId: course.id } }">
<Button
:icon="PrimeIcons.ARROW_RIGHT"
:label="t('components.card.open')"
icon-pos="right"
outlined
/>
</RouterLink>
</slot>
</template>
</CourseDetailCard>
<CourseGeneralCard class="h-full" :course="course" v-else />
</div>
</template>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/layout/BaseLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Footer from '@/components/layout/Footer.vue';
</script>

<template>
<div id="layout" class="w-12 lg:w-9 mx-auto">
<div id="layout" class="w-12 lg:w-11 xl:w-9 mx-auto h-100">
<Header />

<Body id="body">
Expand All @@ -19,6 +19,7 @@ import Footer from '@/components/layout/Footer.vue';
<style scoped>
#layout {
max-width: 1460px;
height: 100vh;
#body {
min-height: calc(100vh - (180px + 175px));
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/layout/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const logo: Record<string, string> = { nl, en };
</script>

<template>
<div id="footer" class="p-4 py-3">
<div id="footer" class="p-4 py-3 mt-auto">
<div class="w-full lg:w-2 flex align-items-center py-3">
<img class="w-full max-w-9rem" :src="logo[locale]" :alt="t('layout.header.logo')" />
</div>
Expand Down
71 changes: 63 additions & 8 deletions frontend/src/components/layout/Header.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
<script setup lang="ts">
import en from '@/assets/img/logo-en.png';
import nl from '@/assets/img/logo-nl.png';
import tiny from '@/assets/img/logo-tiny.png';
import Button from 'primevue/button';
import LanguageSelector from '@/components/LanguageSelector.vue';
import RoleSelector from '@/components/RoleSelector.vue';
import Sidebar from 'primevue/sidebar';
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
import { computed, ref } from 'vue';
import { useAuthStore } from '@/store/authentication.store.ts';
import { storeToRefs } from 'pinia';
import RoleSelector from '@/components/RoleSelector.vue';
/* Composables */
const { user, isAuthenticated } = storeToRefs(useAuthStore());
const { t, locale } = useI18n();
/* Localization variables */
/* State */
const showSidebar = ref(false);
const logo = computed(() => {
if (locale.value === 'nl') {
return nl;
Expand Down Expand Up @@ -49,14 +53,21 @@ const items = computed(() => [

<template>
<div class="flex w-full">
<div class="w-full lg:w-2 flex align-items-center p-3 lg:pl-0">
<img class="w-full max-w-9rem" :src="logo" :alt="t('layout.header.logo')" />
<!-- Logo -->
<div class="lg:w-2 lg:pl-0 flex align-items-center p-3">
<RouterLink :to="'/'">
<img class="w-full max-w-9rem" :src="logo" :alt="t('layout.header.logo')" />
</RouterLink>
</div>
<!-- Content -->
<div class="flex flex-column w-full lg:w-10">
<!-- Header -->
<div id="header" class="w-full flex text-white p-4">
<div class="flex align-items-end">
<!-- Title -->
<div class="hidden md:flex align-items-end">
<h1 class="text-white m-0">Ypovoli</h1>
</div>
<!-- User information -->
<div class="text-right ml-auto text-sm flex flex-column align-items-end gap-3">
<div class="flex align-items-center gap-3">
<template v-if="user !== null && user.hasMultipleRoles()">
Expand All @@ -65,12 +76,19 @@ const items = computed(() => [
</template>
<!-- Language selector -->
<LanguageSelector />
<!-- Menu selector -->
<span @click="showSidebar = !showSidebar" class="md:hidden pi pi-bars cursor-pointer" />
</div>
<div>
<!-- User information -->
<template v-if="user !== null">
<RouterLink :to="{ name: 'logout' }" class="text-white">
{{ t('layout.header.user', [user.getFullName()]) }}
<span class="hidden md:inline">
{{ t('layout.header.user', [user.getFullName()]) }}
</span>
<span class="inline md:hidden">
{{ user.getFullName() }}
</span>
</RouterLink>
</template>
<!-- Login button -->
Expand All @@ -88,7 +106,7 @@ const items = computed(() => [
</div>
</div>
<!-- Navigation -->
<div id="navigation" class="w-full h-full flex">
<div id="navigation" class="hidden md:flex w-full h-full">
<template v-if="isAuthenticated">
<RouterLink :to="{ name: item.route }" v-for="item in items" :key="item.route" class="nav-item">
<div
Expand All @@ -101,6 +119,43 @@ const items = computed(() => [
</template>
</div>
</div>
<Sidebar v-model:visible="showSidebar">
<template #container="{ closeCallback }">
<div class="flex flex-column h-full">
<div class="flex align-items-center justify-content-between p-4 pb-2 flex-shrink-0">
<span class="inline-flex align-items-center gap-2">
<img :alt="t('layout.header.logo')" :src="tiny" class="w-2rem mr-2" />
<span class="font-bold text-2xl text-primary">Ypovoli</span>
</span>
<span>
<Button
type="button"
@click="closeCallback"
icon="pi pi-times"
rounded
outlined
class="h-2rem w-2rem"
/>
</span>
</div>
<div class="overflow-y-auto px-2">
<ul class="list-none p-0 m-0">
<li v-for="item in items" :key="item.route">
<RouterLink
:to="{ name: item.route }"
@click="closeCallback"
class="flex align-items-center cursor-pointer p-3 text-black-alpha-90 border-bottom-1 border-300"
v-ripple
>
<i class="mr-2" :class="'pi pi-' + item.icon" />
<span class="font-medium">{{ item.label }}</span>
</RouterLink>
</li>
</ul>
</div>
</div>
</template>
</Sidebar>
</div>
</template>

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/projects/ProjectCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const { t } = useI18n();
<template #footer>
<RouterLink
:to="{
name: 'courseProject',
name: 'course-project',
params: {
courseId: course.id,
projectId: project.id,
Expand Down
100 changes: 46 additions & 54 deletions frontend/src/components/projects/ProjectCreateButton.vue
Original file line number Diff line number Diff line change
@@ -1,72 +1,64 @@
<script setup lang="ts">
import Dialog from 'primevue/dialog';
import Button from 'primevue/button';
import { useI18n } from 'vue-i18n';
import { type Course } from '@/types/Course.ts';
import { PrimeIcons } from 'primevue/api';
import Dialog from 'primevue/dialog';
import Button from 'primevue/button';
import { useRouter } from 'vue-router';
import { ref } from 'vue';
import CourseList from '@/components/courses/CourseList.vue';
/* Composable injections */
const { t } = useI18n();
const { push } = useRouter();
/* Props */
const props = defineProps<{ courses: Course[] }>();
const props = defineProps<{ courses: Course[]; label?: string; severity?: string }>();
/* Dialog state to select the course you want to create a project for */
const displayCourseSelection = ref(false);
/* Method to route to the project creation view */
const createProjectForCourse = (courseId: string): void => {
push({ name: 'project-create', params: { courseId } });
displayCourseSelection.value = false;
};
</script>

<template>
<!-- Button to create a new project -->
<Button
v-if="props.courses && props.courses.length > 0"
:icon="PrimeIcons.PLUS"
icon-pos="right"
class="custom-button"
@click="displayCourseSelection = true"
/>
<!-- Dialog to select the course you want to create a project for -->
<Dialog
v-model:visible="displayCourseSelection"
modal
:draggable="false"
:contentStyle="{ width: '50vw' }"
:header="t('views.dashboard.select_course')"
>
<!-- List of courses to select from-->
<div v-if="props.courses && props.courses.length > 0">
<div
v-for="course in props.courses"
:key="course.id"
class="course-item"
@click="createProjectForCourse(course.id)"
>
<span class="course-name">{{ course.name }}</span>
</div>
</div>
</Dialog>
<div>
<!-- Button to create a new project -->
<Button
v-if="props.courses && props.courses.length > 0"
:icon="PrimeIcons.PLUS"
icon-pos="right"
:label="label ?? ''"
:severity="severity ?? 'primary'"
class="custom-button"
@click="displayCourseSelection = true"
/>
<!-- Dialog to select the course you want to create a project for -->
<Dialog
v-model:visible="displayCourseSelection"
class="m-3"
:draggable="false"
:contentStyle="{ 'min-width': '50vw' }"
modal
>
<template #header>
<h2 class="my-3 text-primary">
{{ t('views.dashboard.select_course') }}
</h2>
</template>
<template #default>
<!-- List of courses to select from-->
<CourseList :cols="3" :courses="props.courses">
<template #footer="{ course }">
<RouterLink :to="{ name: 'project-create', params: { courseId: course.id } }">
<Button
:icon="PrimeIcons.PLUS"
:label="t('components.card.newProject')"
icon-pos="right"
outlined
/>
</RouterLink>
</template>
</CourseList>
</template>
</Dialog>
</div>
</template>
<style scoped lang="scss">
.course-item {
cursor: pointer;
padding: 8px;
border-radius: 4px;
margin-bottom: 8px;
transition: background-color 0.3s;
}
.course-item:hover {
background-color: #f0f0f0;
}
.course-name {
font-weight: bold;
}
</style>
<style scoped lang="scss"></style>
2 changes: 1 addition & 1 deletion frontend/src/components/projects/ProjectList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ watch(
<template v-if="sortedProjects !== null">
<template v-if="sortedProjects.length > 0">
<div
class="col-12 md:col-6 lg:col-4"
class="col-12 md:col-6"
:class="'xl:col-' + 12 / cols"
v-for="project in sortedProjects"
:key="project.id"
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ body {
padding: 0;
overflow-x: hidden;
line-height: 1.6rem;
min-height: 100vh;

#app {
min-height: 100vh;
}

* {
box-sizing: border-box;
Expand Down
Loading

0 comments on commit b2120e1

Please sign in to comment.