Adding a progress bar
This commit is contained in:
parent
6b2569aed0
commit
fe8ca05fd4
|
@ -1,6 +1,14 @@
|
||||||
import { createForm } from '@felte/solid';
|
import { createForm } from '@felte/solid';
|
||||||
import { Component, Index, Match, onMount, Show, Switch } from 'solid-js';
|
import {
|
||||||
import { TextField, Button } from '@kobalte/core';
|
Component,
|
||||||
|
createSignal,
|
||||||
|
Index,
|
||||||
|
Match,
|
||||||
|
onMount,
|
||||||
|
Show,
|
||||||
|
Switch,
|
||||||
|
} from 'solid-js';
|
||||||
|
import { TextField, Button, Progress } from '@kobalte/core';
|
||||||
import reporter from '@felte/reporter-tippy';
|
import reporter from '@felte/reporter-tippy';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import { useNavigate } from 'solid-start';
|
import { useNavigate } from 'solid-start';
|
||||||
|
@ -18,6 +26,8 @@ interface Props {
|
||||||
const User: Component<Props> = (props) => {
|
const User: Component<Props> = (props) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [progress, setProgress] = createSignal(-1);
|
||||||
|
|
||||||
const credentials = adminCredentials();
|
const credentials = adminCredentials();
|
||||||
const { database } = credentials || { database: null };
|
const { database } = credentials || { database: null };
|
||||||
|
|
||||||
|
@ -37,6 +47,7 @@ const User: Component<Props> = (props) => {
|
||||||
values,
|
values,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
setProgress(0);
|
||||||
const id = getValues()?._id ?? userId(values.username, values.database);
|
const id = getValues()?._id ?? userId(values.username, values.database);
|
||||||
await put(id, values, isNew());
|
await put(id, values, isNew());
|
||||||
const couchUserId = `org.couchdb.user:${values.username}`;
|
const couchUserId = `org.couchdb.user:${values.username}`;
|
||||||
|
@ -49,6 +60,8 @@ const User: Component<Props> = (props) => {
|
||||||
};
|
};
|
||||||
await put(couchUserId, userDoc, isNew(), '_users');
|
await put(couchUserId, userDoc, isNew(), '_users');
|
||||||
|
|
||||||
|
setProgress(1);
|
||||||
|
|
||||||
const subscriptions = !!props?.values
|
const subscriptions = !!props?.values
|
||||||
? props.values().subscriptions ?? []
|
? props.values().subscriptions ?? []
|
||||||
: [];
|
: [];
|
||||||
|
@ -74,6 +87,8 @@ const User: Component<Props> = (props) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setProgress(2);
|
||||||
|
|
||||||
for (let i = 0; i < subscriptions.length; i++) {
|
for (let i = 0; i < subscriptions.length; i++) {
|
||||||
let subscription = subscriptions[i];
|
let subscription = subscriptions[i];
|
||||||
if (!isIn(subscription.username, updatedSubscriptions)) {
|
if (!isIn(subscription.username, updatedSubscriptions)) {
|
||||||
|
@ -83,10 +98,12 @@ const User: Component<Props> = (props) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setProgress(3);
|
||||||
|
|
||||||
setInitialValues(values);
|
setInitialValues(values);
|
||||||
setIsDirty(false);
|
setIsDirty(false);
|
||||||
|
|
||||||
|
setProgress(-1);
|
||||||
navigate(`/user/${id}`);
|
navigate(`/user/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,102 +217,125 @@ const User: Component<Props> = (props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Show when={!isNew()}>
|
<Show when={progress() >= 0}>
|
||||||
<h2>{userId(data('username'), data('database'))}</h2>
|
<Progress.Root
|
||||||
|
value={progress()}
|
||||||
|
minValue={0}
|
||||||
|
maxValue={10}
|
||||||
|
getValueLabel={({ value, max }) =>
|
||||||
|
`${value} of ${max} tasks completed`
|
||||||
|
}
|
||||||
|
class='progress'
|
||||||
|
>
|
||||||
|
<div class='progress__label-container'>
|
||||||
|
<Progress.Label class='progress__label'>
|
||||||
|
Processing...
|
||||||
|
</Progress.Label>
|
||||||
|
<Progress.ValueLabel class='progress__value-label' />
|
||||||
|
</div>
|
||||||
|
<Progress.Track class='progress__track'>
|
||||||
|
<Progress.Fill class='progress__fill' />
|
||||||
|
</Progress.Track>
|
||||||
|
</Progress.Root>
|
||||||
|
</Show>
|
||||||
|
<Show when={progress() < 0}>
|
||||||
|
<Show when={!isNew()}>
|
||||||
|
<h2>{userId(data('username'), data('database'))}</h2>
|
||||||
|
</Show>
|
||||||
|
<form use:form>
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Label>Mail address</TextField.Label>
|
||||||
|
<TextField.Input
|
||||||
|
type='mail'
|
||||||
|
name='mail'
|
||||||
|
required={true}
|
||||||
|
placeholder='Email address'
|
||||||
|
/>
|
||||||
|
<TextField.ErrorMessage>
|
||||||
|
Please provide a valid URL
|
||||||
|
</TextField.ErrorMessage>
|
||||||
|
</TextField.Root>
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Label>Database</TextField.Label>
|
||||||
|
<TextField.Input
|
||||||
|
type='url'
|
||||||
|
name='database'
|
||||||
|
required={true}
|
||||||
|
placeholder='Database URL'
|
||||||
|
readOnly={true}
|
||||||
|
/>
|
||||||
|
</TextField.Root>
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Label>User name</TextField.Label>
|
||||||
|
<TextField.Input
|
||||||
|
type='text'
|
||||||
|
name='username'
|
||||||
|
required={true}
|
||||||
|
placeholder='user name'
|
||||||
|
readOnly={!isNew()}
|
||||||
|
/>
|
||||||
|
</TextField.Root>
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Label>Password</TextField.Label>
|
||||||
|
<TextField.Input
|
||||||
|
type='text'
|
||||||
|
name='password'
|
||||||
|
required={true}
|
||||||
|
placeholder='Password'
|
||||||
|
autocomplete='off'
|
||||||
|
/>
|
||||||
|
</TextField.Root>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<button type='button' onClick={addSubscription()}>
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<th>User name</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<Index each={subscriptions()}>
|
||||||
|
{(_, index) => (
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<button type='button' onClick={removeSubscription(index)}>
|
||||||
|
-
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<TextField.Root>
|
||||||
|
<TextField.Input
|
||||||
|
type='text'
|
||||||
|
name={`subscriptions.${index}.username`}
|
||||||
|
required={true}
|
||||||
|
placeholder='user name'
|
||||||
|
/>
|
||||||
|
</TextField.Root>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</Index>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<Switch>
|
||||||
|
<Match when={!isNew()}>
|
||||||
|
<Button.Root type='submit' disabled={!isDirty() || !isValid()}>
|
||||||
|
Save
|
||||||
|
</Button.Root>
|
||||||
|
<Button.Root onclick={deleteHandler}>Delete</Button.Root>
|
||||||
|
</Match>
|
||||||
|
<Match when={isNew()}>
|
||||||
|
<Button.Root type='submit' isDisabled={!isValid()}>
|
||||||
|
Create
|
||||||
|
</Button.Root>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
|
<Button.Root onclick={cancelHandler}>Back</Button.Root>
|
||||||
|
</form>
|
||||||
</Show>
|
</Show>
|
||||||
<form use:form>
|
|
||||||
<TextField.Root>
|
|
||||||
<TextField.Label>Mail address</TextField.Label>
|
|
||||||
<TextField.Input
|
|
||||||
type='mail'
|
|
||||||
name='mail'
|
|
||||||
required={true}
|
|
||||||
placeholder='Email address'
|
|
||||||
/>
|
|
||||||
<TextField.ErrorMessage>
|
|
||||||
Please provide a valid URL
|
|
||||||
</TextField.ErrorMessage>
|
|
||||||
</TextField.Root>
|
|
||||||
<TextField.Root>
|
|
||||||
<TextField.Label>Database</TextField.Label>
|
|
||||||
<TextField.Input
|
|
||||||
type='url'
|
|
||||||
name='database'
|
|
||||||
required={true}
|
|
||||||
placeholder='Database URL'
|
|
||||||
readOnly={true}
|
|
||||||
/>
|
|
||||||
</TextField.Root>
|
|
||||||
<TextField.Root>
|
|
||||||
<TextField.Label>User name</TextField.Label>
|
|
||||||
<TextField.Input
|
|
||||||
type='text'
|
|
||||||
name='username'
|
|
||||||
required={true}
|
|
||||||
placeholder='user name'
|
|
||||||
readOnly={!isNew()}
|
|
||||||
/>
|
|
||||||
</TextField.Root>
|
|
||||||
<TextField.Root>
|
|
||||||
<TextField.Label>Password</TextField.Label>
|
|
||||||
<TextField.Input
|
|
||||||
type='text'
|
|
||||||
name='password'
|
|
||||||
required={true}
|
|
||||||
placeholder='Password'
|
|
||||||
autocomplete='off'
|
|
||||||
/>
|
|
||||||
</TextField.Root>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<button type='button' onClick={addSubscription()}>
|
|
||||||
+
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
<th>User name</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<Index each={subscriptions()}>
|
|
||||||
{(_, index) => (
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<button type='button' onClick={removeSubscription(index)}>
|
|
||||||
-
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<TextField.Root>
|
|
||||||
<TextField.Input
|
|
||||||
type='text'
|
|
||||||
name={`subscriptions.${index}.username`}
|
|
||||||
required={true}
|
|
||||||
placeholder='user name'
|
|
||||||
/>
|
|
||||||
</TextField.Root>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</Index>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<Switch>
|
|
||||||
<Match when={!isNew()}>
|
|
||||||
<Button.Root type='submit' disabled={!isDirty() || !isValid()}>
|
|
||||||
Save
|
|
||||||
</Button.Root>
|
|
||||||
<Button.Root onclick={deleteHandler}>Delete</Button.Root>
|
|
||||||
</Match>
|
|
||||||
<Match when={isNew()}>
|
|
||||||
<Button.Root type='submit' isDisabled={!isValid()}>
|
|
||||||
Create
|
|
||||||
</Button.Root>
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
<Button.Root onclick={cancelHandler}>Back</Button.Root>
|
|
||||||
</form>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -142,3 +142,33 @@ form {
|
||||||
transform: scale(0.96);
|
transform: scale(0.96);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
.progress__label-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.progress__label,
|
||||||
|
.progress__value-label {
|
||||||
|
color: hsl(240 4% 16%);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.progress__track {
|
||||||
|
height: 10px;
|
||||||
|
background-color: hsl(240 6% 90%);
|
||||||
|
}
|
||||||
|
.progress__fill {
|
||||||
|
background-color: hsl(200 98% 39%);
|
||||||
|
height: 100%;
|
||||||
|
width: var(--kb-progress-fill-width);
|
||||||
|
transition: width 250ms linear;
|
||||||
|
}
|
||||||
|
.progress__fill[data-progress="complete"] {
|
||||||
|
background-color: #16a34a;
|
||||||
|
}
|
Loading…
Reference in New Issue