📑 Added a AirDCPP Settings form WIP

This commit is contained in:
2021-10-15 15:25:19 -07:00
parent 049c4266f3
commit ed120fb230
6 changed files with 200 additions and 38 deletions

View File

@@ -10,6 +10,7 @@ services:
ports: ports:
- "8050:8050" - "8050:8050"
- "3050:3050" - "3050:3050"
- "8051:8051"
depends_on: depends_on:
- rabbitmq - rabbitmq
- nginx - nginx

View File

@@ -0,0 +1,54 @@
import React, { ReactElement } from "react";
import { Form, Field } from "react-final-form";
export const AirDCPPSettingsForm = (): ReactElement => {
const onSubmit = () => {};
const validate = async () => {};
return (
<Form
onSubmit={onSubmit}
validate={validate}
render={({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<h2>Simple Default Input</h2>
<div>
<label>First Name</label>
<Field
name="firstName"
component="input"
placeholder="First Name"
/>
</div>
<h2>Render Function</h2>
<Field
name="bio"
render={({ input, meta }) => (
<div>
<label>Bio</label>
<textarea {...input} />
{meta.touched && meta.error && <span>{meta.error}</span>}
</div>
)}
/>
<h2>Render Function as Children</h2>
<Field name="phone">
{({ input, meta }) => (
<div>
<label>Phone</label>
<input type="text" {...input} placeholder="Phone" />
{meta.touched && meta.error && <span>{meta.error}</span>}
</div>
)}
</Field>
<button type="submit">Submit</button>
</form>
)}
/>
);
};
export default AirDCPPSettingsForm;

View File

@@ -260,9 +260,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
<div className="mt-5"> <div className="mt-5">
{!isEmpty(extractedComicBookArchive) ? ( {!isEmpty(extractedComicBookArchive) ? (
<DnD data={extractedComicBookArchive} /> <DnD data={extractedComicBookArchive} />
) : ( ) : null}
"..."
)}
</div> </div>
{!isEmpty(extractedComicBookArchive) ? ( {!isEmpty(extractedComicBookArchive) ? (
<div className="column mt-5"> <div className="column mt-5">

View File

@@ -1,52 +1,71 @@
import React, { useState, useEffect, useCallback, ReactElement } from "react"; import React, { useState, useEffect, useCallback, ReactElement } from "react";
import { AirDCPPSettingsForm } from "./AirDCPPSettingsForm";
import settingsObject from "../constants/settings/settingsMenu.json";
import { isUndefined, map } from "lodash";
interface ISettingsProps {} interface ISettingsProps {}
export const Settings = (props: ISettingsProps): ReactElement => { export const Settings = (props: ISettingsProps): ReactElement => {
const [active, setActive] = useState("gen-db");
return ( return (
<section className="container"> <section className="container">
<div className="columns"> <div className="columns">
<div className="section column is-one-quarter"> <div className="section column is-one-quarter">
<h1 className="title">Settings</h1> <h1 className="title">Settings</h1>
<aside className="menu"> <aside className="menu">
<p className="menu-label">General</p> {map(settingsObject, (settingObject, idx) => {
<ul className="menu-list"> return (
<li> <>
<a>Dashboard</a> <p className="menu-label" key={idx}>
</li> {settingObject.category}
<li> </p>
<a>Global Search</a> {/* First level children */}
</li> {!isUndefined(settingObject.children) ? (
</ul> <ul className="menu-list" key={settingObject.id}>
<p className="menu-label">Acquisition</p> {map(settingObject.children, (item, idx) => {
<ul className="menu-list"> return (
<li> <li key={item.id}>
<a className="is-active">AirDC++</a> <a
<ul> className={
<li> item.id.toString() === active ? "is-active" : ""
<a>Connection</a> }
</li> onClick={() => setActive(item.id.toString())}
<li> >
<a>Hubs</a> {item.displayName}
</li> </a>
<li> {/* Second level children */}
<a>Additional Configuration</a> {!isUndefined(item.children) ? (
</li> <ul>
</ul> {map(item.children, (item, idx) => (
</li> <li key={item.id}>
</ul> <a
<p className="menu-label">ComicVine</p> className={
<ul className="menu-list"> item.id.toString() === active
<li> ? "is-active"
<a>API</a> : ""
</li> }
<li> onClick={() =>
<a>Configuration</a> setActive(item.id.toString())
</li> }
</ul> >
{item.displayName}
</a>
</li>
))}
</ul>
) : null}
</li>
);
})}
</ul>
) : null}
</>
);
})}
</aside> </aside>
</div> </div>
</div> </div>
<AirDCPPSettingsForm />
</section> </section>
); );
}; };

View File

@@ -0,0 +1,58 @@
[
{
"id": 1,
"category": "general",
"displayName": "General",
"children": [
{
"id": "gen-db",
"displayName": "Dashboard"
},
{
"id": "gen-gls",
"displayName": "Global Search"
}
]
},
{
"id": 2,
"category": "acquisition",
"displayName": "Acquisition",
"children": [
{
"id": "adc",
"displayName": "AirDC++",
"children": [
{
"id": "adc-connection",
"displayName": "Connection"
},
{
"id": "adc-hubs",
"displayName": "Hubs"
},
{
"id": "adc-add-config",
"displayName": "Additional Configuration"
}
]
}
]
},
{
"id": 3,
"category": "comicvine",
"displayName": "Comic Vine",
"children": [
{
"id": "api",
"displayName": "API"
},
{
"id": "options",
"displayName": "Options"
}
]
}
]

View File

@@ -20,3 +20,35 @@ const changes = (object, base) => {
} }
}); });
}; };
export type TraverseFunction<T> = (
obj: T,
prop: string,
value: unknown,
scope: string[],
) => void;
/**
* Deep diff between two object, using lodash
* @param {Object} object Object to traverse
* @param {Object} fn Callback function
* @return {Object} Return a new object who represent the diff
*/
export const traverseObject = <T = Record<string, unknown>>(
object: T,
fn: TraverseFunction<T>,
): void => traverseInternal(object, fn, []);
const traverseInternal = <T = Record<string, unknown>>(
object: T,
fn: TraverseFunction<T>,
scope: string[] = [],
): void => {
Object.entries(object).forEach(([key, value]) => {
fn.apply(this, [object, key, value, scope]);
if (value !== null && typeof value === "object") {
traverseInternal(value, fn, scope.concat(key));
}
});
};