improve changes made visibility

This commit is contained in:
mbecker20
2024-06-02 20:54:41 -07:00
parent 050c29f4a3
commit 0ce5248292
4 changed files with 192 additions and 11 deletions

View File

@@ -60,8 +60,10 @@ export const ConfigLayout = <
variant="outline"
onClick={onReset}
disabled={disabled || (config ? !Object.keys(config).length : true)}
className="flex items-center gap-2"
>
<History className="w-4 h-4" />
Reset
</Button>
{changesMade && (
<ConfirmUpdate

View File

@@ -296,8 +296,13 @@ export const ConfirmUpdate = ({
return (
<Dialog open={open} onOpenChange={set}>
<DialogTrigger asChild>
<Button onClick={() => set(true)} disabled={disabled}>
<Button
onClick={() => set(true)}
disabled={disabled}
className="flex items-center gap-2"
>
<Save className="w-4 h-4" />
Save
</Button>
</DialogTrigger>
<DialogContent>

View File

@@ -19,8 +19,9 @@ import {
} from "@ui/select";
import { Textarea } from "@ui/textarea";
import { PlusCircle } from "lucide-react";
import { ReactNode, useEffect, useState } from "react";
import { ReactNode, RefObject, createRef, useEffect, useState } from "react";
import { CopyGithubWebhook, LabelsConfig, ResourceSelector } from "../common";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ui/tabs";
export const BuildConfig = ({
id,
@@ -270,24 +271,171 @@ const BuildArgs = ({
set: (input: Partial<Types.BuildConfig>) => void;
disabled: boolean;
}) => {
const [args, setArgs] = useState(env_to_text(vars));
useEffect(() => {
!!args && set({ build_args: text_to_env(args) });
}, [args, set]);
const ref = createRef<HTMLTextAreaElement>();
const [args, setArgs] = useState<string>();
useEffect(() => setArgs(env_to_text(vars)), [vars]);
const update = () => {
if (!args) return;
const parsed = text_to_env(args);
// Diff the vars from old to new
for (const [v, i] of vars.map(
(v, i) => [v, i] as [Types.EnvironmentVar, number]
)) {
const _v = parsed[i];
if (!_v || v.value !== _v.value || v.variable !== _v.variable) {
set({ build_args: parsed });
return;
}
}
// Diff the vars from new to old
for (const [v, i] of parsed.map(
(v, i) => [v, i] as [Types.EnvironmentVar, number]
)) {
const _v = vars[i];
if (!_v || v.value !== _v.value || v.variable !== _v.variable) {
set({ build_args: parsed });
return;
}
}
};
return (
<ConfigItem className="flex-col gap-4 items-start">
{!disabled && <Secrets args={args} setArgs={setArgs} argsRef={ref} />}
<Textarea
className="min-h-[300px]"
ref={ref}
className="min-h-[400px]"
placeholder="VARIABLE=value"
value={args}
onChange={(e) => setArgs(e.target.value)}
onBlur={update}
disabled={disabled}
/>
</ConfigItem>
);
};
const Secrets = ({
args,
setArgs,
argsRef,
}: {
args?: string;
setArgs: (args: string) => void;
argsRef: RefObject<HTMLTextAreaElement>;
}) => {
const { variables, secrets } = useRead("ListVariables", {}).data ?? {
variables: [],
secrets: [],
};
const _args = args || "";
if (variables.length === 0 && secrets.length === 0) return;
if (variables.length === 0) {
// ONLY SECRETS
return (
<div className="flex flex-col gap-2 w-full">
<h2 className="text-muted-foreground">Secrets</h2>
<div className="flex gap-4 items-center flex-wrap w-full">
{secrets.map((secret) => (
<Button
variant="secondary"
key={secret}
onClick={() =>
setArgs(
_args.slice(0, argsRef.current?.selectionStart) +
`[[${secret}]]` +
_args.slice(argsRef.current?.selectionStart, undefined)
)
}
>
{secret}
</Button>
))}
</div>
</div>
);
}
if (secrets.length === 0) {
// ONLY VARIABLES
return (
<div className="flex flex-col gap-2 w-full">
<h2 className="text-muted-foreground">Variables</h2>
<div className="flex gap-4 items-center flex-wrap w-full">
{variables.map(({ name }) => (
<Button
variant="secondary"
key={name}
onClick={() =>
setArgs(
_args.slice(0, argsRef.current?.selectionStart) +
`[[${name}]]` +
_args.slice(argsRef.current?.selectionStart, undefined)
)
}
>
{name}
</Button>
))}
</div>
</div>
);
}
return (
<Tabs className="w-full" defaultValue="Variables">
<TabsList>
<TabsTrigger value="Variables">Variables</TabsTrigger>
<TabsTrigger value="Secrets">Secrets</TabsTrigger>
</TabsList>
<TabsContent value="Variables">
<div className="flex gap-4 items-center w-full flex-wrap pt-1">
{variables.map(({ name }) => (
<Button
variant="secondary"
key={name}
onClick={() =>
setArgs(
_args.slice(0, argsRef.current?.selectionStart) +
`[[${name}]]` +
_args.slice(argsRef.current?.selectionStart, undefined)
)
}
>
{name}
</Button>
))}
</div>
</TabsContent>
<TabsContent value="Secrets">
<div className="flex gap-4 items-center w-full flex-wrap pt-1">
{secrets.map((secret) => (
<Button
variant="secondary"
key={secret}
onClick={() =>
setArgs(
_args.slice(0, argsRef.current?.selectionStart) +
`[[${secret}]]` +
_args.slice(argsRef.current?.selectionStart, undefined)
)
}
>
{secret}
</Button>
))}
</div>
</TabsContent>
</Tabs>
);
};
const DockerOrganizations = ({
value,
set,

View File

@@ -20,10 +20,35 @@ export const EnvVars = ({
server?: string;
}) => {
const ref = createRef<HTMLTextAreaElement>();
const [env, setEnv] = useState(env_to_text(vars));
useEffect(() => {
!!env && set({ environment: text_to_env(env) });
}, [env, set]);
const [env, setEnv] = useState<string>();
useEffect(() => setEnv(env_to_text(vars)), [vars]);
const update = () => {
if (!env) return;
const parsed = text_to_env(env);
// Diff the vars from old to new
for (const [v, i] of vars.map(
(v, i) => [v, i] as [Types.EnvironmentVar, number]
)) {
const _v = parsed[i];
if (!_v || v.value !== _v.value || v.variable !== _v.variable) {
set({ environment: parsed });
return;
}
}
// Diff the vars from new to old
for (const [v, i] of parsed.map(
(v, i) => [v, i] as [Types.EnvironmentVar, number]
)) {
const _v = vars[i];
if (!_v || v.value !== _v.value || v.variable !== _v.variable) {
set({ environment: parsed });
return;
}
}
};
return (
<ConfigItem className="flex-col gap-4 items-start">
@@ -36,6 +61,7 @@ export const EnvVars = ({
placeholder="VARIABLE=value"
value={env}
onChange={(e) => setEnv(e.target.value)}
onBlur={update}
disabled={disabled}
/>
</ConfigItem>