backend/src/components/invitation/Invitation.tsx

246 lines
6.9 KiB
TypeScript
Raw Normal View History

2023-02-21 20:11:03 +00:00
import { createForm } from '@felte/solid';
2023-02-22 14:32:02 +00:00
import { Component, createSignal, Match, Switch } from 'solid-js';
import { TextField, Button, Dialog } from '@kobalte/core';
2023-02-21 20:11:03 +00:00
import './style.css';
import { createServerAction$ } from 'solid-start/server';
import PouchDb from 'pouchdb';
import { v4 as uuid } from 'uuid';
2023-02-22 10:19:10 +00:00
import { put } from '~/lib/db';
import { useNavigate } from 'solid-start';
2023-02-22 13:54:41 +00:00
import { toHex } from '~/lib/to-hex';
import { cloneDeep } from 'lodash';
2023-02-21 10:23:35 +00:00
2023-02-22 10:19:10 +00:00
interface Props {
values?: any;
}
2023-02-21 10:23:35 +00:00
const Invitation: Component<Props> = (props) => {
2023-02-22 10:19:10 +00:00
const navigate = useNavigate();
2023-02-22 14:32:02 +00:00
const [openDialog, setOpenDialog] = createSignal(false);
const [status, setStatus] = createSignal<string>();
2023-02-22 10:19:10 +00:00
const [saving, save] = createServerAction$(async (args: any) => {
const { props, values } = args;
console.log({
caller: 'Invitation / save',
props,
values,
args,
2023-02-22 10:58:56 +00:00
id: props.values?._id,
2023-02-22 10:19:10 +00:00
});
2023-02-21 20:11:03 +00:00
const db = new PouchDb('.db');
2023-02-22 10:58:56 +00:00
const id = props.values?._id ?? `invitation/${uuid()}`;
2023-02-22 10:19:10 +00:00
await put({
db,
doc: {
_id: id,
date: new Date().toISOString(),
type: 'invitation',
...values,
},
2023-02-21 12:38:43 +00:00
});
2023-02-21 15:12:52 +00:00
return id;
2023-02-21 12:38:43 +00:00
});
2023-02-22 13:54:41 +00:00
const [dbChecking, dbCheck] = createServerAction$(async (args: any) => {
console.log({
caller: 'Invitation / dbCheck',
args,
});
2023-02-22 14:32:02 +00:00
let baseDbInfoAuth;
2023-02-22 13:54:41 +00:00
try {
const baseDb = new PouchDb(cloneDeep(args));
2023-02-22 14:32:02 +00:00
baseDbInfoAuth = await baseDb.info();
} catch (error) {
baseDbInfoAuth = { error };
}
let baseDbInfoAnon;
try {
const baseDb = new PouchDb(args.name);
baseDbInfoAnon = await baseDb.info();
2023-02-22 13:54:41 +00:00
} catch (error) {
2023-02-22 14:32:02 +00:00
baseDbInfoAnon = { error };
2023-02-22 13:54:41 +00:00
}
const name = `${args.name}/userdb-${toHex(args.auth.username)}`;
let userDbInfo;
try {
const userDb = new PouchDb({ ...args, name });
userDbInfo = await userDb.info();
} catch (error) {
2023-02-22 14:32:02 +00:00
userDbInfo = { error };
2023-02-22 13:54:41 +00:00
}
2023-02-22 14:32:02 +00:00
let userDbInfoAnon;
try {
const userDb = new PouchDb(name);
userDbInfoAnon = await userDb.info();
} catch (error) {
userDbInfoAnon = { error };
}
return { baseDbInfoAuth, baseDbInfoAnon, userDbInfo, userDbInfoAnon };
2023-02-22 13:54:41 +00:00
});
2023-02-22 10:19:10 +00:00
const submitHandler = async (values: any, context: any) => {
2023-02-21 10:23:35 +00:00
console.log({
2023-02-21 20:11:03 +00:00
caller: 'Invitation / submitHandler',
2023-02-21 10:23:35 +00:00
props,
values,
context,
});
2023-02-22 10:19:10 +00:00
const id = await save({ values, props });
if (!props.values) {
navigate(`/invitations/${encodeURIComponent(id)}`);
}
2023-02-21 10:23:35 +00:00
};
2023-02-22 10:58:56 +00:00
const cancelHandler = () => {
navigate(`/invitations/`);
};
const deleteHandler = async () => {
console.log({
caller: 'Invitation / deleteHandler',
props,
});
await save({ props, values: { _deleted: true } });
navigate(`/invitations/`);
};
2023-02-22 13:54:41 +00:00
const { form, data } = createForm({
2023-02-22 10:19:10 +00:00
onSubmit: submitHandler,
initialValues: props?.values,
});
2023-02-22 13:54:41 +00:00
const dbCheckHandler = async () => {
const result = await dbCheck({
name: data('database'),
auth: { username: data('username'), password: data('password') },
});
console.log({
caller: 'Invitation / dbCheckHandler',
props,
data: data(),
result,
});
2023-02-22 14:32:02 +00:00
if (result.baseDbInfoAnon.error) {
setStatus('baseError');
} else if (!result.userDbInfo.error) {
setStatus('OK');
} else if (
result.userDbInfoAnon.error.reason ===
'You are not authorized to access this db.'
) {
setStatus('passwordError');
} else {
setStatus('notFound');
}
setOpenDialog(true);
2023-02-22 13:54:41 +00:00
};
2023-02-22 10:19:10 +00:00
console.log({
caller: 'Invitation ',
props,
});
2023-02-21 10:23:35 +00:00
return (
2023-02-22 14:32:02 +00:00
<>
<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'
/>
<TextField.ErrorMessage>
Please provide a valid URL
</TextField.ErrorMessage>
</TextField.Root>
<TextField.Root>
<TextField.Label>User name</TextField.Label>
<TextField.Input
type='text'
name='username'
required={true}
placeholder='user name'
/>
</TextField.Root>
<TextField.Root>
<TextField.Label>Password</TextField.Label>
<TextField.Input
type='text'
name='password'
required={true}
placeholder='Password'
autocomplete='off'
/>
<TextField.ErrorMessage>
Please provide a valid password
</TextField.ErrorMessage>
</TextField.Root>
<Switch>
<Match when={!!props.values}>
<Button.Root type='submit'>Save</Button.Root>
<Button.Root onclick={deleteHandler}>Delete</Button.Root>
</Match>
<Match when={!props.values}>
<Button.Root type='submit'>Create</Button.Root>
</Match>
</Switch>
<Button.Root onclick={dbCheckHandler}>DB check</Button.Root>
<Button.Root onclick={cancelHandler}>Cancel</Button.Root>
</form>
<Dialog.Root isOpen={openDialog()} onOpenChange={setOpenDialog}>
<Dialog.Portal>
<Dialog.Overlay class='dialog__overlay' />
<div class='dialog__positioner'>
<Dialog.Content class='dialog__content'>
<div class='dialog__header'>
<Dialog.Title class='dialog__title'>
Database check
</Dialog.Title>
<Dialog.CloseButton class='dialog__close-button'>
X
</Dialog.CloseButton>
</div>
<Dialog.Description class='dialog__description'>
<Switch>
<Match when={status() === 'baseError'}>
The database address seems to be wrong !!
</Match>{' '}
<Match when={status() === 'OK'}>
The user is already existing.
</Match>
<Match when={status() === 'notFound'}>
The user must be created.
</Match>
<Match when={status() === 'passwordError'}>
The user seems to exist but the password is wrong.
</Match>
</Switch>
</Dialog.Description>
</Dialog.Content>
</div>
</Dialog.Portal>
</Dialog.Root>
</>
2023-02-21 10:23:35 +00:00
);
};
export default Invitation;