forked from github-starred/komodo
improve changes made visibility
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user