From 67113db33dd4e7e173ee334075b5b247649e9d25 Mon Sep 17 00:00:00 2001 From: Bluerberry Date: Fri, 5 Jul 2024 00:02:01 +0200 Subject: [PATCH 01/29] redundant css --- .../app/course/[course]/overview/+page.svelte | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/routes/app/course/[course]/overview/+page.svelte b/src/routes/app/course/[course]/overview/+page.svelte index 084ccb2..c9f6c5e 100644 --- a/src/routes/app/course/[course]/overview/+page.svelte +++ b/src/routes/app/course/[course]/overview/+page.svelte @@ -216,24 +216,6 @@ @use "$styles/variables.sass" as * @use "$styles/palette.sass" as * - form - display: grid - grid-template: "label content" auto / 1fr 2fr - gap: $form-small-gap $form-medium-gap - place-items: center start - - margin-top: $form-big-gap - - label - grid-column: label - justify-self: end - - :global(.textfield), :global(.dropdown) - grid-column: content - - :global(.button) - grid-column: content - .graph display: flex flex-flow: row nowrap From 88aa55d255df836e7517e95ab1ca77af583d5756 Mon Sep 17 00:00:00 2001 From: Bluerberry Date: Fri, 5 Jul 2024 00:06:40 +0200 Subject: [PATCH 02/29] there's nothing here --- .../app/course/[course]/overview/+page.svelte | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/routes/app/course/[course]/overview/+page.svelte b/src/routes/app/course/[course]/overview/+page.svelte index c9f6c5e..71a7751 100644 --- a/src/routes/app/course/[course]/overview/+page.svelte +++ b/src/routes/app/course/[course]/overview/+page.svelte @@ -169,6 +169,10 @@

Graphs

+ {#if graphs.length === 0} +

There's nothing here.

+ {/if} + {#each course.graphs as graph} {#if graph.hasLinks()} @@ -202,6 +206,12 @@

Links

+ + + {#if true} +

There's nothing here.

+ {/if} +
@@ -216,6 +226,10 @@ @use "$styles/variables.sass" as * @use "$styles/palette.sass" as * + .grayed + margin: auto + color: $placeholder-color + .graph display: flex flex-flow: row nowrap From dc4ea74b84b97561c88a14ab27835eed542931b1 Mon Sep 17 00:00:00 2001 From: Julia van der Kris Date: Fri, 5 Jul 2024 22:35:18 +0200 Subject: [PATCH 03/29] Add functionality to update graphs in db from DTOs --- .../server/controllers/DomainController.ts | 1 + src/lib/server/controllers/GraphController.ts | 2 +- .../server/controllers/LectureController.ts | 1 + .../server/controllers/SubjectController.ts | 1 + src/lib/server/helpers/DomainHelper.ts | 27 ++++++++++++++++- src/lib/server/helpers/GraphHelper.ts | 27 +++++++++++++++++ src/lib/server/helpers/LectureHelper.ts | 17 ++++++++++- src/lib/server/helpers/SubjectHelper.ts | 29 +++++++++++++++++++ 8 files changed, 102 insertions(+), 3 deletions(-) diff --git a/src/lib/server/controllers/DomainController.ts b/src/lib/server/controllers/DomainController.ts index e69de29..ff8b4c5 100644 --- a/src/lib/server/controllers/DomainController.ts +++ b/src/lib/server/controllers/DomainController.ts @@ -0,0 +1 @@ +export default {}; diff --git a/src/lib/server/controllers/GraphController.ts b/src/lib/server/controllers/GraphController.ts index dd01095..a8f6611 100644 --- a/src/lib/server/controllers/GraphController.ts +++ b/src/lib/server/controllers/GraphController.ts @@ -12,4 +12,4 @@ export async function getGraphsByCourseCode(code: string) { } }); return await Promise.all(graphs.map(g => GraphHelper.toDTO(g))); -} \ No newline at end of file +} diff --git a/src/lib/server/controllers/LectureController.ts b/src/lib/server/controllers/LectureController.ts index e69de29..ff8b4c5 100644 --- a/src/lib/server/controllers/LectureController.ts +++ b/src/lib/server/controllers/LectureController.ts @@ -0,0 +1 @@ +export default {}; diff --git a/src/lib/server/controllers/SubjectController.ts b/src/lib/server/controllers/SubjectController.ts index e69de29..ff8b4c5 100644 --- a/src/lib/server/controllers/SubjectController.ts +++ b/src/lib/server/controllers/SubjectController.ts @@ -0,0 +1 @@ +export default {}; diff --git a/src/lib/server/helpers/DomainHelper.ts b/src/lib/server/helpers/DomainHelper.ts index ab48430..d1e2a34 100644 --- a/src/lib/server/helpers/DomainHelper.ts +++ b/src/lib/server/helpers/DomainHelper.ts @@ -70,4 +70,29 @@ export async function toDTO(domain: Domain): Promise { children: await getChildIds(domain), parents: await getParentIds(domain) } -} \ No newline at end of file +} + + +/** + * Updates a Domain object in the database to a SerializedDomain object sent by the client. + * @param dto SerializedDomain object + */ +export async function updateFromDTO(dto: SerializedDomain): Promise { + await prisma.domain.update({ + where: { + id: dto.id + }, + data: { + name: dto.name, + x: dto.x, + y: dto.y, + style: dto.style, + childDomains: { + connect: dto.children.map(id => ({ id })) + }, + parentDomains: { + connect: dto.parents.map(id => ({ id })) + } + } + }); +} diff --git a/src/lib/server/helpers/GraphHelper.ts b/src/lib/server/helpers/GraphHelper.ts index 3dc3dbf..8ef0e18 100644 --- a/src/lib/server/helpers/GraphHelper.ts +++ b/src/lib/server/helpers/GraphHelper.ts @@ -56,3 +56,30 @@ export async function toDTO(graph: Graph): Promise { lectures: await Promise.all((await getLectures(graph)).map(l => LectureHelper.toDTO(l))) } } + + +export async function updateFromDTO(dto: SerializedGraph): Promise { + await Promise.all([ + ...dto.domains.map(d => DomainHelper.updateFromDTO(d)), + ...dto.subjects.map(s => SubjectHelper.updateFromDTO(s)), + ...dto.lectures.map(l => LectureHelper.updateFromDTO(l)) + ]); + + await prisma.graph.update({ + where: { + id: dto.id + }, + data: { + name: dto.name, + domains: { + connect: dto.domains.map(d => ({ id: d.id })) + }, + subjects: { + connect: dto.subjects.map(s => ({ id: s.id })) + }, + lectures: { + connect: dto.lectures.map(l => ({ id: l.id })) + } + } + }); +} diff --git a/src/lib/server/helpers/LectureHelper.ts b/src/lib/server/helpers/LectureHelper.ts index ce34cef..ad51df7 100644 --- a/src/lib/server/helpers/LectureHelper.ts +++ b/src/lib/server/helpers/LectureHelper.ts @@ -23,4 +23,19 @@ export async function toDTO(lecture: Lecture): Promise { name: lecture.name, subjects: await getSubjectIds(lecture) } -} \ No newline at end of file +} + + +export async function updateFromDTO(dto: SerializedLecture) { + await prisma.lecture.update({ + where: { + id: dto.id + }, + data: { + name: dto.name, + subjects: { + connect: dto.subjects.map(s => ({ id: s })) + } + } + }); +} diff --git a/src/lib/server/helpers/SubjectHelper.ts b/src/lib/server/helpers/SubjectHelper.ts index 588ec41..3a5f8b7 100644 --- a/src/lib/server/helpers/SubjectHelper.ts +++ b/src/lib/server/helpers/SubjectHelper.ts @@ -69,3 +69,32 @@ export async function toDTO(subject: Subject): Promise { parents: await getParentIds(subject) } } + + +/** + * Updates a Subject object in the database to a SerializedSubject object sent by the client. + * @param dto SerializedSubject object + */ +export async function updateFromDTO(dto: SerializedSubject): Promise { + await prisma.subject.update({ + where: { + id: dto.id + }, + data: { + x: dto.x, + y: dto.y, + domain: { + connect: { + id: dto.domain + } + }, + name: dto.name, + childSubjects: { + connect: dto.children.map(id => ({ id })) + }, + parentSubjects: { + connect: dto.parents.map(id => ({ id })) + } + } + }); +} From cefb9b80ab8e8241ce2179d75716a2511667f049 Mon Sep 17 00:00:00 2001 From: Julia van der Kris Date: Sat, 6 Jul 2024 00:02:55 +0200 Subject: [PATCH 04/29] Add API endpoints for fetching and updating graphs --- src/lib/server/controllers/GraphController.ts | 15 ++++++++++ src/params/number.ts | 3 ++ src/routes/api/graph/[id=number]/+server.ts | 29 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/params/number.ts create mode 100644 src/routes/api/graph/[id=number]/+server.ts diff --git a/src/lib/server/controllers/GraphController.ts b/src/lib/server/controllers/GraphController.ts index a8f6611..6e955de 100644 --- a/src/lib/server/controllers/GraphController.ts +++ b/src/lib/server/controllers/GraphController.ts @@ -1,6 +1,8 @@ +import { error } from '@sveltejs/kit'; import prisma from '$lib/server/prisma'; import { GraphHelper } from '$lib/server/helpers'; +import { type SerializedGraph } from '$scripts/entities'; export async function getGraphsByCourseCode(code: string) { @@ -13,3 +15,16 @@ export async function getGraphsByCourseCode(code: string) { }); return await Promise.all(graphs.map(g => GraphHelper.toDTO(g))); } + + +export async function getGraphById(id: number): Promise { + const graph = await prisma.graph.findUnique({ + where: { + id + } + }); + + if (!graph) error(404, 'Graph not found'); + + return await GraphHelper.toDTO(graph); +} diff --git a/src/params/number.ts b/src/params/number.ts new file mode 100644 index 0000000..4efdac1 --- /dev/null +++ b/src/params/number.ts @@ -0,0 +1,3 @@ +export function match(param) { + return !isNaN(Number(param)) +} diff --git a/src/routes/api/graph/[id=number]/+server.ts b/src/routes/api/graph/[id=number]/+server.ts new file mode 100644 index 0000000..0d3382b --- /dev/null +++ b/src/routes/api/graph/[id=number]/+server.ts @@ -0,0 +1,29 @@ +import { json, error } from '@sveltejs/kit'; + +import { GraphHelper } from '$lib/server/helpers'; +import { getGraphById } from '$lib/server/controllers/GraphController'; +import { type SerializedGraph } from '$scripts/entities'; + + +/** + * Fetches a graph by its ID and returns it as a DTO + */ +export async function GET({ params }): Promise { + const id = Number(params.id); + const graph = await getGraphById(id); + return json(graph); +} + + +/** + * Updates a graph from a DTO + */ +export async function PUT({ request, params }): Promise { + const id = Number(params.id); + const dto: SerializedGraph = await request.json(); + + if (id !== dto.id) error(400, 'ID mismatch'); + + await GraphHelper.updateFromDTO(dto); + return new Response(null, { status: 201 }); +} From 1cc87d8157ee507f0b6c5476ae1bdf4af22508ba Mon Sep 17 00:00:00 2001 From: Julia van der Kris Date: Sat, 6 Jul 2024 18:31:01 +0200 Subject: [PATCH 05/29] Call graph update endpoint, some bug fixes --- src/lib/scripts/entities/Fields.ts | 1 + src/lib/scripts/entities/Graph.ts | 12 ++++++++++-- src/lib/server/helpers/DomainHelper.ts | 5 +++-- src/lib/server/helpers/SubjectHelper.ts | 5 +++-- .../[course]/graph/[graph]/settings/+page.server.ts | 10 +++++----- .../graph/[graph]/settings/DomainSettings.svelte | 6 ++++-- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/lib/scripts/entities/Fields.ts b/src/lib/scripts/entities/Fields.ts index 61b8e7e..9ffef74 100644 --- a/src/lib/scripts/entities/Fields.ts +++ b/src/lib/scripts/entities/Fields.ts @@ -159,6 +159,7 @@ class Domain extends Field { static create(graph: Graph, id: ID): Domain { /* Create a new domain */ + //! WARNING: using length as index seems dangerous, what happens when domains get deleted? const domain = new Domain(graph, graph.domains.length, id) graph.domains.push(domain) return domain diff --git a/src/lib/scripts/entities/Graph.ts b/src/lib/scripts/entities/Graph.ts index 99346d0..ded6ecb 100644 --- a/src/lib/scripts/entities/Graph.ts +++ b/src/lib/scripts/entities/Graph.ts @@ -203,10 +203,18 @@ class Graph { } } - save() { + async save() { /* Save the graph to the database */ - console.log(this.reduce()) + const response = await fetch(`/api/graph/${this.id}`, { + method: 'PUT', + body: JSON.stringify(this.reduce()) + }); + + if (!response.ok) { + const message = await response.text(); + console.error(`Failed to save graph: ${message}`); + } } delete() { diff --git a/src/lib/server/helpers/DomainHelper.ts b/src/lib/server/helpers/DomainHelper.ts index d1e2a34..c66e31f 100644 --- a/src/lib/server/helpers/DomainHelper.ts +++ b/src/lib/server/helpers/DomainHelper.ts @@ -4,8 +4,8 @@ import type { SerializedDomain } from '$scripts/entities'; import type { Domain } from '@prisma/client'; -export async function create(graphId: number) { - await prisma.domain.create({ +export async function create(graphId: number): Promise { + const domain = await prisma.domain.create({ data: { graph: { connect: { @@ -14,6 +14,7 @@ export async function create(graphId: number) { } } }); + return domain.id; } diff --git a/src/lib/server/helpers/SubjectHelper.ts b/src/lib/server/helpers/SubjectHelper.ts index 3a5f8b7..0db35cb 100644 --- a/src/lib/server/helpers/SubjectHelper.ts +++ b/src/lib/server/helpers/SubjectHelper.ts @@ -4,8 +4,8 @@ import type { SerializedSubject } from '$scripts/entities'; import type { Subject } from '@prisma/client'; -export async function create(graphId: number) { - await prisma.subject.create({ +export async function create(graphId: number): Promise { + const subject = await prisma.subject.create({ data: { graph: { connect: { @@ -14,6 +14,7 @@ export async function create(graphId: number) { } } }); + return subject.id; } diff --git a/src/routes/app/course/[course]/graph/[graph]/settings/+page.server.ts b/src/routes/app/course/[course]/graph/[graph]/settings/+page.server.ts index e126757..95ca37c 100644 --- a/src/routes/app/course/[course]/graph/[graph]/settings/+page.server.ts +++ b/src/routes/app/course/[course]/graph/[graph]/settings/+page.server.ts @@ -1,27 +1,27 @@ -import { fail } from '@sveltejs/kit'; +import { fail, type ActionFailure } from '@sveltejs/kit'; import prisma from '$lib/server/prisma'; import { CourseHelper, GraphHelper, DomainHelper, SubjectHelper } from '$lib/server/helpers'; export const actions = { - newDomain: async ({ params, request }) => { + newDomain: async ({ params, request }): Promise => { const data = await request.formData(); const graphId = Number(data.get('graph')); if (!graphId) return fail(400, { graphId, missing: true }); - await DomainHelper.create(graphId); + return await DomainHelper.create(graphId); }, - newSubject: async ({ params, request }) => { + newSubject: async ({ params, request }): Promise => { const data = await request.formData(); const graphId = Number(data.get('graph')); if (!graphId) return fail(400, { graphId, missing: true }); - await SubjectHelper.create(graphId); + return await SubjectHelper.create(graphId); } }; diff --git a/src/routes/app/course/[course]/graph/[graph]/settings/DomainSettings.svelte b/src/routes/app/course/[course]/graph/[graph]/settings/DomainSettings.svelte index 684c76f..4d6addf 100644 --- a/src/routes/app/course/[course]/graph/[graph]/settings/DomainSettings.svelte +++ b/src/routes/app/course/[course]/graph/[graph]/settings/DomainSettings.svelte @@ -23,7 +23,9 @@ // Exports export let graph: Graph - export let update: () => void + export function update() { + graph = graph; + } // Variables let domain_query: string = '' @@ -46,7 +48,7 @@ return } - const id = Number(await response.text()) + const id = Number(JSON.parse((await response.json()).data)[0]) Domain.create(graph, id) update() } From 5f6f20ab4fb47a2d2b6b4a239739e94ca7685430 Mon Sep 17 00:00:00 2001 From: Julia van der Kris Date: Sat, 6 Jul 2024 20:01:16 +0200 Subject: [PATCH 06/29] Sort queries --- src/lib/server/controllers/GraphController.ts | 3 +++ src/lib/server/helpers/CourseHelper.ts | 3 +++ src/lib/server/helpers/DomainHelper.ts | 6 ++++++ src/lib/server/helpers/GraphHelper.ts | 9 +++++++++ src/lib/server/helpers/LectureHelper.ts | 3 +++ src/lib/server/helpers/SubjectHelper.ts | 6 ++++++ src/routes/app/dashboard/+page.server.ts | 19 +++++++++++++++++-- 7 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/lib/server/controllers/GraphController.ts b/src/lib/server/controllers/GraphController.ts index 6e955de..c29191e 100644 --- a/src/lib/server/controllers/GraphController.ts +++ b/src/lib/server/controllers/GraphController.ts @@ -11,6 +11,9 @@ export async function getGraphsByCourseCode(code: string) { course: { code } + }, + orderBy: { + createdAt: 'asc' } }); return await Promise.all(graphs.map(g => GraphHelper.toDTO(g))); diff --git a/src/lib/server/helpers/CourseHelper.ts b/src/lib/server/helpers/CourseHelper.ts index 62fbd77..6072f7e 100644 --- a/src/lib/server/helpers/CourseHelper.ts +++ b/src/lib/server/helpers/CourseHelper.ts @@ -31,6 +31,9 @@ async function getSerializedUsers(course: Course): Promise ({ diff --git a/src/lib/server/helpers/DomainHelper.ts b/src/lib/server/helpers/DomainHelper.ts index c66e31f..847696c 100644 --- a/src/lib/server/helpers/DomainHelper.ts +++ b/src/lib/server/helpers/DomainHelper.ts @@ -32,6 +32,9 @@ async function getChildIds(domain: Domain): Promise { id: domain.id } } + }, + orderBy: { + id: 'asc' } })).map(d => d.id); } @@ -51,6 +54,9 @@ async function getParentIds(domain: Domain): Promise { id: domain.id } } + }, + orderBy: { + id: 'asc' } })).map(d => d.id); } diff --git a/src/lib/server/helpers/GraphHelper.ts b/src/lib/server/helpers/GraphHelper.ts index 8ef0e18..1866dbf 100644 --- a/src/lib/server/helpers/GraphHelper.ts +++ b/src/lib/server/helpers/GraphHelper.ts @@ -24,6 +24,9 @@ async function getDomains(graph: Graph): Promise { return await prisma.domain.findMany({ where: { graphId: graph.id + }, + orderBy: { + id: 'asc' } }); } @@ -33,6 +36,9 @@ async function getSubjects(graph: Graph): Promise { return await prisma.subject.findMany({ where: { graphId: graph.id + }, + orderBy: { + id: 'asc' } }); } @@ -42,6 +48,9 @@ async function getLectures(graph: Graph): Promise { return await prisma.lecture.findMany({ where: { graphId: graph.id + }, + orderBy: { + id: 'asc' } }); } diff --git a/src/lib/server/helpers/LectureHelper.ts b/src/lib/server/helpers/LectureHelper.ts index ad51df7..7cccf72 100644 --- a/src/lib/server/helpers/LectureHelper.ts +++ b/src/lib/server/helpers/LectureHelper.ts @@ -12,6 +12,9 @@ async function getSubjectIds(lecture: Lecture): Promise { id: lecture.id } } + }, + orderBy: { + id: 'asc' } })).map(s => s.id); } diff --git a/src/lib/server/helpers/SubjectHelper.ts b/src/lib/server/helpers/SubjectHelper.ts index 0db35cb..52ff946 100644 --- a/src/lib/server/helpers/SubjectHelper.ts +++ b/src/lib/server/helpers/SubjectHelper.ts @@ -36,6 +36,9 @@ async function getChildIds(subject: Subject): Promise { id: subject.id } } + }, + orderBy: { + id: 'asc' } })).map(d => d.id); } @@ -49,6 +52,9 @@ async function getParentIds(subject: Subject): Promise { id: subject.id } } + }, + orderBy: { + id: 'asc' } })).map(d => d.id); } diff --git a/src/routes/app/dashboard/+page.server.ts b/src/routes/app/dashboard/+page.server.ts index a11a732..1dc3403 100644 --- a/src/routes/app/dashboard/+page.server.ts +++ b/src/routes/app/dashboard/+page.server.ts @@ -32,8 +32,23 @@ export const actions = { export async function load() { - const programs = await prisma.program.findMany({ include: { courses: true, coordinators: true } }) - const courses = await prisma.course.findMany({ include: { program: true } }) + const programs = await prisma.program.findMany({ + include: { + courses: true, + coordinators: true + }, + orderBy: { + createdAt: 'asc' + } + }) + const courses = await prisma.course.findMany({ + include: { + program: true + }, + orderBy: { + createdAt: 'asc' + } + }) return { programs, From b9989b7f691aed2b24624ec57e82b9fb3e3cf31e Mon Sep 17 00:00:00 2001 From: Bram Kreulen Date: Mon, 8 Jul 2024 13:10:36 +0200 Subject: [PATCH 07/29] Helper objects rename --- .../app/course/[course]/overview/+page.svelte | 40 +++++++++++----- src/routes/app/dashboard/+page.svelte | 48 ++++++++++++++----- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/routes/app/course/[course]/overview/+page.svelte b/src/routes/app/course/[course]/overview/+page.svelte index 7550a49..b310a72 100644 --- a/src/routes/app/course/[course]/overview/+page.svelte +++ b/src/routes/app/course/[course]/overview/+page.svelte @@ -32,7 +32,7 @@ // Helpers - class GraphInput { + class GraphModal { name: string = '' get options(): DropdownOption[] { @@ -41,6 +41,14 @@ }) } + show() { + graph_modal?.show() + } + + hide() { + graph_modal?.hide() + } + validate(): ValidationData { const result = new ValidationData() @@ -59,10 +67,18 @@ } } - class Link { + class LinkModal { name: string = '' graph?: number + show() { + link_modal?.show() + } + + hide() { + link_modal?.hide() + } + validate(): ValidationData { const result = new ValidationData() @@ -93,8 +109,8 @@ $: course = Course.revive(data.course); $: graphs = data.graphs.map(graph => Graph.revive(graph)); - const graphInput = new GraphInput() - const link = new Link() + const graph = new GraphModal() + const link = new LinkModal() let graph_modal: Modal let link_modal: Modal @@ -121,11 +137,11 @@ ]} > - - @@ -139,13 +155,13 @@

Create Graph

Add a new graph to this course. Graphs are visual representations of the course content. They are intended to help students understand the course structure. -
+ - +
- - + +
@@ -154,12 +170,12 @@

Create Link

Add a new link to this course. This will link to a graph in this course, and can be provided to students, or embedded into course material. -
+ - +