mirror of
https://github.com/gurucomputing/headscale-ui.git
synced 2026-07-25 08:54:03 +00:00
added alert UI, improved createuser ui
This commit is contained in:
parent
fc923b55c3
commit
29da48c76f
3 changed files with 126 additions and 12 deletions
66
src/lib/common/Alert.svelte
Normal file
66
src/lib/common/Alert.svelte
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<script lang="ts">
|
||||
import { writable } from 'svelte/store';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
export const alert = writable('test');
|
||||
export let ms = 3000;
|
||||
let visible = false;
|
||||
let timeout: number;
|
||||
|
||||
onMount(async () => {
|
||||
const onMessageChange = (message: string, ms: number) => {
|
||||
clearTimeout(timeout);
|
||||
if (!message) {
|
||||
// hide Alert if message is empty
|
||||
visible = false;
|
||||
} else {
|
||||
visible = true;
|
||||
if (ms > 0) timeout = window.setTimeout(() => (visible = false), ms); // and hide it after ms milliseconds
|
||||
}
|
||||
};
|
||||
$: onMessageChange($alert, ms); // whenever the alert store or the ms props changes run onMessageChange
|
||||
onDestroy(() => clearTimeout(timeout)); // make sure we clean-up the timeout
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if visible}
|
||||
<div on:click={() => (visible = false)}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
|
||||
><path
|
||||
d="M12.432 0c1.34 0 2.01.912 2.01 1.957 0 1.305-1.164 2.512-2.679 2.512-1.269 0-2.009-.75-1.974-1.99C9.789 1.436 10.67 0 12.432 0zM8.309 20c-1.058 0-1.833-.652-1.093-3.524l1.214-5.092c.211-.814.246-1.141 0-1.141-.317 0-1.689.562-2.502 1.117l-.528-.88c2.572-2.186 5.531-3.467 6.801-3.467 1.057 0 1.233 1.273.705 3.23l-1.391 5.352c-.246.945-.141 1.271.106 1.271.317 0 1.357-.392 2.379-1.207l.6.814C12.098 19.02 9.365 20 8.309 20z"
|
||||
/></svg
|
||||
>
|
||||
<p>{$alert}</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
div {
|
||||
position: fixed;
|
||||
cursor: pointer;
|
||||
margin-right: 1.5rem;
|
||||
margin-left: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 0.2rem;
|
||||
background-color: #565656;
|
||||
color: #fff;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 700;
|
||||
padding: 0.5rem 1.4rem;
|
||||
font-size: 1.5rem;
|
||||
z-index: 100;
|
||||
opacity: 95%;
|
||||
}
|
||||
div p {
|
||||
color: #fff;
|
||||
}
|
||||
div svg {
|
||||
height: 1.6rem;
|
||||
fill: currentcolor;
|
||||
width: 1.4rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,19 +1,65 @@
|
|||
<script lang="ts">
|
||||
import { fade } from 'svelte/transition';
|
||||
// name for user creation
|
||||
let userName = '';
|
||||
// whether the new card html element is visible
|
||||
let newUserCardVisible = false;
|
||||
// The Form used for validating input
|
||||
let newUserForm: HTMLFormElement;
|
||||
|
||||
function createUser() {}
|
||||
function createUser(): void {
|
||||
let headscaleURL = localStorage.getItem('headscaleURL') || '';
|
||||
let headscaleAPIKey = localStorage.getItem('headscaleAPIKey') || '';
|
||||
let endpointURL = '/api/v1/namespace';
|
||||
if (newUserForm.reportValidity()) {
|
||||
fetch(headscaleURL + endpointURL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${headscaleAPIKey}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: userName.toLowerCase()
|
||||
})
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
response.json().then((data) => {
|
||||
console.log(data);
|
||||
});
|
||||
} else {
|
||||
response.json().then((data) => {
|
||||
console.error(data);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- html -->
|
||||
<div in:fade class="p-4"><button class="btn-primary bg-teal-700 hover:bg-teal-900 " type="button">+ New User</button></div>
|
||||
<div in:fade class="card-pending">
|
||||
<input class="card-input" placeholder="name" />
|
||||
<div>
|
||||
<button><svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 inline rounded-full hover:bg-gray-300" fill="none" viewBox="0 0 24 24" stroke="black" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg></button>
|
||||
<button><svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 inline rounded-full hover:bg-gray-300" fill="none" viewBox="0 0 24 24" stroke="black" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg></button>
|
||||
<div in:fade class="p-4"><button on:click={() => (newUserCardVisible = true)} class="btn-primary bg-teal-700 hover:bg-teal-900 " type="button">+ New User</button></div>
|
||||
{#if newUserCardVisible}
|
||||
<div in:fade out:fade={{ duration: newUserCardVisible ? 0 : 500 }} class="card-pending">
|
||||
<form class="relative" bind:this={newUserForm}>
|
||||
<!-- Input has to be lower case, but we will force lower case on submit -->
|
||||
<input bind:value={userName} class="card-input lowercase" required pattern="[a-zA-Z\-\.]+" placeholder="name" />
|
||||
</form>
|
||||
<div>
|
||||
<button on:click={() => createUser()}
|
||||
><svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 inline rounded-full hover:bg-gray-300" fill="none" viewBox="0 0 24 24" stroke="black" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg></button
|
||||
>
|
||||
<button on:click={() => (newUserCardVisible = false)}
|
||||
><svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 inline rounded-full hover:bg-gray-300" fill="none" viewBox="0 0 24 24" stroke="black" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg></button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import '../app.css';
|
||||
import Nav from '$lib/common/nav.svelte';
|
||||
import Alert from '$lib/common/Alert.svelte'
|
||||
</script>
|
||||
|
||||
<main class="flex flex-col">
|
||||
|
|
@ -9,6 +10,7 @@
|
|||
<Nav />
|
||||
<!-- main window -->
|
||||
<div class="flex flex-1 flex-col">
|
||||
<Alert></Alert>
|
||||
<!-- header -->
|
||||
<!-- <div class="flex bg-gray-100 h-12 p-4">Header</div> -->
|
||||
<!-- content -->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue