From 355ff0b3c947b9f4a13aad30b12578cf7fc44612 Mon Sep 17 00:00:00 2001 From: Arne Dierick Date: Sat, 18 May 2024 16:52:47 +0200 Subject: [PATCH] Added UI in the projectTable (where useIsCourseAdmin is defined) so a course admin can easily check the visibility of projects --- frontend/src/i18n/en/translation.json | 7 + frontend/src/i18n/nl/translation.json | 8 +- .../pages/index/components/ProjectCard.tsx | 100 +++++++------ .../index/components/ProjectTableCourse.tsx | 138 ++++++++++++++++++ 4 files changed, 208 insertions(+), 45 deletions(-) create mode 100644 frontend/src/pages/index/components/ProjectTableCourse.tsx diff --git a/frontend/src/i18n/en/translation.json b/frontend/src/i18n/en/translation.json index c4f55181..15ada75a 100644 --- a/frontend/src/i18n/en/translation.json +++ b/frontend/src/i18n/en/translation.json @@ -49,6 +49,13 @@ "showMore": "Show more", "submit": "Submit", "projectStatus": "Status", + "visibility": "Visibility", + "visibleStatus": { + "visible": "Visible", + "invisible": "Invisible", + "visibleFrom": "Visible from ", + "scheduled": "Scheduled" + }, "status": { "completed": "Completed", "failed": "Failed", diff --git a/frontend/src/i18n/nl/translation.json b/frontend/src/i18n/nl/translation.json index 7ab53224..6315beda 100644 --- a/frontend/src/i18n/nl/translation.json +++ b/frontend/src/i18n/nl/translation.json @@ -47,8 +47,14 @@ "deadline": "Deadline", "deadlineNotPassed": "Toon enkel actieve projecten", "showMore": "Toon meer", - "projectStatus": "Status", + "visibility": "Zichtbaarheid", + "visibleStatus": { + "visible": "Zichtbaar", + "invisible": "Onzichtbaar", + "visibleFrom": "Zichtbaar vanaf ", + "scheduled" : "gepland" + }, "status": { "completed": "Voltooid", "failed": "Verkeerd", diff --git a/frontend/src/pages/index/components/ProjectCard.tsx b/frontend/src/pages/index/components/ProjectCard.tsx index b092a439..e5244e3c 100644 --- a/frontend/src/pages/index/components/ProjectCard.tsx +++ b/frontend/src/pages/index/components/ProjectCard.tsx @@ -1,5 +1,6 @@ import { FC, useEffect, useState } from "react" -import ProjectTable, { ProjectType } from "./ProjectTable" +import ProjectTableCourse, { ProjectType } from "./ProjectTableCourse" +import ProjectTable, { ProjectType as NormalProjectType } from "./ProjectTable" import { Button, Card } from "antd" import { ApiRoutes } from "../../../@types/requests.d" import { useTranslation } from "react-i18next" @@ -8,53 +9,64 @@ import { useNavigate } from "react-router-dom" import CourseAdminView from "../../../hooks/CourseAdminView" import { PlusOutlined } from "@ant-design/icons" import useApi from "../../../hooks/useApi" +import useIsCourseAdmin from "../../../hooks/useIsCourseAdmin"; const ProjectCard: FC<{ courseId?: number }> = ({ courseId }) => { - const [projects, setProjects] = useState(null) - const { t } = useTranslation() - const navigate = useNavigate() - const API = useApi() + const [projects, setProjects] = useState(null) + const { t } = useTranslation() + const navigate = useNavigate() + const API = useApi() + const isCourseAdmin = useIsCourseAdmin() - useEffect(() => { - if (courseId) { - API.GET(ApiRoutes.COURSE_PROJECTS, { pathValues: { id: courseId } }).then((res) => { - if (!res.success) return - setProjects(res.response.data) - }) - } - }, [courseId]) + useEffect(() => { + if (courseId) { + API.GET(ApiRoutes.COURSE_PROJECTS, { pathValues: { id: courseId } }).then((res) => { + if (!res.success) return + setProjects(res.response.data) + }) + } + }, [courseId]) - return ( - <> - -
- -
-
- - - - - ) + return ( + <> + {isCourseAdmin && ( + +
+ +
+
+ )} + + {isCourseAdmin ? ( + + ) : ( + + )} + + + ) } export default ProjectCard diff --git a/frontend/src/pages/index/components/ProjectTableCourse.tsx b/frontend/src/pages/index/components/ProjectTableCourse.tsx new file mode 100644 index 00000000..861c0c66 --- /dev/null +++ b/frontend/src/pages/index/components/ProjectTableCourse.tsx @@ -0,0 +1,138 @@ +import { Button, Table, TableProps, Tag, Tooltip } from "antd" +import { FC, useMemo } from "react" +import { ApiRoutes, GET_Responses } from "../../../@types/requests.d" +import { useTranslation } from "react-i18next" +import i18n from 'i18next' +import useAppApi from "../../../hooks/useAppApi" +import ProjectStatusTag from "./ProjectStatusTag" +import GroupProgress from "./GroupProgress" +import { Link } from "react-router-dom" +import { AppRoutes } from "../../../@types/routes" +import { ClockCircleOutlined } from "@ant-design/icons" +import useIsCourseAdmin from "../../../hooks/useIsCourseAdmin"; + +export type ProjectType = GET_Responses[ApiRoutes.PROJECT] + +const ProjectTableCourse: FC<{ projects: ProjectType[] | null, ignoreColumns?: string[] }> = ({ projects, ignoreColumns }) => { + const { t } = useTranslation() + const { modal } = useAppApi() + const isCourseAdmin = useIsCourseAdmin() + + const columns: TableProps["columns"] = useMemo( + () => { + let columns: TableProps["columns"] = [ + { + title: t("home.projects.name"), + key: "name", + render: (project: ProjectType) => ( + + + + ) + }, + { + title: t("home.projects.course"), + dataIndex: "course", + key: "course", + sorter: (a: ProjectType, b: ProjectType) => a.course.name.localeCompare(b.course.name), + sortDirections: ['ascend', 'descend'], + render: (course: ProjectType["course"]) => course.name + }, + { + title: t("home.projects.deadline"), + dataIndex: "deadline", + key: "deadline", + sorter: (a: ProjectType, b: ProjectType) => new Date(a.deadline).getTime() - new Date(b.deadline).getTime(), + sortDirections: ['ascend', "descend"], + defaultSortOrder: "ascend", + filters: [{ text: t('home.projects.deadlineNotPassed'), value: 'notPassed' }], + onFilter: (value: any, record: any) => { + const currentTimestamp = new Date().getTime(); + const deadlineTimestamp = new Date(record.deadline).getTime(); + return value === 'notPassed' ? deadlineTimestamp >= currentTimestamp : true; + }, + defaultFilteredValue: ["notPassed"], + render: (text: string) => + new Date(text).toLocaleString(i18n.language, { + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + }), + }, + { + title: t("home.projects.groupProgress"), + key: "progress", + render: (project: ProjectType) => ( + + ), + } + ] + + if (ignoreColumns) { + columns = columns.filter((c) => !ignoreColumns.includes(c.key as string)) + } + + if (isCourseAdmin) { + columns = columns.filter((c) => c.key !== "status") + columns.push({ + title: t("home.projects.visibility"), + key: "visible", + render: (project: ProjectType) => { + if (project.visible) { + return {t("home.projects.visibleStatus.visible")} + } else if (project.visibleAfter) { + return ( + + } color="default">{t("home.projects.visibleStatus.scheduled")} + + ) + } else { + return {t("home.projects.visibleStatus.invisible")} + } + } + }) + } else { + columns.push({ + title: t("home.projects.projectStatus"), + key: "status", + render: (project: ProjectType) => + project.status && , + }) + } + + return columns + }, + [t, modal, projects, isCourseAdmin] + ) + + return ( + project.projectId} + /> + ) +} + +export default ProjectTableCourse