Release v0.1.3
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Button } from "@govoplan/core-webui";
|
||||
import { Dialog } from "@govoplan/core-webui";
|
||||
import { DismissibleAlert } from "@govoplan/core-webui";
|
||||
@@ -74,19 +75,49 @@ export function UndefinedPlaceholderDecisionDialog({
|
||||
field,
|
||||
contextLabel = "template",
|
||||
removeLabel = "Remove placeholder",
|
||||
localFields = [],
|
||||
globalFields = [],
|
||||
onCancel,
|
||||
onRemove,
|
||||
onReplace,
|
||||
onAddField,
|
||||
addDisabled = false
|
||||
}: {
|
||||
field: UndefinedPlaceholder | null;
|
||||
contextLabel?: string;
|
||||
removeLabel?: string;
|
||||
localFields?: TemplateFieldOption[];
|
||||
globalFields?: TemplateFieldOption[];
|
||||
onCancel: () => void;
|
||||
onRemove: (field: UndefinedPlaceholder) => void;
|
||||
onReplace?: (field: UndefinedPlaceholder, namespace: TemplateNamespace, name: string) => void;
|
||||
onAddField: (field: UndefinedPlaceholder) => void;
|
||||
addDisabled?: boolean;
|
||||
}) {
|
||||
const replacementOptions = useMemo(
|
||||
() => [
|
||||
...localFields.map((item) => ({ namespace: "local" as const, ...item })),
|
||||
...globalFields.map((item) => ({ namespace: "global" as const, ...item }))
|
||||
],
|
||||
[globalFields, localFields]
|
||||
);
|
||||
const [replacement, setReplacement] = useState("");
|
||||
const firstReplacement = replacementOptions[0];
|
||||
const effectiveReplacement = replacement || (firstReplacement ? `${firstReplacement.namespace}:${firstReplacement.name}` : "");
|
||||
|
||||
useEffect(() => {
|
||||
setReplacement(firstReplacement ? `${firstReplacement.namespace}:${firstReplacement.name}` : "");
|
||||
}, [field?.raw, firstReplacement?.namespace, firstReplacement?.name]);
|
||||
|
||||
function replaceWithSelected() {
|
||||
if (!field || !onReplace || !effectiveReplacement) return;
|
||||
const separator = effectiveReplacement.indexOf(":");
|
||||
if (separator < 0) return;
|
||||
const namespace = effectiveReplacement.slice(0, separator) as TemplateNamespace;
|
||||
const name = effectiveReplacement.slice(separator + 1);
|
||||
onReplace(field, namespace, name);
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={Boolean(field)}
|
||||
@@ -98,6 +129,7 @@ export function UndefinedPlaceholderDecisionDialog({
|
||||
<>
|
||||
<Button onClick={onCancel}>Continue editing</Button>
|
||||
<Button onClick={() => onRemove(field)}>{removeLabel}</Button>
|
||||
{onReplace && replacementOptions.length > 0 && <Button onClick={replaceWithSelected}>Replace</Button>}
|
||||
<Button variant="primary" onClick={() => onAddField(field)} disabled={!field.name || field.reason === "invalid-namespace" || addDisabled}>Add field</Button>
|
||||
</>
|
||||
) : undefined}
|
||||
@@ -111,6 +143,18 @@ export function UndefinedPlaceholderDecisionDialog({
|
||||
{field.reason === "missing-field" && (
|
||||
<p className="muted">You can add <strong>{field.name}</strong> as a campaign field, remove this placeholder, or continue editing.</p>
|
||||
)}
|
||||
{onReplace && replacementOptions.length > 0 && (
|
||||
<label className="template-replacement-field">
|
||||
<span>Replace by existing field</span>
|
||||
<select value={effectiveReplacement} onChange={(event) => setReplacement(event.target.value)}>
|
||||
{replacementOptions.map((option) => (
|
||||
<option key={`${option.namespace}:${option.name}`} value={`${option.namespace}:${option.name}`}>
|
||||
{option.namespace}:{option.label || option.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Dialog>
|
||||
|
||||
Reference in New Issue
Block a user