🐳 Added Docker vars in the UI
This commit is contained in:
38
src/client/components/Settings/DockerVars/DockerVars.tsx
Normal file
38
src/client/components/Settings/DockerVars/DockerVars.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export const DockerVars = (): React.ReactElement => {
|
||||
const [environmentVariables, setEnvironmentVariables] = React.useState<
|
||||
Record<string, string>
|
||||
>({});
|
||||
const { data } = useQuery({
|
||||
queryKey: ["docker-vars"],
|
||||
queryFn: async () => {
|
||||
await axios({
|
||||
method: "GET",
|
||||
url: "http://localhost:3000/api/settings/getEnvironmentVariables",
|
||||
}).then((response) => {
|
||||
setEnvironmentVariables(response.data);
|
||||
});
|
||||
},
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
});
|
||||
console.log("Docker Vars: ", environmentVariables);
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<h2 className="text-xl font-semibold">Docker Environment Variables</h2>
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
<pre>
|
||||
{Object.entries(environmentVariables).length > 0
|
||||
? JSON.stringify(environmentVariables, null, 2)
|
||||
: "No environment variables found."}
|
||||
</pre>
|
||||
</p>
|
||||
{/* Add your form or content for Docker environment variables here */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DockerVars;
|
||||
@@ -4,6 +4,7 @@ import { AirDCPPHubsForm } from "./AirDCPPSettings/AirDCPPHubsForm";
|
||||
import { QbittorrentConnectionForm } from "./QbittorrentSettings/QbittorrentConnectionForm";
|
||||
import { SystemSettingsForm } from "./SystemSettings/SystemSettingsForm";
|
||||
import ProwlarrSettingsForm from "./ProwlarrSettings/ProwlarrSettingsForm";
|
||||
import DockerVars from "./DockerVars/DockerVars";
|
||||
import { ServiceStatuses } from "../ServiceStatuses/ServiceStatuses";
|
||||
import settingsObject from "../../constants/settings/settingsMenu.json";
|
||||
import { isUndefined, map } from "lodash";
|
||||
@@ -12,139 +13,130 @@ interface ISettingsProps {}
|
||||
|
||||
export const Settings = (props: ISettingsProps): ReactElement => {
|
||||
const [active, setActive] = useState("gen-db");
|
||||
console.log(active);
|
||||
const [expanded, setExpanded] = useState<Record<string, boolean>>({});
|
||||
|
||||
const toggleExpanded = (id: string) => {
|
||||
setExpanded((prev) => ({
|
||||
...prev,
|
||||
[id]: !prev[id],
|
||||
}));
|
||||
};
|
||||
|
||||
const settingsContent = [
|
||||
{
|
||||
id: "adc-hubs",
|
||||
content: (
|
||||
<div key="adc-hubs">
|
||||
<AirDCPPHubsForm />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "adc-connection",
|
||||
content: (
|
||||
<div key="adc-connection">
|
||||
<AirDCPPSettingsForm />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "qbt-connection",
|
||||
content: (
|
||||
<div key="qbt-connection">
|
||||
<QbittorrentConnectionForm />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "prwlr-connection",
|
||||
content: (
|
||||
<>
|
||||
<ProwlarrSettingsForm />
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "core-service",
|
||||
content: <>a</>,
|
||||
},
|
||||
{
|
||||
id: "flushdb",
|
||||
content: (
|
||||
<div key="flushdb">
|
||||
<SystemSettingsForm />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{ id: "adc-hubs", content: <AirDCPPHubsForm /> },
|
||||
{ id: "adc-connection", content: <AirDCPPSettingsForm /> },
|
||||
{id: "gen-docker-vars", content: <DockerVars />},
|
||||
{ id: "qbt-connection", content: <QbittorrentConnectionForm /> },
|
||||
{ id: "prwlr-connection", content: <ProwlarrSettingsForm /> },
|
||||
{ id: "core-service", content: <>a</> },
|
||||
{ id: "flushdb", content: <SystemSettingsForm /> },
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<section>
|
||||
{/* Header */}
|
||||
<header className="bg-slate-200 dark:bg-slate-500">
|
||||
<div className="mx-auto max-w-screen-xl px-2 py-2 sm:px-6 sm:py-8 lg:px-8 lg:py-4">
|
||||
<div className="mx-auto max-w-screen-xl px-4 py-6 sm:px-6 lg:px-8">
|
||||
<div className="sm:flex sm:items-center sm:justify-between">
|
||||
<div className="text-center sm:text-left">
|
||||
<h1 className="text-2xl font-bold text-gray-900 dark:text-white sm:text-3xl">
|
||||
<h1 className="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-white">
|
||||
Settings
|
||||
</h1>
|
||||
|
||||
<p className="mt-1.5 text-sm text-gray-500 dark:text-white">
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-white">
|
||||
Import comics into the ThreeTwo library.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="flex flex-row">
|
||||
<div className="inset-y-0 w-80 dark:bg-gray-800 bg-slate-300 text-white overflow-y-auto">
|
||||
<aside className="px-4 py-4 sm:px-6 sm:py-8 lg:px-8">
|
||||
{map(settingsObject, (settingObject, idx) => {
|
||||
return (
|
||||
|
||||
{/* Main Layout */}
|
||||
<div className="flex gap-8 px-12 py-6">
|
||||
{/* Sidebar */}
|
||||
<div className="relative z-30">
|
||||
<aside
|
||||
className="sticky top-6 w-72 max-h-[90vh]
|
||||
rounded-2xl shadow-xl backdrop-blur-md
|
||||
bg-white/70 dark:bg-slate-800/60
|
||||
border border-slate-200 dark:border-slate-700
|
||||
overflow-hidden"
|
||||
>
|
||||
<div className="px-4 py-6 overflow-y-auto">
|
||||
{map(settingsObject, (settingObject, idx) => (
|
||||
<div
|
||||
className="w-64 py-2 text-slate-700 dark:text-slate-400"
|
||||
key={idx}
|
||||
className="mb-6 text-slate-700 dark:text-slate-300"
|
||||
>
|
||||
<h3 className="text-l pb-2">
|
||||
<h3 className="text-xs font-semibold text-slate-500 dark:text-slate-400 tracking-wide mb-3">
|
||||
{settingObject.category.toUpperCase()}
|
||||
</h3>
|
||||
{/* First level children */}
|
||||
{!isUndefined(settingObject.children) ? (
|
||||
<ul key={settingObject.id}>
|
||||
|
||||
{!isUndefined(settingObject.children) && (
|
||||
<ul>
|
||||
{map(settingObject.children, (item, idx) => {
|
||||
const isOpen = expanded[item.id];
|
||||
|
||||
return (
|
||||
<li key={idx} className="mb-2">
|
||||
<a
|
||||
className={
|
||||
item.id.toString() === active
|
||||
? "is-active flex items-center"
|
||||
: "flex items-center"
|
||||
}
|
||||
onClick={() => setActive(item.id.toString())}
|
||||
<li key={idx} className="mb-1">
|
||||
<div
|
||||
onClick={() => toggleExpanded(item.id)}
|
||||
className={`cursor-pointer flex justify-between items-center px-1 py-1 rounded-md transition-colors hover:bg-white/50 dark:hover:bg-slate-700 ${
|
||||
item.id === active
|
||||
? "font-semibold text-blue-600 dark:text-blue-400"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{item.displayName}
|
||||
</a>
|
||||
{/* Second level children */}
|
||||
{!isUndefined(item.children) ? (
|
||||
<ul className="pl-4 mt-2">
|
||||
{map(item.children, (item, idx) => (
|
||||
<li key={item.id} className="mb-2">
|
||||
<span
|
||||
onClick={() => setActive(item.id.toString())}
|
||||
className="flex-1"
|
||||
>
|
||||
{item.displayName}
|
||||
</span>
|
||||
{!isUndefined(item.children) && (
|
||||
<span className="text-xs opacity-60">
|
||||
{isOpen ? "−" : "+"}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isUndefined(item.children) && isOpen && (
|
||||
<ul className="pl-4 mt-1">
|
||||
{map(item.children, (subItem) => (
|
||||
<li key={subItem.id} className="mb-1">
|
||||
<a
|
||||
className={
|
||||
item.id.toString() === active
|
||||
? "is-active flex items-center"
|
||||
: "flex items-center"
|
||||
}
|
||||
onClick={() =>
|
||||
setActive(item.id.toString())
|
||||
setActive(subItem.id.toString())
|
||||
}
|
||||
className={`cursor-pointer flex items-center px-1 py-1 rounded-md transition-colors hover:bg-white/50 dark:hover:bg-slate-700 ${
|
||||
subItem.id.toString() === active
|
||||
? "font-semibold text-blue-600 dark:text-blue-400"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{item.displayName}
|
||||
{subItem.displayName}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
) : null}
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
{/* content for settings */}
|
||||
<div className="flex mx-12">
|
||||
<div className="">
|
||||
{map(settingsContent, ({ id, content }) =>
|
||||
active === id ? content : null,
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Content */}
|
||||
<main className="flex-1 px-2 py-2">
|
||||
{settingsContent.map(({ id, content }) =>
|
||||
active === id ? <div key={id}>{content}</div> : null,
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
"displayName": "Dashboard"
|
||||
},
|
||||
{
|
||||
"id": "gen-gls",
|
||||
"displayName": "Global Search"
|
||||
"id": "gen-docker-vars",
|
||||
"displayName": "Docker ENV vars"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user