diff --git a/package-lock.json b/package-lock.json index 2f7164d..3ed5672 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,12 +7,14 @@ "name": "backend", "dependencies": { "@felte/reporter-solid": "^1.2.5", + "@felte/reporter-tippy": "^1.1.5", "@felte/solid": "^1.2.7", "@kobalte/core": "^0.6.1", "@types/pouchdb": "^6.4.0", "lodash": "^4.17.21", "pouchdb": "^8.0.1", "pouchdb-server": "^4.2.0", + "tippy.js": "^6.3.7", "uuid": "^9.0.0" }, "devDependencies": { @@ -2183,6 +2185,20 @@ "solid-js": "^1.2.0" } }, + "node_modules/@felte/reporter-tippy": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@felte/reporter-tippy/-/reporter-tippy-1.1.5.tgz", + "integrity": "sha512-boCEXGOkqTXRQa1l0t2Whjw/7wJHy16fA1Q3TNNj7XOiDAKYyzGfwbQn0kMR1jdzJTpSteB/xGb+ue1PenRDEQ==", + "dependencies": { + "@felte/common": "1.1.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "tippy.js": "^6.0.0" + } + }, "node_modules/@felte/solid": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@felte/solid/-/solid-1.2.7.tgz", @@ -2509,6 +2525,15 @@ "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", "dev": true }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rollup/plugin-commonjs": { "version": "24.0.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.1.tgz", @@ -10332,6 +10357,14 @@ "node": ">=14.0.0" } }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/package.json b/package.json index f3cfc6b..15a475b 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,14 @@ }, "dependencies": { "@felte/reporter-solid": "^1.2.5", + "@felte/reporter-tippy": "^1.1.5", "@felte/solid": "^1.2.7", "@kobalte/core": "^0.6.1", "@types/pouchdb": "^6.4.0", "lodash": "^4.17.21", "pouchdb": "^8.0.1", "pouchdb-server": "^4.2.0", + "tippy.js": "^6.3.7", "uuid": "^9.0.0" } } diff --git a/src/components/credentials/Credentials.tsx b/src/components/credentials/Credentials.tsx new file mode 100644 index 0000000..57481d6 --- /dev/null +++ b/src/components/credentials/Credentials.tsx @@ -0,0 +1,157 @@ +import { createForm } from '@felte/solid'; +import reporter from '@felte/reporter-tippy'; +import { Button, Dialog, TextField } from '@kobalte/core'; +import { Component, createSignal } from 'solid-js'; +import 'tippy.js/dist/tippy.css'; + +interface CredentialsType { + username: string; + password: string; + hostname?: string; +} + +const [adminCredentials, setAdminCredentials] = createSignal(); + +export { adminCredentials }; + +interface Props {} + +const Credentials: Component = (props) => { + const validationHandler = async (values: any) => { + const { database, username, password } = values; + let errors: any = {}; + try { + const response = await fetch(database, { mode: 'cors' }); + const dbStatus = await response.json(); + if (!dbStatus.couchdb) { + errors.database = 'The URL is not a couchdb instance'; + } + } catch (error) { + // console.error({ + // caller: 'Credentials / validationHandler / database root', + // error, + // }); + errors.database = "Can't access the database"; + } + if (!!errors.database) { + return errors; + } + try { + const authString = `${username}:${password}`; + const headers = new Headers(); + headers.set('Authorization', 'Basic ' + btoa(authString)); + const response = await fetch(`${database}//_all_dbs`, { + mode: 'cors', + headers, + }); + const dbStatus = await response.json(); + if (!!dbStatus.error) { + errors.username = dbStatus.reason || 'Wrong username or password'; + errors.password = dbStatus.reason || 'Wrong username or password'; + } + console.log({ + caller: 'Credentials / validationHandler', + props, + values, + errors, + dbStatus, + }); + // if (!dbStatus.couchdb) { + // errors.database = 'The URL is not a couchdb instance'; + // } + } catch (error) { + console.error({ + caller: 'Credentials / validationHandler / database root', + error, + }); + errors.username = 'Wrong username or password'; + errors.password = 'Wrong username or password'; + } + console.log({ + caller: 'Credentials / validationHandler', + props, + values, + errors, + }); + return errors; + }; + + const submitHandler = async (values: any, context: any) => { + console.log({ + caller: 'Credentials / submitHandler', + props, + values, + context, + }); + setAdminCredentials(values); + }; + + let { form, data } = createForm({ + onSubmit: submitHandler, + validate: validationHandler, + extend: reporter(), + // initialValues: passwords().get(url), + }); + + return ( + + + +
+ +
+ + Admin user name and password + + + X + +
+ +
+ Please enter the database URL and its admin username and + password. +
+
+ + Database URL + + + + User name + + + + Password + + + Please provide a valid password + + + Save +
+
+
+
+
+
+ ); +}; + +export default Credentials; diff --git a/src/components/credentials/index.ts b/src/components/credentials/index.ts new file mode 100644 index 0000000..0e971d7 --- /dev/null +++ b/src/components/credentials/index.ts @@ -0,0 +1 @@ +export { default, adminCredentials } from './Credentials'; diff --git a/src/components/password/Password.tsx b/src/components/password/Password.tsx deleted file mode 100644 index d3a26f5..0000000 --- a/src/components/password/Password.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { createForm } from '@felte/solid'; -import { Button, Dialog, TextField } from '@kobalte/core'; -import { cloneDeep } from 'lodash'; -import { Component, createEffect, createSignal } from 'solid-js'; - -export interface UsernamePassword { - username: string; - password: string; -} - -interface Props { - url: string; - usernamePassword: (params: UsernamePassword) => void; - open: () => boolean; - setOpen: (open: boolean) => void; -} - -const [passwords, setPasswords] = createSignal( - new Map() -); - -const Password: Component = (props) => { - const { url, usernamePassword, open, setOpen } = props; - - const submitHandler = async (values: any, context: any) => { - console.log({ - caller: 'Password / submitHandler', - props, - values, - context, - }); - const unPw = { username: values.username, password: values.password }; - const newPasswords = cloneDeep(passwords()); - newPasswords.set(url, unPw); - setPasswords(newPasswords); - - usernamePassword(unPw); - }; - - let { form, data } = createForm({ - onSubmit: submitHandler, - initialValues: passwords().get(url), - }); - - createEffect(() => { - const unPw = passwords().get(url); - console.log({ - caller: 'Password / createEffect', - props, - passwords: passwords(), - unPw, - }); - const newForm = createForm({ - onSubmit: submitHandler, - initialValues: passwords().get(url), - }); - form = newForm.form; - data = newForm.data; - }); - - return ( - - - -
- -
- - Admin user name and password - - - X - -
- -
Please enter the admin and password for {url}
-
- - User name - - - - Password - - - Please provide a valid password - - - Save and create -
-
-
-
-
-
- ); -}; - -export default Password; diff --git a/src/components/password/index.ts b/src/components/password/index.ts deleted file mode 100644 index e15b6dd..0000000 --- a/src/components/password/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default, UsernamePassword } from './Password'; diff --git a/src/components/user/User.tsx b/src/components/user/User.tsx index 4aa7de9..6a2490c 100644 --- a/src/components/user/User.tsx +++ b/src/components/user/User.tsx @@ -10,7 +10,6 @@ import { put } from '~/lib/db'; import { useNavigate } from 'solid-start'; import { toHex } from '~/lib/to-hex'; import { cloneDeep } from 'lodash'; -import Password, { UsernamePassword } from '../password/Password'; interface Props { values?: any; @@ -151,17 +150,6 @@ const User: Component = (props) => { setOpenUserNamePasswordDialog(true); }; - const usernamePasswordHandler = async ( - usernamePassword: UsernamePassword - ) => { - console.log({ - caller: 'User / usernamePasswordHandler', - props, - usernamePassword, - }); - setOpenUserNamePasswordDialog(false); - }; - console.log({ caller: 'User ', props, @@ -269,12 +257,6 @@ const User: Component = (props) => { - ); }; diff --git a/src/components/user/style.css b/src/components/user/style.css index bdd1dc4..06d4773 100644 --- a/src/components/user/style.css +++ b/src/components/user/style.css @@ -19,7 +19,6 @@ form { text-align: left; } - /* Dialog */ .dialog__trigger { @@ -99,6 +98,14 @@ form { font-size: 16px; color: hsl(240 5% 26%); } + +.dialog__description > div { + padding-bottom: 20px; + font-size: 18px; + justify-content: space-between; + color: hsl(240 6% 10%); +} + @keyframes overlayShow { from { opacity: 0; diff --git a/src/root.tsx b/src/root.tsx index 269af6b..fa92457 100644 --- a/src/root.tsx +++ b/src/root.tsx @@ -1,6 +1,6 @@ // @refresh reload -import { Routes } from "@solidjs/router"; -import { Suspense } from "solid-js"; +import { Routes } from '@solidjs/router'; +import { createSignal, Show, Suspense } from 'solid-js'; import { Body, FileRoutes, @@ -9,16 +9,16 @@ import { Meta, Scripts, Title, -} from "solid-start"; -import { ErrorBoundary } from "solid-start/error-boundary"; +} from 'solid-start'; +import { ErrorBoundary } from 'solid-start/error-boundary'; export default function Root() { return ( - + - SolidStart - With Vitest - - + Dyomedea users + + diff --git a/src/routes/user/index.tsx b/src/routes/user/index.tsx index bbb6160..2c1616f 100644 --- a/src/routes/user/index.tsx +++ b/src/routes/user/index.tsx @@ -1,10 +1,21 @@ -import Users from "~/components/users"; +import { createEffect, Show } from 'solid-js'; +import Credentials, { adminCredentials } from '~/components/credentials'; +import Users from '~/components/users'; + +createEffect(() => { + console.log({ + caller: 'user/index / createEffect', + adminCredentials: adminCredentials(), + }); +}); export default () => { return (

Users

- + }> + +
); };