ai #1
@@ -21,6 +21,10 @@ export function ConfigTemplate(props: ConfigTemplateProps) {
|
|||||||
}
|
}
|
||||||
}, [props.config.template.content, mode]);
|
}, [props.config.template.content, mode]);
|
||||||
|
|
||||||
|
// Validate placeholders (check if @placeholders@ have matching params)
|
||||||
|
const missingPlaceholders = props.config.validatePlaceholders();
|
||||||
|
const hasValidationWarnings = missingPlaceholders.length > 0;
|
||||||
|
|
||||||
function handleEdit() {
|
function handleEdit() {
|
||||||
setOriginalContent(props.config.template.content);
|
setOriginalContent(props.config.template.content);
|
||||||
setDraftContent(props.config.template.content);
|
setDraftContent(props.config.template.content);
|
||||||
@@ -67,11 +71,21 @@ export function ConfigTemplate(props: ConfigTemplateProps) {
|
|||||||
<div className="config-template-editor">
|
<div className="config-template-editor">
|
||||||
{mode === 'view' ? (
|
{mode === 'view' ? (
|
||||||
<>
|
<>
|
||||||
<div className="mb-2">
|
<div className="mb-2 d-flex gap-2 align-items-center">
|
||||||
<button className="btn btn-primary btn-sm" onClick={handleEdit}>
|
<button className="btn btn-primary btn-sm" onClick={handleEdit}>
|
||||||
✎ Edit
|
✎ Edit
|
||||||
</button>
|
</button>
|
||||||
|
{hasValidationWarnings && (
|
||||||
|
<span className="text-warning">
|
||||||
|
⚠ {missingPlaceholders.length} placeholder(s) without params
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{hasValidationWarnings && (
|
||||||
|
<div className="alert alert-warning py-2 px-3 mb-2" style={{ fontSize: '0.875rem' }}>
|
||||||
|
<strong>Missing parameters:</strong> {missingPlaceholders.join(", ")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<Highlight className="language-json">
|
<Highlight className="language-json">
|
||||||
{props.config.template.content || "{}"}
|
{props.config.template.content || "{}"}
|
||||||
</Highlight>
|
</Highlight>
|
||||||
|
|||||||
@@ -109,5 +109,50 @@ export class Config {
|
|||||||
|
|
||||||
return missingParams;
|
return missingParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that all @placeholders@ in template have corresponding params.
|
||||||
|
* Checks DEFAULT env first, then all custom envs.
|
||||||
|
* Returns array of placeholder names that are not defined.
|
||||||
|
*/
|
||||||
|
validatePlaceholders(): string[] {
|
||||||
|
const defaultEnv = this.envs.find(e => e.name === "DEFAULT");
|
||||||
|
const customEnvs = this.envs.filter(e => e.name !== "DEFAULT");
|
||||||
|
|
||||||
|
// Collect all param names from DEFAULT
|
||||||
|
const defaultParamNames = new Set(
|
||||||
|
defaultEnv?.params.map(p => p.name).filter(n => n && n.trim() !== "") || []
|
||||||
|
);
|
||||||
|
|
||||||
|
// Collect all param names from all custom envs
|
||||||
|
const customParamNames = new Set(
|
||||||
|
customEnvs.flatMap(e => e.params.map(p => p.name).filter(n => n && n.trim() !== ""))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extract all @placeholders@ from template
|
||||||
|
const placeholderRegex = /@(\w+)@/g;
|
||||||
|
const placeholdersInTemplate = new Set<string>();
|
||||||
|
let match;
|
||||||
|
while ((match = placeholderRegex.exec(this.template.content)) !== null) {
|
||||||
|
placeholdersInTemplate.add(match[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find placeholders that don't have matching params
|
||||||
|
const missingParams: string[] = [];
|
||||||
|
for (const placeholder of placeholdersInTemplate) {
|
||||||
|
if (placeholder === Config.ENV_NAME_PARAM) continue; // Skip built-in
|
||||||
|
|
||||||
|
// Check if exists in DEFAULT or in ANY custom env
|
||||||
|
const inDefault = defaultParamNames.has(placeholder);
|
||||||
|
const inCustom = customParamNames.has(placeholder);
|
||||||
|
|
||||||
|
// Valid if: in DEFAULT, or in at least one custom env
|
||||||
|
if (!inDefault && !inCustom) {
|
||||||
|
missingParams.push(placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return missingParams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user