add ability to remove user and add task depndencies closes #69

This commit is contained in:
2024-04-17 14:56:57 +01:00
parent 00ddb91a22
commit 8ece8306dd
25 changed files with 439 additions and 54 deletions

View File

@@ -1,4 +1,5 @@
<script lang="ts">
import Notifications from './lib/Notifications.svelte';
import { userStore } from './routes/UserStore.svelte';
</script>
@@ -26,6 +27,8 @@
</ul>
</nav>
<Notifications />
<style class="scss">
nav {
background: #ececec;

View File

@@ -0,0 +1,42 @@
<script lang="ts">
import { fly, fade } from 'svelte/transition';
import { notificationStore } from './NotificationsStore.svelte';
</script>
<div class="notifications">
{#each notificationStore.notifications as noti}
<div
class="notification"
class:noti-success={noti.type === 'success'}
class:noti-danger={noti.type === 'danger'}
class:noti-info={noti.type === 'info'}
in:fly|global={{ duration: 300, y: -120, opacity: 0 }}
out:fly|global={{ duration: 300, y: -120, opacity: 1 }}
>
{noti.message}
{@html noti.html ?? ''}
</div>
{/each}
</div>
<style lang="scss">
.notifications {
position: fixed;
top: 0;
left: 50%;
transform: translateX(-50%);
width: max(300px, 30%);
.notification {
border: 1px solid black;
padding: 20px;
background: #ffffff;
margin: 15px 0;
border-radius: 20px;
&.noti-danger {
background: var(--danger-ligther);
}
}
}
</style>

View File

@@ -0,0 +1,68 @@
type NotificationType = 'danger' | 'success' | 'info';
type Notification = {
type?: NotificationType;
timeToLive?: number;
message: string;
html?: string;
};
export function createNotificationStore(defaultTimetoLive: number) {
type InternalNotifications = {
notification: Notification;
endDate: Date;
};
let notifications = $state<InternalNotifications[]>([]);
let timeout = $state<number | undefined>();
function clearNotifications() {
const now = new Date().getTime();
let min: number | undefined = undefined;
notifications = notifications.filter((a) => {
const t = a.endDate.getTime();
if (t <= now) {
return false;
}
if (min == undefined) {
min = t;
} else if (min > t) {
min = t;
}
return true;
});
if (min != undefined) {
timeout = setTimeout(clearNotifications, now - min);
} else {
timeout = undefined;
}
}
function add(noti: Notification) {
if (!timeout) {
timeout = setTimeout(clearNotifications, noti.timeToLive ?? defaultTimetoLive);
}
const now = new Date();
notifications.push({
notification: noti,
endDate: new Date(now.getTime() + (noti.timeToLive ?? defaultTimetoLive))
});
}
return {
get notifications() {
return notifications.map((a) => a.notification);
},
clear() {
notifications.forEach((a) => clearInterval(a.timeout));
notifications = [];
},
add,
notify(message: string, type: NotificationType = 'danger') {
add({ message, type });
},
display(message: string) {
add({ message, type: 'danger' });
}
};
}
export const notificationStore = createNotificationStore(5000);

View File

@@ -108,7 +108,11 @@ export async function showMessage(
if (e == null) {
return false;
} else if (e instanceof Response) {
messages.display(await e.json());
try {
messages.display(await e.json());
} catch (ex) {
showMessage(ex, messages, message);
}
return true;
} else {
console.error(e);

View File

@@ -25,7 +25,7 @@
</script>
<script lang="ts">
import { onMount } from 'svelte';
import { onDestroy, onMount } from 'svelte';
import BaseModelInfo from './BaseModelInfo.svelte';
import DeleteModel from './DeleteModel.svelte';
@@ -50,16 +50,22 @@
let id: string | undefined = $state();
let re_query_timeout: number | undefined = undefined;
async function getModel() {
if (re_query_timeout) {
clearTimeout(re_query_timeout);
re_query_timeout = undefined;
}
try {
let temp_model: Model = await get(`models/edit?id=${id}`);
if ([3, 7, 6].includes(temp_model.status)) {
setTimeout(getModel, 2000);
re_query_timeout = setTimeout(getModel, 2000);
}
if (temp_model.status == 4) {
setTimeout(getModel, 5000);
re_query_timeout = setTimeout(getModel, 5000);
definitions = await get(`models/edit/definitions?id=${id}`);
}
@@ -108,6 +114,12 @@
}
}
onDestroy(() => {
if (re_query_timeout) {
clearTimeout(re_query_timeout);
}
});
// Auto reload after 2s when model.status 3,4
</script>

View File

@@ -0,0 +1,8 @@
<h1>Your User has been deleted</h1>
<style>
h1 {
text-align: center;
font-size: 40px;
}
</style>

View File

@@ -7,6 +7,7 @@
import { post } from 'src/lib/requests.svelte';
import MessageSimple, { type DisplayFn } from 'src/lib/MessageSimple.svelte';
import TokenTable from './TokenTable.svelte';
import DeleteUser from './DeleteUser.svelte';
onMount(() => {
if (!userStore.isLogin()) {
@@ -110,8 +111,8 @@
<button> Update </button>
</div>
</form>
<!-- TODO Delete -->
<TokenTable />
<DeleteUser />
</div>
</div>

View File

@@ -0,0 +1,34 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { notificationStore } from 'src/lib/NotificationsStore.svelte';
import { rdelete, showMessage } from 'src/lib/requests.svelte';
import { userStore } from 'src/routes/UserStore.svelte';
let data = $state({ password: '' });
async function deleteUser() {
if (!userStore.user) {
return;
}
try {
await rdelete('user/delete', {
id: userStore.user?.id,
password: data.password
});
userStore.user = undefined;
goto('/user-deleted');
} catch (e) {
showMessage(e, notificationStore);
}
}
</script>
<form class="danger-bg" on:submit|preventDefault={deleteUser}>
<h2 class="no-top-margin">Delete user</h2>
Deleting the user will delete all your data stored in the service including the images.
<fieldset>
To confirm please type your password
<input name="password" type="password" required bind:value={data.password} />
</fieldset>
<button> Delete </button>
</form>

View File

@@ -13,6 +13,7 @@
--warning: #fca311;
--warning-transparent: #fca31144;
--danger-ligther: #ffe0de;
--danger: #ff8282;
--danger-transparent: #ff828244;
@@ -171,3 +172,20 @@ a.button {
background-color: var(--danger-transparent);
border: 1px solid var(--danger);
}
.box {
padding: 30px;
margin: 20px 0;
border-radius: 10px;
box-shadow: 2px 5px 8px 2px #66666655;
}
.no-top-margin {
margin-top: 0px;
}
.box.danger-bg,
form.danger-bg {
background-color: var(--danger-transparent);
border: 1px solid var(--danger);
}