Skip to content

Commit

Permalink
Add notification service
Browse files Browse the repository at this point in the history
  • Loading branch information
KordonDev committed Nov 20, 2022
1 parent 38fd395 commit 3869718
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 40 deletions.
15 changes: 9 additions & 6 deletions frontend/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
<script lang="ts">
import Router from "svelte-spa-router";
import Router, { link, replace } from "svelte-spa-router";
import Login from "./views/security/Login.svelte";
import { routes } from "./routes";
import Register from "./views/security/Register.svelte";
import MemberOverview from "./views/member/MemberOverview.svelte";
import { logout } from "./views/security/security.service";
import AddMember from "./views/member/AddMember.svelte";
import MemberDetail from "./views/member/MemberDetail.svelte";
import Notification from "./components/Notification.svelte";
if (window.location.pathname === "/") {
window.location.assign(routes.MemberOverview.link);
if (window.location.pathname === "/" && window.location.hash === "") {
replace(routes.MemberOverview.link);
}
</script>

<main>
<nav>
<a href={routes.Login.link}>Einloggen</a>
<a href={routes.MemberOverview.link}>Übersicht</a>
<a href={routes.AddMember.link}>Mitglied hinzufügen</a>
<a href={routes.Login.link} use:link>Einloggen</a>
<a href={routes.MemberOverview.link} use:link>Übersicht</a>
<a href={routes.AddMember.link} use:link>Mitglied hinzufügen</a>
<button on:click={logout}>Ausloggen</button>
</nav>

Expand All @@ -32,5 +33,7 @@
/>
</main>

<Notification />

<style>
</style>
33 changes: 33 additions & 0 deletions frontend/src/components/Notification.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts">
import { Alert } from "flowbite-svelte";
import { notificationsStore, removeNotification } from "./notificationStore";
import type { Notification } from "src/components/notificationStore";
let notifications: Notification[];
notificationsStore.subscribe((value) => {
notifications = value;
});
</script>

<div class="alert-container">
{#each notifications as notification}
<Alert
class="mb-4 top-alert"
color={notification.color}
dismissable
style="display: block;"
on:close={() => removeNotification(notification.id)}
>
{notification.text}
</Alert>
{/each}
</div>

<style>
.alert-container {
position: absolute;
top: 20px;
right: 20px;
}
</style>
28 changes: 28 additions & 0 deletions frontend/src/components/notificationStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { writable } from "svelte/store";

export interface Notification {
color: string;
text: string;
id: string;
}

export const notificationsStore = writable([]);

export const createNotification = (
n: Omit<Notification, "id">,
hideAfterSeconds?: number
) => {
const id = randomId();
notificationsStore.update((nS) => [...nS, { ...n, id }]);
if (hideAfterSeconds) {
setTimeout(() => removeNotification(id), hideAfterSeconds * 1000);
}
};

export const removeNotification = (id: string) => {
notificationsStore.update((nS) => nS.filter((n) => n.id !== id));
};

function randomId() {
return (Math.random() + 1).toString(36).substring(7);
}
10 changes: 5 additions & 5 deletions frontend/src/routes.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
export const routes = {
Login: {
path: "/login",
link: "/#/login",
link: "/login",
},
Register: {
path: "/register",
link: "/#/register",
link: "/register",
},
MemberOverview: {
path: "/member/overview",
link: "/#/member/overview",
link: "/member/overview",
},
MemberDetail: {
path: "/member/detail/:id",
link: "/#/member/detail/",
link: "/member/detail/",
},
AddMember: {
path: "/member/add",
link: "/#/member/add",
link: "/member/add",
},
};
3 changes: 2 additions & 1 deletion frontend/src/views/apiService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { routes } from "../routes";
import { BASE_URL } from "../constants";
import { replace } from "svelte-spa-router";

export function fetchApi(url: string, headers?: RequestInit) {
return fetch(`${BASE_URL}${url}`, {
Expand All @@ -24,7 +25,7 @@ export function fetchApi(url: string, headers?: RequestInit) {
if (contentType && contentType.indexOf("application/json") !== -1) {
return res.json().then((data) => {
if (data.redirect === "login") {
window.location.replace(routes.Login.link);
replace(routes.Login.link);
}
});
}
Expand Down
38 changes: 24 additions & 14 deletions frontend/src/views/member/AddMember.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script lang="ts">
import { Alert } from "flowbite-svelte";
import { routes } from "../../routes";
import { push } from "svelte-spa-router";
import { createNotification } from "../../components/notificationStore";
import type { Member } from "./member.service";
import { createMember } from "./member.service";
import MemberForm from "./MemberForm.svelte";
Expand All @@ -10,27 +12,35 @@
group: "",
};
let errorAlert = false;
let loading = true;
let loading = false;
function createMemberInternal(m: Member) {
createMember(m)
.then((succ) => {
.then((newMember) => {
createNotification(
{
color: "green",
text: `Mitglied ${m.name} wurde erfolgreich angelegt.`,
},
5
);
loading = false;
push(`${routes.MemberDetail.link}${newMember.id}`);
})
.catch((err) => {
errorAlert = true;
.catch(() => {
createNotification({
color: "red",
text: `Mitglied ${m.name} konnte nicht angelegt werden.`,
});
loading = false;
});
}
function closeAlert() {
errorAlert = false;
}
</script>

<h1>Mitglied hinzufügen</h1>
<MemberForm {member} onSubmit={createMember} submitText="Anlegen" />
{#if errorAlert}
<Alert color="red" dismissable on:close={closeAlert}>Close me</Alert>
{/if}
<MemberForm
{member}
onSubmit={createMemberInternal}
submitText="Anlegen"
{loading}
/>
8 changes: 7 additions & 1 deletion frontend/src/views/member/MemberDetail.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import { createNotification } from "../../components/notificationStore";
import { getMember, updateMember } from "./member.service";
import MemberForm from "./MemberForm.svelte";
export let params = { id: undefined };
Expand All @@ -8,5 +9,10 @@

{#await memberPromise then member}
<h1>{member.name}</h1>
<MemberForm {member} onSubmit={updateMember} submitText="Speichern" />
<MemberForm
{member}
onSubmit={updateMember}
submitText="Speichern"
loading={false}
/>
{/await}
13 changes: 10 additions & 3 deletions frontend/src/views/member/MemberForm.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script lang="ts">
import { Label, Input, Select, Button } from "flowbite-svelte";
import { Label, Input, Select, Button, Spinner } from "flowbite-svelte";
import type { Member } from "./member.service";
export let member: Member;
export let submitText: string;
export let loading: boolean;
export let onSubmit: (m: Member) => void;
const allGroups = [
Expand All @@ -16,7 +17,7 @@
}
</script>

<form on:submit|preventDefault={handleSubmit}>
<form on:submit|preventDefault={handleSubmit} disabled={loading}>
<Label for="name" class="block mb-2">Name</Label>
<Input required class="mb-4" id="name" bind:value={member.name} />

Expand All @@ -25,6 +26,12 @@
<Select required items={allGroups} bind:value={member.group} />
</Label>
<div class="flex flex-row justify-end">
<Button class="j" color="purple" type="submit">{submitText}</Button>
{#if loading}
<Spinner />
{:else}
<Button color="purple" type="submit">
{submitText}
</Button>
{/if}
</div>
</form>
3 changes: 2 additions & 1 deletion frontend/src/views/member/MemberOverview.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { getMembers } from "./member.service";
import { Card } from "flowbite-svelte";
import { routes } from "../../routes";
import { link } from "svelte-spa-router";
let membersPromise = getMembers();
</script>
Expand All @@ -11,7 +12,7 @@
<div class="flex flex-wrap">
{#each members as member}
<Card class="m-4">
<a href={`${routes.MemberDetail.link}${member.id}`}>
<a href={`${routes.MemberDetail.link}${member.id}`} use:link>
{`${member.id} ${member.name}`}
</a>
</Card>
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/views/security/Login.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<script lang="ts">
import { replace } from "svelte-spa-router";
import { routes } from "../../routes";
import { login } from "./security.service";
let username = "";
const handleLogin = () => {
login(username).then(() =>
window.location.replace(routes.MemberOverview.link)
);
login(username).then(() => replace(routes.MemberOverview.link));
};
</script>

Expand Down
1 change: 0 additions & 1 deletion frontend/src/views/security/security.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { BASE_URL } from "../../constants";
import { fetchApi } from "../apiService";

function bufferDecode(value) {
Expand Down
10 changes: 5 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ import (
)

func main() {
args := parseConfig()
config := parseConfig()

router := gin.Default()
api := router.Group("/api")

corsConfig := cors.DefaultConfig()
corsConfig.AllowOrigins = []string{"http://localhost:5173"}
corsConfig.AllowOrigins = []string{config.Origin}
corsConfig.AllowCredentials = true
api.Use(cors.New(corsConfig))

db := createDB(args.Debug)
db := createDB(config.Debug)

memberDB := members.NewMemberDB(db)
memberService := members.NewMemberService(memberDB)
Expand All @@ -42,7 +42,7 @@ func main() {
membersRoute.DELETE("/:id", memberService.DeleteById)

userDB := security.NewUserDB(db)
webAuthNService := security.NewWebAuthNService(userDB, args.Origin, args.Domain)
webAuthNService := security.NewWebAuthNService(userDB, config.Origin, config.Domain)

api.GET("/register/:username", webAuthNService.StartRegister)
api.POST("/register/:username", webAuthNService.FinishRegistration)
Expand All @@ -51,7 +51,7 @@ func main() {
api.POST("/login/:username", webAuthNService.FinishLogin)
api.POST("/logout", webAuthNService.Logout)

router.Run(fmt.Sprintf("%s:8080", args.Domain))
router.Run(fmt.Sprintf("%s:8080", config.Domain))
}

func createDB(debug bool) *gorm.DB {
Expand Down

0 comments on commit 3869718

Please sign in to comment.