diff --git a/frontend/src/components/config/index.tsx b/frontend/src/components/config/index.tsx index 8cae92f91..e8fb44d3a 100644 --- a/frontend/src/components/config/index.tsx +++ b/frontend/src/components/config/index.tsx @@ -20,7 +20,9 @@ import { Fragment, ReactNode, SetStateAction, useState } from "react"; const keys = >(obj: T) => Object.keys(obj) as Array; -export const ConfigLayout = ["config"]>({ +export const ConfigLayout = < + T extends Types.Resource["config"] +>({ config, children, onConfirm, @@ -46,10 +48,12 @@ export const ConfigLayout = ["config" > - {Object.keys(config).length ? : null} + {Object.keys(config).length ? ( + + ) : null} } > @@ -200,4 +204,4 @@ export const ConfigAgain = < })} ); -}; \ No newline at end of file +}; diff --git a/frontend/src/components/config/util.tsx b/frontend/src/components/config/util.tsx index 64835d9e2..53bbd036a 100644 --- a/frontend/src/components/config/util.tsx +++ b/frontend/src/components/config/util.tsx @@ -19,7 +19,7 @@ import { SearchX, } from "lucide-react"; import { ReactNode, useState } from "react"; -import { cn } from "@lib/utils"; +import { cn, snake_case_to_upper_space_case } from "@lib/utils"; import { Dialog, DialogContent, @@ -52,7 +52,7 @@ export const ConfigItem = ({ className )} > -
{label}
+
{snake_case_to_upper_space_case(label)}
{children} ); @@ -295,7 +295,7 @@ export const InputList = ({ // intent="success" onClick={() => set({ [field]: [...values, ""] } as Partial)} > - Add Docker Account + Add {snake_case_to_upper_space_case(field as string).slice(0, -1)} diff --git a/frontend/src/components/layouts.tsx b/frontend/src/components/layouts.tsx index da9ebf0e9..43a55007c 100644 --- a/frontend/src/components/layouts.tsx +++ b/frontend/src/components/layouts.tsx @@ -94,7 +94,7 @@ export const Page = ({ ); interface SectionProps { - title: string; + title: ReactNode; children: ReactNode; icon?: ReactNode; actions?: ReactNode; @@ -129,7 +129,7 @@ export const NewResource = ({ return ( - diff --git a/frontend/src/components/omnibar.tsx b/frontend/src/components/omnibar.tsx index e597b8566..e11c7692d 100644 --- a/frontend/src/components/omnibar.tsx +++ b/frontend/src/components/omnibar.tsx @@ -15,6 +15,9 @@ import { useNavigate } from "react-router-dom"; import { ResourceComponents } from "./resources"; import { UsableResource } from "@types"; import { RESOURCE_TARGETS } from "@lib/utils"; +import { DeploymentComponents } from "./resources/deployment"; +import { BuildComponents } from "./resources/build"; +import { ServerComponents } from "./resources/server"; const ResourceGroup = ({ type, @@ -26,6 +29,8 @@ const ResourceGroup = ({ const data = useRead(`List${type}s`, {}).data; const Components = ResourceComponents[type]; + if (!data || !data.length) return + return ( {data?.map(({ id }) => { @@ -54,9 +59,10 @@ export const Omnibar = () => { useEffect(() => { const down = (e: KeyboardEvent) => { - console.log(e); + // This will ignore Shift + S if it is sent from input / textarea const target = e.target as any; if (target.matches("input") || target.matches("textarea")) return; + if (e.shiftKey && e.key === "S") { e.preventDefault(); set(true); @@ -90,8 +96,31 @@ export const Omnibar = () => { Home + nav("/deployments")} + > + + Deployments + + nav("/builds")} + > + + Builds + + nav("/servers")} + > + + Servers + + + {RESOURCE_TARGETS.map((rt) => ( diff --git a/frontend/src/components/resources/alerter/index.tsx b/frontend/src/components/resources/alerter/index.tsx index e44e210d0..7bdfecef5 100644 --- a/frontend/src/components/resources/alerter/index.tsx +++ b/frontend/src/components/resources/alerter/index.tsx @@ -17,7 +17,6 @@ import { Config } from "@components/config"; import { DataTable } from "@ui/data-table"; import { ResourceComponents } from ".."; import { Link } from "react-router-dom"; -import { fmt_date_with_minutes } from "@lib/utils"; import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card"; const useAlerter = (id?: string) => @@ -131,11 +130,6 @@ const AlerterTable = () => { }, }, { header: "Tags", accessorFn: ({ tags }) => tags.join(", ") }, - { - header: "Created", - accessorFn: ({ created_at }) => - fmt_date_with_minutes(new Date(created_at)), - }, ]} /> ); diff --git a/frontend/src/components/resources/build/config.tsx b/frontend/src/components/resources/build/config.tsx new file mode 100644 index 000000000..e8c752cda --- /dev/null +++ b/frontend/src/components/resources/build/config.tsx @@ -0,0 +1,105 @@ +import { Config } from "@components/config"; +import { + AccountSelector, + ConfigItem, + ResourceSelector, +} from "@components/config/util"; +import { useRead, useWrite } from "@lib/hooks"; +import { env_to_text, text_to_env } from "@lib/utils"; +import { Types } from "@monitor/client"; +import { Textarea } from "@ui/textarea"; +import { useEffect, useState } from "react"; + +export const BuildConfig = ({ id }: { id: string }) => { + const config = useRead("GetBuild", { build: id }).data?.config; + // const orgs = useRead("GetAccounts") + const [update, set] = useState>({}); + const { mutate } = useWrite("UpdateBuild"); + + if (!config) return null; + + return ( + mutate({ id, config: update })} + components={{ + general: { + general: { + builder_id: (id, set) => ( +
+
Builder
+ set({ builder_id })} + /> +
+ ), + }, + git: { + repo: true, + branch: true, + github_account: (account, set) => ( + set({ github_account })} + /> + ), + }, + docker: { + build_path: true, + dockerfile_path: true, + docker_account: (account, set) => ( + set({ docker_account })} + /> + ), + use_buildx: true, + // docker_organization, + }, + }, + "Build Args": { + "Build Args": { + build_args: (vars, set) => ( + + ), + skip_secret_interp: true, + }, + }, + }} + /> + ); +}; + +const BuildArgs = ({ + vars, + set, +}: { + vars: Types.EnvironmentVar[]; + set: (input: Partial) => void; +}) => { + const [args, setArgs] = useState(env_to_text(vars)); + useEffect(() => { + !!args && set({ build_args: text_to_env(args) }); + }, [args, set]); + + return ( + +