support uiHInt property in env vars (#526)

* support uiHInt property in env vars

* wip

* remove placeholder for app envs input
This commit is contained in:
Hoan Luu Huu
2025-05-26 06:34:29 +07:00
committed by GitHub
parent 36f22e2075
commit 19620116b5
3 changed files with 92 additions and 55 deletions

View File

@@ -798,6 +798,7 @@ export interface AppEnvProperty {
required?: boolean; required?: boolean;
default?: string | number | boolean; default?: string | number | boolean;
obscure?: boolean; obscure?: boolean;
uiHint?: "input" | "textarea" | "filepicker";
} }
export interface AppEnv { export interface AppEnv {

View File

@@ -10,6 +10,7 @@ import {
Passwd, Passwd,
Message, Message,
AccountSelect, AccountSelect,
FileUpload,
} from "src/components/forms"; } from "src/components/forms";
import { import {
vendors, vendors,
@@ -769,7 +770,7 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
const defaultValue = webhook.webhookEnv![key].default; const defaultValue = webhook.webhookEnv![key].default;
return ( return (
<div className="inp" key={key}> <div key={key}>
{isBoolean ? ( {isBoolean ? (
// Boolean input as checkbox // Boolean input as checkbox
<label htmlFor={`env_${key}`} className="chk"> <label htmlFor={`env_${key}`} className="chk">
@@ -784,10 +785,10 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
: Boolean(defaultValue) : Boolean(defaultValue)
} }
onChange={(e) => { onChange={(e) => {
setEnvVars({ setEnvVars((prev) => ({
...(envVars || {}), ...(prev || {}),
[key]: e.target.checked, [key]: e.target.checked,
}); }));
}} }}
/> />
<Tooltip <Tooltip
@@ -812,22 +813,21 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
)} )}
</Tooltip> </Tooltip>
</label> </label>
{webhook.webhookEnv![key].obscure ? ( {(() => {
<ObscureInput // Common props for both input types
name={`env_${key}`} const commonProps = {
id={`env_${key}`} id: `env_${key}`,
placeholder={ name: `env_${key}`,
webhook.webhookEnv![key].description required: webhook.webhookEnv![key].required,
} value:
required={webhook.webhookEnv![key].required}
value={
envVars && envVars[key] !== undefined envVars && envVars[key] !== undefined
? String(envVars[key]) ? String(envVars[key])
: defaultValue !== undefined : defaultValue !== undefined
? String(defaultValue) ? String(defaultValue)
: "" : "",
} onChange: (
onChange={(e) => { e: React.ChangeEvent<HTMLInputElement>,
) => {
// Convert to proper type based on schema // Convert to proper type based on schema
let newValue; let newValue;
if (isNumber) { if (isNumber) {
@@ -839,47 +839,75 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
newValue = e.target.value; newValue = e.target.value;
} }
setEnvVars({ setEnvVars((prev) => ({
...(envVars || {}), ...(prev || {}),
[key]: newValue, [key]: newValue,
}); }));
}} },
/> };
) : (
<input
id={`env_${key}`}
type={isNumber ? "number" : "text"}
name={`env_${key}`}
placeholder={
webhook.webhookEnv![key].description
}
required={webhook.webhookEnv![key].required}
value={
envVars && envVars[key] !== undefined
? String(envVars[key])
: defaultValue !== undefined
? String(defaultValue)
: ""
}
onChange={(e) => {
// Convert to proper type based on schema
let newValue;
if (isNumber) {
newValue =
e.target.value === ""
? ""
: Number(e.target.value);
} else {
newValue = e.target.value;
}
setEnvVars({ // Extra props only for regular input
...(envVars || {}), const inputSpecificProps = {
[key]: newValue, type: isNumber ? "number" : "text",
}); };
}}
/> const textAreaSpecificProps = {
)} rows: 6,
cols: 61,
};
// Choose component type based on obscure flag
const componentType = webhook.webhookEnv![key]
.obscure
? ObscureInput
: webhook.webhookEnv![key].uiHint || "input";
if (componentType === "filepicker") {
return (
<>
<FileUpload
id={`app_env_${key}`}
name={`app_env_${key}`}
handleFile={(file) => {
file
.text()
.then((content) => {
setEnvVars((prev) => ({
...(prev || {}),
[key]: content,
}));
})
.catch((err) => {
toastError(
`Failed to read file: ${err.message}`,
);
});
}}
placeholder="Choose a file"
required={
webhook.webhookEnv![key].required
}
/>
{React.createElement("textarea", {
...commonProps,
...inputSpecificProps,
...textAreaSpecificProps,
})}
</>
);
}
// Create the component with appropriate props
return React.createElement(
componentType,
webhook.webhookEnv![key].obscure
? commonProps
: {
...commonProps,
...inputSpecificProps,
...(webhook.webhookEnv![key].uiHint ===
"textarea" && textAreaSpecificProps),
},
);
})()}
</> </>
)} )}
</div> </div>

View File

@@ -151,6 +151,14 @@ fieldset {
margin-top: ui-vars.$px01; margin-top: ui-vars.$px01;
} }
div + textarea {
margin-top: ui-vars.$px02;
}
textarea {
border-radius: ui-vars.$px01;
}
* + label { * + label {
margin-top: ui-vars.$px02; margin-top: ui-vars.$px02;
} }