Skip to content

Commit 09765fd

Browse files
committed
Proton (resolves #33), documents & document signing (linked to MeetPlan/MeetPlanBackend#7) - one more document needs to be signed, communication fixes, dark mode (resolves #45), improved UI on mobile devices (resolves #47)
1 parent 6d67f71 commit 09765fd

32 files changed

+1429
-7380
lines changed

package-lock.json

Lines changed: 0 additions & 6665 deletions
This file was deleted.

package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99
"start": "sirv public --no-clear -s",
1010
"tauri": "tauri",
1111
"tauri-build": "TAURI=true tauri build",
12-
"tauri-dev": "TAURI=true tauri dev"
12+
"tauri-dev": "TAURI=true tauri dev",
13+
"prepare": "npm run smui-theme-light && npm run smui-theme-dark",
14+
"smui-theme-light": "smui-theme compile public/build/smui.css -i src/theme",
15+
"smui-theme-dark": "smui-theme compile public/build/smui-dark.css -i src/theme/dark"
1316
},
1417
"devDependencies": {
18+
"@material/elevation": "^14.0.0",
19+
"@material/theme": "^14.0.0",
20+
"@material/typography": "^14.0.0",
1521
"@rollup/plugin-commonjs": "^22.0.1",
1622
"@rollup/plugin-node-resolve": "^13.3.0",
1723
"@rollup/plugin-replace": "^4.0.0",
@@ -25,6 +31,7 @@
2531
"@smui/dialog": "^6.0.0-beta.16",
2632
"@smui/drawer": "^6.0.0-beta.16",
2733
"@smui/list": "^6.0.0-beta.16",
34+
"@smui/menu-surface": "^6.0.0-beta.16",
2835
"@smui/paper": "^6.0.0-beta.16",
2936
"@smui/ripple": "^6.0.0-beta.16",
3037
"@smui/select": "^6.0.0-beta.16",
@@ -37,6 +44,8 @@
3744
"@types/marked": "^4.0.3",
3845
"apexcharts": "^3.35.3",
3946
"date-fns": "^2.28.0",
47+
"insane": "^2.6.2",
48+
"is-mobile": "^3.1.1",
4049
"jwt-decode": "^3.1.2",
4150
"marked": "^4.0.17",
4251
"rollup": "^2.75.7",
@@ -50,6 +59,7 @@
5059
"svelte-apexcharts": "^1.0.2",
5160
"svelte-avatar": "^1.1.1",
5261
"svelte-check": "^2.8.0",
62+
"svelte-dnd-action": "^0.9.18",
5363
"svelte-material-ui": "^6.0.0-beta.16",
5464
"svelte-preprocess": "^4.10.7",
5565
"svelte-routing": "^1.6.0",

public/global.css

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ html, body {
55
}
66

77
body {
8-
color: #333;
98
margin: 0;
109
padding: 8px;
1110
box-sizing: border-box;
@@ -61,3 +60,28 @@ button:not(:disabled):active {
6160
button:focus {
6261
border-color: #666;
6362
}
63+
64+
.drawer-container {
65+
position: relative;
66+
display: flex;
67+
height: 100%;
68+
width: 600px;
69+
border: 1px solid
70+
var(--mdc-theme-text-hint-on-background, rgba(0, 0, 0, 0.1));
71+
overflow: hidden;
72+
z-index: 0;
73+
}
74+
75+
.app-content {
76+
flex: auto;
77+
overflow: auto;
78+
position: relative;
79+
flex-grow: 1;
80+
}
81+
82+
.main-content {
83+
overflow: auto;
84+
padding: 16px;
85+
height: 100%;
86+
box-sizing: border-box;
87+
}

public/index.html

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@
55
<meta name='viewport' content='width=device-width,initial-scale=1'>
66

77
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
8-
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700">
9-
<link rel="stylesheet" href="https://unpkg.com/svelte-material-ui/bare.css">
8+
9+
<!-- SMUI Styles -->
10+
<link
11+
rel="stylesheet"
12+
href="/build/smui.css"
13+
media="(prefers-color-scheme: light)"
14+
/>
15+
<link
16+
rel="stylesheet"
17+
href="/build/smui-dark.css"
18+
media="screen and (prefers-color-scheme: dark)"
19+
/>
1020

1121
<title>MeetPlan</title>
1222

src/Admin/Users.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@
3838
3939
let choices = ["unverified", "student", "parent", "teacher", "food organizer", "school psychologist", "principal assistant", "principal"];
4040
41-
import jwt_decode, { JwtPayload } from "jwt-decode";
41+
import jwt_decode from "jwt-decode";
4242
import { navigate } from "svelte-routing";
4343
4444
const token = localStorage.getItem("key");
4545
if (token === null || token === undefined) {
4646
navigate("/login");
4747
}
4848
49-
const decoded = jwt_decode<JwtPayload>(token);
49+
const decoded = jwt_decode(token);
5050
</script>
5151

5252
<Drawer active="users" />

src/App.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import UserSettings from "./UserSettings.svelte";
2626
import ProtonSettings from "./ProtonSettings.svelte";
2727
import ErrorPage from "./ErrorPage.svelte";
28+
import Documents from "./Documents.svelte";
2829
2930
export let url = "";
3031
</script>
@@ -74,6 +75,7 @@
7475
<Route path="/classes" component="{Classes}" />
7576
<Route path="/settings" component="{Settings}" />
7677
<Route path="/notifications" component="{Notifications}" />
78+
<Route path="/documents" component="{Documents}" />
7779
<Route path="/settings/user" component="{UserSettings}" />
7880
<Route path="/proton/settings" component="{ProtonSettings}" />
7981
<Route path="/napaka" component="{ErrorPage}" />

src/Class.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
import Textfield from "@smui/textfield";
1313
import HelperText from '@smui/textfield/helper-text';
1414
import {navigate} from "svelte-routing";
15-
import jwt_decode, {JwtPayload} from "jwt-decode";
15+
import jwt_decode from "jwt-decode";
1616
1717
const token = localStorage.getItem("key");
1818
if (token === null || token === undefined) {
1919
navigate("/login");
2020
}
2121
22-
const decoded = jwt_decode<JwtPayload>(token);
22+
const decoded = jwt_decode(token);
2323
2424
let myClasses;
2525
let students;

src/ClassUser.svelte

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
import IconButton, { Icon } from '@smui/icon-button';
1515
1616
import Accordion, { Panel, Header, Content } from '@smui-extra/accordion';
17-
import jwt_decode, { JwtPayload } from "jwt-decode";
17+
import jwt_decode from "jwt-decode";
1818
1919
import * as marked from 'marked';
2020
2121
import List, {
2222
Item,
2323
Meta,
2424
} from '@smui/list';
25+
import insane from "insane";
2526
2627
let grades;
2728
let userData;
@@ -152,7 +153,7 @@
152153
navigate("/login");
153154
}
154155
155-
const decoded = jwt_decode<JwtPayload>(token);
156+
const decoded = jwt_decode(token);
156157
157158
const translatedSegments = {
158159
"DONE": "NAREJENO",
@@ -349,7 +350,7 @@
349350
{#each improvements as improvement}
350351
<h2>{improvement.MeetingName}</h2>
351352
Vpisal {improvement.TeacherName}
352-
{@html marked.marked(improvement.Message)}
353+
{@html insane(marked.marked(improvement.Message))}
353354
{/each}
354355
<p/>
355356
</main>

src/Classes.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
1919
import { navigate } from "svelte-routing";
2020
import {baseurl} from "./constants";
21-
import jwt_decode, {JwtPayload} from "jwt-decode";
21+
import jwt_decode from "jwt-decode";
2222
2323
const token = localStorage.getItem("key");
2424
if (token === null || token === undefined) {
2525
navigate("/login");
2626
}
2727
28-
const decoded = jwt_decode<JwtPayload>(token);
28+
const decoded = jwt_decode(token);
2929
3030
let items = [];
3131
let teachers = [];

src/Communication.svelte

Lines changed: 74 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
2020
import Button, {Label} from "@smui/button";
2121
import Icon from '@smui/textfield/icon';
22-
import jwt_decode, {JwtPayload} from "jwt-decode";
22+
import jwt_decode from "jwt-decode";
23+
import insane from "insane";
2324
2425
export let id: string = "";
2526
2627
const token = localStorage.getItem("key");
27-
const decoded = jwt_decode<JwtPayload>(token);
28+
const decoded = jwt_decode(token);
2829
2930
function getCommunication() {
3031
fetch(`${baseurl}/communication/get/${id}`, {headers: {"Authorization": "Bearer " + localStorage.getItem("key")}})
@@ -115,6 +116,76 @@
115116
}
116117
</script>
117118

119+
{#if rerenderDrawer}<Drawer active={"communication" + id} communicationActive={id} openDialog={openDialog} />{/if}
120+
<AppContent class="app-content">
121+
<main class="main-content">
122+
{#if comm}
123+
<h1>{comm.Title}</h1>
124+
{#each comm.Messages as message}
125+
<div style="white-space: nowrap;">
126+
<Avatar name={message.UserName} style="display: inline-block;"/>
127+
<h2 style="display: inline-block; text-align: center;">{message.UserName}</h2>
128+
{#if message.UserID === decoded["user_id"]}
129+
<Meta style="display: inline-block;">
130+
<Button on:click={() => deleteMessage(message.ID)}>
131+
<Icon class="material-icons">delete</Icon>
132+
<Label>Izbriši</Label>
133+
</Button>
134+
</Meta>
135+
<Meta style="display: inline-block;">
136+
<Button on:click={() => {
137+
messageEditingId = message.ID;
138+
newMessageValue = message.Body;
139+
}}>
140+
<Icon class="material-icons">edit</Icon>
141+
<Label>Uredi</Label>
142+
</Button>
143+
</Meta>
144+
{/if}
145+
</div>
146+
{@html insane(marked.marked(message.Body))}
147+
{/each}
148+
<hr>
149+
<Textfield
150+
textarea
151+
bind:value={newMessageValue}
152+
style="width: 100%;"
153+
/>
154+
{#if newMessageValue !== ""}
155+
<h2>Predogled</h2>
156+
{@html insane(marked.marked(newMessageValue))}
157+
{/if}
158+
<p/>
159+
{#if messageEditingId === undefined}
160+
<Button on:click={() => {
161+
let fd = new FormData();
162+
fd.append("body", newMessageValue)
163+
fetch(`${baseurl}/communication/get/${id}/message/new`, {headers: {"Authorization": "Bearer " + localStorage.getItem("key")}, body: fd, method: "POST"})
164+
.then((r) => {
165+
newMessageValue = "";
166+
getCommunication();
167+
});
168+
}}>
169+
<Icon class="material-icons">send</Icon>
170+
<Label>Pošlji</Label>
171+
</Button>
172+
{:else}
173+
<Button on:click={() => editMessage()}>
174+
<Icon class="material-icons">done</Icon>
175+
<Label>Končaj z urejanjem</Label>
176+
</Button>
177+
<Button on:click={() => {
178+
messageEditingId = undefined;
179+
newMessageValue = "";
180+
}}>
181+
<Icon class="material-icons">close</Icon>
182+
<Label>Končaj z urejanjem brez shranjevanja sprememb</Label>
183+
</Button>
184+
{/if}
185+
{/if}
186+
</main>
187+
</AppContent>
188+
118189
<Dialog
119190
bind:open
120191
aria-labelledby="simple-title"
@@ -216,76 +287,4 @@
216287
</Label>
217288
</Button>
218289
</Actions>
219-
</Dialog>
220-
221-
{#if rerenderDrawer}
222-
<Drawer active={"communication" + id} communicationActive={id} openDialog={openDialog} />
223-
{/if}
224-
<AppContent class="app-content">
225-
<main class="main-content">
226-
{#if comm}
227-
<h1>{comm.Title}</h1>
228-
{#each comm.Messages as message}
229-
<div style="white-space: nowrap;">
230-
<Avatar name={message.UserName} style="display: inline-block;"/>
231-
<h2 style="display: inline-block; text-align: center;">{message.UserName}</h2>
232-
{#if message.UserID === decoded["user_id"]}
233-
<Meta style="display: inline-block;">
234-
<Button on:click={() => deleteMessage(message.ID)}>
235-
<Icon class="material-icons">delete</Icon>
236-
<Label>Izbriši</Label>
237-
</Button>
238-
</Meta>
239-
<Meta style="display: inline-block;">
240-
<Button on:click={() => {
241-
messageEditingId = message.ID;
242-
newMessageValue = message.Body;
243-
}}>
244-
<Icon class="material-icons">edit</Icon>
245-
<Label>Uredi</Label>
246-
</Button>
247-
</Meta>
248-
{/if}
249-
</div>
250-
{@html marked.marked(message.Body)}
251-
{/each}
252-
<hr>
253-
<Textfield
254-
textarea
255-
bind:value={newMessageValue}
256-
style="width: 100%;"
257-
/>
258-
{#if newMessageValue !== ""}
259-
<h2>Predogled</h2>
260-
{@html marked.marked(newMessageValue)}
261-
{/if}
262-
<p/>
263-
{#if messageEditingId === undefined}
264-
<Button on:click={() => {
265-
let fd = new FormData();
266-
fd.append("body", newMessageValue)
267-
fetch(`${baseurl}/communication/get/${id}/message/new`, {headers: {"Authorization": "Bearer " + localStorage.getItem("key")}, body: fd, method: "POST"})
268-
.then((r) => {
269-
newMessageValue = "";
270-
getCommunication();
271-
});
272-
}}>
273-
<Icon class="material-icons">send</Icon>
274-
<Label>Pošlji</Label>
275-
</Button>
276-
{:else}
277-
<Button on:click={() => editMessage()}>
278-
<Icon class="material-icons">done</Icon>
279-
<Label>Končaj z urejanjem</Label>
280-
</Button>
281-
<Button on:click={() => {
282-
messageEditingId = undefined;
283-
newMessageValue = "";
284-
}}>
285-
<Icon class="material-icons">close</Icon>
286-
<Label>Končaj z urejanjem brez shranjevanja sprememb</Label>
287-
</Button>
288-
{/if}
289-
{/if}
290-
</main>
291-
</AppContent>
290+
</Dialog>

0 commit comments

Comments
 (0)