2023-08-24 04:20:53 +08:00
|
|
|
import { createForm } from '@felte/solid'
|
|
|
|
import { validator } from '@felte/validator-zod'
|
|
|
|
import { useNavigate } from '@solidjs/router'
|
|
|
|
import { IconX } from '@tabler/icons-solidjs'
|
|
|
|
import ky from 'ky'
|
|
|
|
import { For } from 'solid-js'
|
|
|
|
import { v4 as uuid } from 'uuid'
|
|
|
|
import { z } from 'zod'
|
|
|
|
import { endpointList, setEndpointList, setSelectedEndpoint } from '~/signals'
|
|
|
|
|
|
|
|
const schema = z.object({
|
|
|
|
url: z.string().url().nonempty(),
|
|
|
|
secret: z.string(),
|
|
|
|
})
|
|
|
|
|
2023-08-29 14:44:49 +08:00
|
|
|
export default () => {
|
2023-08-24 04:20:53 +08:00
|
|
|
const navigate = useNavigate()
|
|
|
|
|
2023-08-30 17:50:28 +08:00
|
|
|
const onSetupSuccess = (id: string) => {
|
|
|
|
setSelectedEndpoint(id)
|
|
|
|
navigate('/overview')
|
|
|
|
}
|
|
|
|
|
2023-08-30 18:03:05 +08:00
|
|
|
const checkEndpoint = (url: string, secret: string) =>
|
2023-08-30 18:01:48 +08:00
|
|
|
ky
|
|
|
|
.get(url, {
|
2023-08-30 15:49:53 +08:00
|
|
|
headers: secret
|
2023-08-30 10:55:12 +08:00
|
|
|
? {
|
2023-08-30 15:49:53 +08:00
|
|
|
Authorization: `Bearer ${secret}`,
|
2023-08-30 10:55:12 +08:00
|
|
|
}
|
|
|
|
: {},
|
|
|
|
})
|
2023-08-30 18:01:48 +08:00
|
|
|
.then(({ ok }) => ok)
|
|
|
|
.catch(() => false)
|
2023-08-30 17:50:28 +08:00
|
|
|
|
|
|
|
const onEndpointSelect = async (id: string) => {
|
|
|
|
const endpoint = endpointList().find((e) => e.id === id)
|
|
|
|
|
|
|
|
if (!endpoint) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-08-30 18:03:05 +08:00
|
|
|
if (!(await checkEndpoint(endpoint.url, endpoint.secret))) {
|
2023-08-30 17:50:28 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
onSetupSuccess(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
const { form } = createForm<z.infer<typeof schema>>({
|
|
|
|
extend: validator({ schema }),
|
|
|
|
async onSubmit({ url, secret }) {
|
|
|
|
const endpointFromHistory = endpointList().find(
|
|
|
|
(history) => history.url === url && history.secret === secret,
|
|
|
|
)
|
|
|
|
|
|
|
|
if (endpointFromHistory) {
|
|
|
|
onSetupSuccess(endpointFromHistory.id)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-08-30 18:03:05 +08:00
|
|
|
if (!(await checkEndpoint(url, secret))) {
|
2023-08-30 17:50:28 +08:00
|
|
|
return
|
|
|
|
}
|
2023-08-24 04:20:53 +08:00
|
|
|
|
2023-08-30 15:49:53 +08:00
|
|
|
const id = uuid()
|
|
|
|
setEndpointList([{ id, url, secret }, ...endpointList()])
|
2023-08-30 17:50:28 +08:00
|
|
|
onSetupSuccess(id)
|
2023-08-24 04:20:53 +08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
const onRemove = (id: string) =>
|
|
|
|
setEndpointList(endpointList().filter((e) => e.id !== id))
|
|
|
|
|
|
|
|
return (
|
2023-08-27 22:25:41 +08:00
|
|
|
<div class="mx-auto flex flex-col items-center gap-4 py-10 sm:w-2/3">
|
2023-08-24 04:20:53 +08:00
|
|
|
<form class="contents" use:form={form}>
|
2023-08-27 22:25:41 +08:00
|
|
|
<div class="flex w-full flex-col gap-4">
|
2023-08-24 04:20:53 +08:00
|
|
|
<input
|
|
|
|
name="url"
|
|
|
|
type="url"
|
2023-08-27 22:25:41 +08:00
|
|
|
class="input input-bordered"
|
2023-08-24 04:20:53 +08:00
|
|
|
placeholder="http://127.0.0.1:9000"
|
|
|
|
list="defaultEndpoints"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<datalist id="defaultEndpoints">
|
|
|
|
<option value="http://127.0.0.1:9000" />
|
|
|
|
</datalist>
|
|
|
|
|
|
|
|
<input
|
|
|
|
name="secret"
|
|
|
|
type="password"
|
|
|
|
autocomplete="new-password"
|
2023-08-27 22:25:41 +08:00
|
|
|
class="input input-bordered"
|
2023-08-24 04:20:53 +08:00
|
|
|
placeholder="secret"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<button type="submit" class="btn btn-primary join-item uppercase">
|
|
|
|
Add
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<div class="flex w-full flex-col gap-4">
|
|
|
|
<For each={endpointList()}>
|
|
|
|
{({ id, url }) => (
|
|
|
|
<div
|
|
|
|
class="badge badge-info flex w-full cursor-pointer items-center gap-4 py-4"
|
2023-08-30 17:50:28 +08:00
|
|
|
onClick={() => onEndpointSelect(id)}
|
2023-08-24 04:20:53 +08:00
|
|
|
>
|
|
|
|
{url}
|
|
|
|
|
|
|
|
<button
|
|
|
|
class="btn btn-circle btn-ghost btn-xs text-white"
|
|
|
|
onClick={(e) => {
|
|
|
|
e.stopPropagation()
|
|
|
|
onRemove(id)
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<IconX />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|