feat: asked-field envelope, standalone form components, branched forms
This commit is contained in:
parent
0d43b0e8fb
commit
f27be044b4
26 changed files with 3651 additions and 104 deletions
|
|
@ -1,8 +1,10 @@
|
|||
"""Derive a web-form schema from a Langflow export.
|
||||
|
||||
Looks for ``CustomInput*`` nodes (``data.type`` or the inner
|
||||
``display_name`` starting with ``CustomInput`` — see
|
||||
``backend/components/kirche/form_inputs.py``) and maps their ``template``
|
||||
Looks for form nodes — ``CustomInput*`` (``data.type`` or the inner
|
||||
``display_name`` starting with ``CustomInput``, see
|
||||
``backend/components/kirche/form_inputs.py``) plus user-built
|
||||
``CustomComponent`` nodes whose display name ends with ``"Form"``
|
||||
(e.g. ``Mitarbeiter Einstellen Form``) — and maps their ``template``
|
||||
(minus ``code``) to ``{json_schema, ui_schema}`` for RJSF:
|
||||
|
||||
* ``name`` → property key (freely renamable in the Langflow code editor;
|
||||
|
|
@ -39,7 +41,7 @@ _VISIBLE_RE = re.compile(r"\[visible_if\s+([^\]]+)\]")
|
|||
|
||||
|
||||
def _form_templates(langflow_json: dict) -> list[dict]:
|
||||
"""Inner node dicts (``data.node``) of all CustomInput* nodes."""
|
||||
"""Inner node dicts (``data.node``) of all form nodes."""
|
||||
if not isinstance(langflow_json, dict):
|
||||
return []
|
||||
data = langflow_json.get("data") or {}
|
||||
|
|
@ -54,6 +56,10 @@ def _form_templates(langflow_json: dict) -> list[dict]:
|
|||
display = str(inner.get("display_name") or "")
|
||||
if node_type.startswith("CustomInput") or display.startswith("CustomInput"):
|
||||
found.append(inner)
|
||||
elif node_type == "CustomComponent" and display.endswith("Form"):
|
||||
# User-built form components (e.g. "Mitarbeiter Einstellen
|
||||
# Form"): same template contract, no kirche base needed.
|
||||
found.append(inner)
|
||||
return found
|
||||
|
||||
|
||||
|
|
@ -328,3 +334,37 @@ def extract_form_schema(langflow_json: dict) -> dict:
|
|||
elif advanced:
|
||||
ui_schema["ui:order"] = normal + advanced + ["*"]
|
||||
return {"json_schema": json_schema, "ui_schema": ui_schema}
|
||||
|
||||
|
||||
def schema_field_names(cached: dict) -> list[str]:
|
||||
"""All asked field names of a cached form schema (root + branches).
|
||||
|
||||
Used for the run envelope's ``fields`` list so the runtime emits
|
||||
defaults only for asked fields. Order: root properties first, then
|
||||
branch discoveries.
|
||||
"""
|
||||
if not isinstance(cached, dict):
|
||||
return []
|
||||
json_schema = cached.get("json_schema") or {}
|
||||
names: list[str] = []
|
||||
|
||||
def _walk(node: object) -> None:
|
||||
if not isinstance(node, dict):
|
||||
return
|
||||
for subschema in (node.get("then"), node.get("else")):
|
||||
if isinstance(subschema, dict):
|
||||
for key in subschema.get("properties") or {}:
|
||||
if key not in names:
|
||||
names.append(key)
|
||||
_walk(subschema)
|
||||
for key in ("allOf", "oneOf", "anyOf"):
|
||||
items = node.get(key) or []
|
||||
if isinstance(items, list):
|
||||
for item in items:
|
||||
_walk(item)
|
||||
|
||||
for key in json_schema.get("properties") or {}:
|
||||
if key not in names:
|
||||
names.append(key)
|
||||
_walk(json_schema)
|
||||
return names
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue