aboutsummaryrefslogtreecommitdiff
path: root/src/components/EditorActions.svelte
diff options
context:
space:
mode:
authorFurkan Sahin <furkan-dev@proton.me>2021-11-05 09:27:35 -0500
committerFurkan Sahin <furkan-dev@proton.me>2021-11-05 09:27:35 -0500
commit85380b4b60bf74507a01957b29bd6e3808e216db (patch)
treea43784660fdc29e5b95df3e358cf722eec2b092b /src/components/EditorActions.svelte
parentffef3a6be19d1139b6378c8119d444082dd0cbac (diff)
parent29fc563863f561cdc707485289c5580b4397a580 (diff)
Merge pull request #10 from cobraguy/rewrite
Update to Svelte app
Diffstat (limited to 'src/components/EditorActions.svelte')
-rw-r--r--src/components/EditorActions.svelte128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/components/EditorActions.svelte b/src/components/EditorActions.svelte
new file mode 100644
index 0000000..fa2a041
--- /dev/null
+++ b/src/components/EditorActions.svelte
@@ -0,0 +1,128 @@
+<script lang="ts">
+ import Button, { Label } from "@smui/button";
+ import IconButton from "@smui/icon-button";
+ import Snackbar, { Actions } from "@smui/snackbar";
+ import FileUpload from "./FileUpload.svelte";
+ import {
+ parseDatabaseFile,
+ parseLabScheduleFile,
+ parsePTFile,
+ } from "../logic/EditorActions";
+ import { labStore, ptStore } from "../stores";
+
+ let ptSchedules: FileList | null;
+ let labSchedule: FileList | null;
+ let dbFile: FileList | null;
+ let snackbar;
+ let snackbarText;
+
+ $: {
+ if (ptSchedules?.length) {
+ const promises = [...ptSchedules].map((file) => parsePTFile(file));
+ Promise.allSettled(promises)
+ .then((results) =>
+ results.flatMap((result) => {
+ if (result.status === "fulfilled") {
+ ptStore.update((val) => val.set(result.value.id, result.value));
+ return [];
+ } else {
+ return [result];
+ }
+ })
+ )
+ .then((failed) => {
+ if (failed.length) {
+ snackbarText = `Failed to add ${failed.length} PTs. See console for details.`;
+ snackbar.open();
+ }
+ });
+ }
+ }
+
+ $: {
+ if (labSchedule?.length) {
+ parseLabScheduleFile(labSchedule[0])
+ .then((labs) => {
+ labStore.update(() => new Map(labs.map((lab) => [lab.id, lab])));
+ })
+ .catch(() => {
+ snackbarText =
+ "Failed to import lab schedule. See console for details.";
+ snackbar.open();
+ });
+ }
+ }
+
+ $: {
+ if (dbFile?.length) {
+ parseDatabaseFile(dbFile[0])
+ .then((database) => {
+ labStore.set(database.labs);
+ ptStore.set(database.peerTeachers);
+ })
+ .catch(() => {
+ snackbarText = "Failed to import database. See console for details.";
+ snackbar.open();
+ });
+ }
+ }
+
+ function exportDB() {
+ const peerTeachers = [...$ptStore.values()];
+ const labs = [...$labStore.values()];
+ const database = {
+ labs: labs,
+ peerTeachers: peerTeachers,
+ };
+
+ const dbObj = JSON.stringify(database, (_, value) => {
+ // Need to manually convert the PeerTeacher objects'
+ // `labs` set to an array because `JSON.stringify` doesn't
+ // support "stringing" it out of the box
+ if (typeof value === "object" && value instanceof Set) {
+ return [...value];
+ }
+ return value;
+ });
+
+ const blob = new Blob([dbObj], { type: "text/json" });
+ const anchor = document.createElement("a");
+ const url = window.URL.createObjectURL(blob);
+ anchor.href = url;
+ anchor.download = "pt-db.json";
+ anchor.style.display = "none";
+ document.body.appendChild(anchor);
+ anchor.click();
+ document.body.removeChild(anchor);
+ window.URL.revokeObjectURL(url);
+ }
+</script>
+
+<div id="action-bar">
+ <FileUpload accept="text/plain" multiple={true} bind:files={ptSchedules}>
+ <Label>Add PT</Label>
+ </FileUpload>
+ <FileUpload accept="application/json" bind:files={labSchedule}>
+ <Label>Import Labs</Label>
+ </FileUpload>
+ <FileUpload accept="application/json" bind:files={dbFile}>
+ <Label>Import DB</Label>
+ </FileUpload>
+ <Button variant="raised" ripple={false} on:click={exportDB}>
+ <Label>Export DB</Label>
+ </Button>
+</div>
+<Snackbar bind:this={snackbar} labelText={snackbarText}>
+ <Label />
+ <Actions>
+ <IconButton class="material-icons" title="Dismiss">close</IconButton>
+ </Actions>
+</Snackbar>
+
+<style>
+ #action-bar {
+ max-width: 100vw;
+ overflow-x: auto;
+ white-space: nowrap;
+ }
+</style>