🏗 Wiring up Settings form
This commit is contained in:
@@ -1,13 +1,31 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { IExtractionOptions } from "threetwo-ui-typings";
|
import { IExtractionOptions } from "threetwo-ui-typings";
|
||||||
import {} from "../constants/action-types";
|
import { SETTINGS_OBJECT_FETCHED } from "../constants/action-types";
|
||||||
import { SETTINGS_SERVICE_BASE_URI } from "../constants/endpoints";
|
import { SETTINGS_SERVICE_BASE_URI } from "../constants/endpoints";
|
||||||
|
|
||||||
export const saveSettings = (settingsObject) => async (dispatch) => {
|
export const saveSettings =
|
||||||
|
(settingsObject, airdcppUserSettings) => async (dispatch) => {
|
||||||
|
const result = await axios({
|
||||||
|
url: `${SETTINGS_SERVICE_BASE_URI}/saveSettings`,
|
||||||
|
method: "POST",
|
||||||
|
data: { settingsObject, airdcppUserSettings },
|
||||||
|
});
|
||||||
|
dispatch({
|
||||||
|
type: SETTINGS_OBJECT_FETCHED,
|
||||||
|
data: result.data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSettings = (settingsKey?) => async (dispatch) => {
|
||||||
const result = await axios({
|
const result = await axios({
|
||||||
url: `${SETTINGS_SERVICE_BASE_URI}/saveSettings`,
|
url: `${SETTINGS_SERVICE_BASE_URI}/getSettings`,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
data: settingsObject,
|
data: settingsKey,
|
||||||
});
|
});
|
||||||
console.log(result);
|
{
|
||||||
|
dispatch({
|
||||||
|
type: SETTINGS_OBJECT_FETCHED,
|
||||||
|
data: result.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,91 +1,180 @@
|
|||||||
import React, { ReactElement } from "react";
|
import React, { ReactElement, useEffect } from "react";
|
||||||
import { Form, Field } from "react-final-form";
|
import { Form, Field } from "react-final-form";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { saveSettings } from "../actions/settings.actions";
|
import { saveSettings, getSettings } from "../actions/settings.actions";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { isUndefined, isEmpty } from "lodash";
|
||||||
|
|
||||||
export const AirDCPPSettingsForm = (): ReactElement => {
|
export const AirDCPPSettingsForm = (): ReactElement => {
|
||||||
|
const airdcppClientSettings = useSelector(
|
||||||
|
(state: RootState) => state.settings.data[0],
|
||||||
|
);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(getSettings());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
const onSubmit = async (values) => {
|
const onSubmit = async (values) => {
|
||||||
try {
|
try {
|
||||||
|
const fqdn = values.protocol + values.hostname;
|
||||||
const airdcppResponse = await axios({
|
const airdcppResponse = await axios({
|
||||||
url: `https://${values.airdcpp_hostname}/api/v1/sessions/authorize`,
|
url: `${fqdn}/api/v1/sessions/authorize`,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
data: {
|
data: {
|
||||||
username: values.airdcpp_username,
|
username: values.username,
|
||||||
password: values.airdcpp_password,
|
password: values.password,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (airdcppResponse.status === 200) {
|
if (airdcppResponse.status === 200) {
|
||||||
dispatch(saveSettings(values));
|
dispatch(saveSettings(values, airdcppResponse.data));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const validate = async () => {};
|
const validate = async () => {};
|
||||||
|
const initFormData = !isUndefined(airdcppClientSettings)
|
||||||
|
? airdcppClientSettings.directConnect.client
|
||||||
|
: null;
|
||||||
return (
|
return (
|
||||||
<Form
|
<>
|
||||||
onSubmit={onSubmit}
|
<Form
|
||||||
validate={validate}
|
onSubmit={onSubmit}
|
||||||
render={({ handleSubmit }) => (
|
validate={validate}
|
||||||
<form onSubmit={handleSubmit}>
|
initialValues={initFormData}
|
||||||
<h2>AirDC++ Connection Information</h2>
|
render={({ handleSubmit }) => (
|
||||||
<div className="field">
|
<form onSubmit={handleSubmit}>
|
||||||
|
<h2>AirDC++ Connection Information</h2>
|
||||||
<label className="label">AirDC++ Hostname</label>
|
<label className="label">AirDC++ Hostname</label>
|
||||||
<div className="control">
|
<div className="field has-addons">
|
||||||
<Field
|
<p className="control">
|
||||||
name="airdcpp_hostname"
|
<span className="select">
|
||||||
component="input"
|
<Field name="protocol" component="select">
|
||||||
className="input"
|
<option value="http://">http://</option>
|
||||||
placeholder="111.222.333.4 / one.airdcpp.com"
|
<option value="https://">https://</option>
|
||||||
/>
|
</Field>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="control is-expanded">
|
||||||
|
<Field
|
||||||
|
name="hostname"
|
||||||
|
component="input"
|
||||||
|
className="input"
|
||||||
|
placeholder="AirDC++ host IP / hostname"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="field">
|
||||||
<div className="field">
|
<div className="is-clearfix">
|
||||||
<div className="is-clearfix">
|
<label className="label">Credentials</label>
|
||||||
<label className="label">Credentials</label>
|
|
||||||
</div>
|
|
||||||
<div className="field-body">
|
|
||||||
<div className="field">
|
|
||||||
<p className="control is-expanded has-icons-left">
|
|
||||||
<Field
|
|
||||||
name="airdcpp_username"
|
|
||||||
component="input"
|
|
||||||
className="input"
|
|
||||||
placeholder="Username"
|
|
||||||
/>
|
|
||||||
<span className="icon is-small is-left">
|
|
||||||
<i className="fa-solid fa-user-ninja"></i>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="field">
|
<div className="field-body">
|
||||||
<p className="control is-expanded has-icons-left has-icons-right">
|
<div className="field">
|
||||||
<Field
|
<p className="control is-expanded has-icons-left">
|
||||||
name="airdcpp_password"
|
<Field
|
||||||
component="input"
|
name="username"
|
||||||
type="password"
|
component="input"
|
||||||
className="input"
|
className="input"
|
||||||
placeholder="Password"
|
placeholder="Username"
|
||||||
/>
|
/>
|
||||||
<span className="icon is-small is-left">
|
<span className="icon is-small is-left">
|
||||||
<i className="fa-solid fa-lock"></i>
|
<i className="fa-solid fa-user-ninja"></i>
|
||||||
</span>
|
</span>
|
||||||
<span className="icon is-small is-right">
|
</p>
|
||||||
<i className="fas fa-check"></i>
|
</div>
|
||||||
</span>
|
<div className="field">
|
||||||
</p>
|
<p className="control is-expanded has-icons-left has-icons-right">
|
||||||
|
<Field
|
||||||
|
name="password"
|
||||||
|
component="input"
|
||||||
|
type="password"
|
||||||
|
className="input"
|
||||||
|
placeholder="Password"
|
||||||
|
/>
|
||||||
|
<span className="icon is-small is-left">
|
||||||
|
<i className="fa-solid fa-lock"></i>
|
||||||
|
</span>
|
||||||
|
<span className="icon is-small is-right">
|
||||||
|
<i className="fas fa-check"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" className="button is-primary">
|
<button type="submit" className="button is-primary">
|
||||||
Submit
|
{!isEmpty(initFormData) ? "Update" : "Save"}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{!isUndefined(airdcppClientSettings) &&
|
||||||
|
!isEmpty(airdcppClientSettings) ? (
|
||||||
|
<div className="mt-4 is-clearfix">
|
||||||
|
<div className="card">
|
||||||
|
<div className="card-content">
|
||||||
|
<span className="icon is-medium is-pulled-right">
|
||||||
|
<i className="fa-solid fa-circle has-text-success"></i>
|
||||||
|
</span>
|
||||||
|
<div className="content is-size-7">
|
||||||
|
<dl>
|
||||||
|
<dt>{airdcppClientSettings._id}</dt>
|
||||||
|
<dt>
|
||||||
|
Client version:{" "}
|
||||||
|
{
|
||||||
|
airdcppClientSettings.directConnect.client
|
||||||
|
.airdcppUserSettings.system_info.client_version
|
||||||
|
}
|
||||||
|
</dt>
|
||||||
|
<dt>
|
||||||
|
Hostname:{" "}
|
||||||
|
{
|
||||||
|
airdcppClientSettings.directConnect.client
|
||||||
|
.airdcppUserSettings.system_info.hostname
|
||||||
|
}
|
||||||
|
</dt>
|
||||||
|
<dt>
|
||||||
|
Platform:{" "}
|
||||||
|
{
|
||||||
|
airdcppClientSettings.directConnect.client
|
||||||
|
.airdcppUserSettings.system_info.platform
|
||||||
|
}
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
Username:{" "}
|
||||||
|
{
|
||||||
|
airdcppClientSettings.directConnect.client
|
||||||
|
.airdcppUserSettings.user.username
|
||||||
|
}
|
||||||
|
</dt>
|
||||||
|
|
||||||
|
<dt>
|
||||||
|
Active Sessions:{" "}
|
||||||
|
{
|
||||||
|
airdcppClientSettings.directConnect.client
|
||||||
|
.airdcppUserSettings.user.active_sessions
|
||||||
|
}
|
||||||
|
</dt>
|
||||||
|
<dt>
|
||||||
|
Permissions:{" "}
|
||||||
|
<pre>
|
||||||
|
{JSON.stringify(
|
||||||
|
airdcppClientSettings.directConnect.client
|
||||||
|
.airdcppUserSettings.user.permissions,
|
||||||
|
undefined,
|
||||||
|
2,
|
||||||
|
)}
|
||||||
|
</pre>
|
||||||
|
</dt>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { Form, Field } from "react-final-form";
|
|||||||
import { getComicBooks } from "../actions/fileops.actions";
|
import { getComicBooks } from "../actions/fileops.actions";
|
||||||
import { isNil } from "lodash";
|
import { isNil } from "lodash";
|
||||||
import { IMPORT_SERVICE_HOST } from "../constants/endpoints";
|
import { IMPORT_SERVICE_HOST } from "../constants/endpoints";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
interface IComicBookLibraryProps {
|
interface IComicBookLibraryProps {
|
||||||
matches?: unknown;
|
matches?: unknown;
|
||||||
@@ -142,6 +143,26 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<div className="column one-fifth">
|
||||||
|
<div className="field has-addons">
|
||||||
|
<p className="control">
|
||||||
|
<button className="button">
|
||||||
|
<span className="icon is-small">
|
||||||
|
<i className="fa-solid fa-list"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
<p className="control">
|
||||||
|
<button className="button">
|
||||||
|
<Link to="/library-grid">
|
||||||
|
<span className="icon is-small">
|
||||||
|
<i className="fa-solid fa-image"></i>
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -292,6 +313,7 @@ export const Library = ({}: IComicBookLibraryProps): ReactElement => {
|
|||||||
<section className="container">
|
<section className="container">
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<h1 className="title">Library</h1>
|
<h1 className="title">Library</h1>
|
||||||
|
|
||||||
<SearchBar />
|
<SearchBar />
|
||||||
<div>
|
<div>
|
||||||
<div className="library">
|
<div className="library">
|
||||||
|
|||||||
@@ -46,9 +46,7 @@ const Navbar: React.FunctionComponent = (props) => {
|
|||||||
<Link to="/library" className="navbar-item">
|
<Link to="/library" className="navbar-item">
|
||||||
Library
|
Library
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/library-grid" className="navbar-item">
|
|
||||||
Library Grid
|
|
||||||
</Link>
|
|
||||||
<Link to="/search" className="navbar-item">
|
<Link to="/search" className="navbar-item">
|
||||||
Search
|
Search
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -34,10 +34,8 @@ export const Settings = (props: ISettingsProps): ReactElement => {
|
|||||||
<aside className="menu">
|
<aside className="menu">
|
||||||
{map(settingsObject, (settingObject, idx) => {
|
{map(settingsObject, (settingObject, idx) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<div key={idx}>
|
||||||
<p className="menu-label" key={idx}>
|
<p className="menu-label">{settingObject.category}</p>
|
||||||
{settingObject.category}
|
|
||||||
</p>
|
|
||||||
{/* First level children */}
|
{/* First level children */}
|
||||||
{!isUndefined(settingObject.children) ? (
|
{!isUndefined(settingObject.children) ? (
|
||||||
<ul className="menu-list" key={settingObject.id}>
|
<ul className="menu-list" key={settingObject.id}>
|
||||||
@@ -78,7 +76,7 @@ export const Settings = (props: ISettingsProps): ReactElement => {
|
|||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
SETTINGS_CALL_IN_PROGRESS,
|
SETTINGS_CALL_IN_PROGRESS,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
const initialState = {
|
const initialState = {
|
||||||
settings: {},
|
data: {},
|
||||||
inProgress: false,
|
inProgress: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user