From 41c0d329fbaa8356cfb658c3061cc758cdabb809 Mon Sep 17 00:00:00 2001 From: minie4 Date: Tue, 20 Jun 2023 20:22:51 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Allow=20updating=20remote=20timetab?= =?UTF-8?q?les=20with=20permission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/api/index.js | 28 ++++++++++++++ server/index.js | 2 + src/components/settings/timetable-card.vue | 8 ++-- src/permission.js | 14 +++++++ src/views/settings/TimetableSettings.vue | 44 +++++++++++++++++++++- 5 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 src/permission.js diff --git a/server/api/index.js b/server/api/index.js index 295e6ce..89eab7f 100644 --- a/server/api/index.js +++ b/server/api/index.js @@ -82,6 +82,34 @@ export async function getTimetable(req, res) { }); } +// Edit timetable API endpoint (/api/timetable) +// Updates a remote timetable with the requested data +export async function putTimetable(req, res) { + const timetableId = parseInt(req.query.id); + const data = req.body.data; + if ( + !(await hasPermission(req.locals.session, "timetable.update", timetableId)) + ) { + res.status(401).send({ + success: false, + error: "missing_permission", + message: "You don't have permission to update this timetable!", + }); + return; + } + + await prisma.timetable.update({ + where: { + id: timetableId, + }, + data: { + data, + title: req.body.title, + }, + }); + res.status(201).send(); +} + // Helper function for converting a date string // (eg. "2022-06-02" or "1654128000000") to a // unix timestamp diff --git a/server/index.js b/server/index.js index 525eb64..a606b57 100644 --- a/server/index.js +++ b/server/index.js @@ -8,6 +8,7 @@ import { getSubstitutions, getHistory, getClasses, + putTimetable, getInfo, putKey, deleteKey, @@ -63,6 +64,7 @@ app.get("/api/info", getInfo); app.put("/api/key", putKey); app.delete("/api/key", deleteKey); app.get("/api/timetable", getTimetable); +app.put("/api/timetable", putTimetable); app.get("/api/substitutions", getSubstitutions); app.get("/api/history", getHistory); app.get("/api/classes", getClasses); diff --git a/src/components/settings/timetable-card.vue b/src/components/settings/timetable-card.vue index 8ccf196..c07a858 100644 --- a/src/components/settings/timetable-card.vue +++ b/src/components/settings/timetable-card.vue @@ -7,11 +7,12 @@ import { TrashIcon, AlertCircleIcon, CopyIcon, + UploadCloudIcon, } from "lucide-vue-next"; import { DownloadIcon } from "lucide-vue-next"; -defineProps(["timetable", "editable", "selected"]); -defineEmits(["click", "edit", "delete", "copy", "export"]); +defineProps(["timetable", "editable", "remote", "selected"]); +defineEmits(["click", "edit", "delete", "copy", "export", "upload"]); const deleteConfirm = ref(false); @@ -38,7 +39,8 @@ watch(deleteConfirm, (value) => {
- + + import TimetableCard from "@/components/settings/timetable-card.vue"; -import { timetables, localTimetables, timetableId } from "@/store"; +import { + timetable, + timetables, + localTimetables, + timetableId, + baseUrl, + fetchTimetables, +} from "@/store"; +import { canEditTimetable } from "@/permission"; import { PlusIcon, PaperclipIcon } from "lucide-vue-next"; import { toRaw, ref } from "vue"; import download from "downloadjs"; +import { loading, loadingProgress } from "@/store"; function copyTimetable(timetable) { const newTimetable = structuredClone(toRaw(timetable)); @@ -47,6 +56,34 @@ function exportTimetable(timetable) { "application/json" ); } + +async function uploadTimetable(id) { + loadingProgress.value = 0.1; + loading.value = true; + + const timetableData = timetable.value; + const response = await fetch( + baseUrl + "/timetable?id=" + encodeURIComponent(id), + { + method: "put", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(timetableData), + } + ); + + if (response.status != 201) { + alert("Failed uploading timetable!"); + } else { + loadingProgress.value = 0.5; + await fetchTimetables(); + timetableId.value = id; + } + + loadingProgress.value = 1; + loading.value = false; +}