From 867c4f9ff949a9cf20e44dfd0673c0ab668b284c Mon Sep 17 00:00:00 2001 From: Fabien Arcellier Date: Sun, 22 Sep 2024 08:34:56 +0200 Subject: [PATCH] feat: store writer framework IDE into project directory instead of ui.json * feat: add support for workflow --- src/writer/core_ui.py | 12 ++--- src/writer/ss_types.py | 4 ++ src/writer/wf_project.py | 89 +++++++++++++++++++++-------------- tests/backend/test_core_ui.py | 8 ++-- 4 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/writer/core_ui.py b/src/writer/core_ui.py index 296af6a86..62d235423 100644 --- a/src/writer/core_ui.py +++ b/src/writer/core_ui.py @@ -386,11 +386,11 @@ def ingest_bmc_component_tree(component_tree: ComponentTree, components: Dict[st component_tree.ingest(components, tree=Branch.bmc) -def lookup_page_for_component(components: Dict[str, ComponentDefinition], component_id: str) -> Optional[str]: +def lookup_parent_type_for_component(components: Dict[str, ComponentDefinition], component_id: str, parent_type: str) -> Optional[str]: """ - Retrieves the page of a component + Retrieves the first parent of type {parent_type} for a component. - >>> lookup_page_for_component(components, "6a490318-239e-4fe9-a56b-f0f33d628c87") + >>> lookup_parent_type_for_component(components, "6a490318-239e-4fe9-a56b-f0f33d628c87", "page") """ component: Optional[ComponentDefinition] = components.get(component_id, None) if component is None: @@ -400,14 +400,14 @@ def lookup_page_for_component(components: Dict[str, ComponentDefinition], compon if parent_id is None: return None - if component['type'] == "page": + if component['type'] == parent_type: return component['id'] if parent_id in components: - if components[parent_id]['type'] == "page": + if components[parent_id]['type'] == parent_type: return parent_id else: - return lookup_page_for_component(components, parent_id) + return lookup_parent_type_for_component(components, parent_id, parent_type) return None diff --git a/src/writer/ss_types.py b/src/writer/ss_types.py index 732dcb6b2..6df5835f2 100644 --- a/src/writer/ss_types.py +++ b/src/writer/ss_types.py @@ -205,3 +205,7 @@ class ComponentDefinition(TypedDict): handlers: Optional[Dict[str, str]] visible: Optional[Union[bool, str]] binding: Optional[Dict] + outs: Optional[Dict[str, str]] + x: Optional[int] + y: Optional[int] + diff --git a/src/writer/wf_project.py b/src/writer/wf_project.py index f5b6eaa18..77fb774d7 100644 --- a/src/writer/wf_project.py +++ b/src/writer/wf_project.py @@ -21,10 +21,15 @@ def write_files(app_path: str, metadata: MetadataDefinition, components: dict[st * the metadata.json file is written in json format * a file for the root component written in jsonline format - * one file per page is created in the form `components-{id}.json` in jsonline format + * a file for the workflows_root component written in jsonline format + * one file per page is created in the form `components-page-{id}.json` in jsonline format + * one file per workflow is created in the form `components-workflows_workflow-{id}.json` in jsonline format >>> wf_project.write_files('app/hello', metadata={"writer_version": "0.1" }, components=...) """ + roots = ['root', 'workflows_root'] + components_parts_root = ['page', 'workflows_workflow'] + wf_directory = os.path.join(app_path, ".wf") if not os.path.exists(wf_directory): os.makedirs(wf_directory) @@ -32,36 +37,42 @@ def write_files(app_path: str, metadata: MetadataDefinition, components: dict[st with io.open(os.path.join(wf_directory, "metadata.json"), "w") as f: json.dump(metadata, f, indent=4) - root_component = components["root"] - with io.open(os.path.join(wf_directory, "components-root.jsonl"), "w") as f: - f.write(json.dumps(root_component)) - - list_pages = [] - for c in components.values(): - if c["type"] == "page": - list_pages.append(c["id"]) + for root in roots: + root_component = components.get(root, None) + if root_component: + with io.open(os.path.join(wf_directory, f"components-{root}.jsonl"), "w") as f: + f.write(json.dumps(root_component)) - for position, page_id in enumerate(list_pages): - page_components = [] - page_components_ids = {page_id} + list_parts_root = [] + for part_root_type in components_parts_root: for c in components.values(): - if core_ui.lookup_page_for_component(components, c['id']) in page_components_ids: - page_components.append(c) - page_components_ids.add(c["id"]) + if c["type"] == part_root_type: + list_parts_root.append(c["id"]) + + for position, component_id in enumerate(list_parts_root): + part_components = [] + part_components_ids = {component_id} + for c in components.values(): + if core_ui.lookup_parent_type_for_component(components, c['id'], parent_type=part_root_type) in part_components_ids: + part_components.append(c) + part_components_ids.add(c["id"]) + + with io.open(os.path.join(wf_directory, f"components-{part_root_type}-{position}-{component_id}.jsonl"), "w") as f: + for p in part_components: + f.write(json.dumps(p) + "\n") - with io.open(os.path.join(wf_directory, f"components-page-{position}-{page_id}.jsonl"), "w") as f: - for p in page_components: - f.write(json.dumps(p) + "\n") def read_files(app_path: str) -> Tuple[MetadataDefinition, dict[str, ComponentDefinition]]: """ Reads project files in the `.wf` folder. - The components are read in page order. + The components are read in page and workflows_workflow order. >>> metadata, components = wf_project.read_files('app/hello') """ components: dict[str, ComponentDefinition] = {} + roots = ['root', 'workflows_root'] + component_part_file_type = ['page', 'workflows_workflow'] meta_data_path = os.path.join(app_path, ".wf", "metadata.json") try: @@ -70,26 +81,32 @@ def read_files(app_path: str) -> Tuple[MetadataDefinition, dict[str, ComponentDe except Exception as e: raise ValueError(f"Error reading metadata file {meta_data_path} : {e}") - root_component_path = os.path.join(app_path, ".wf", "components-root.jsonl") - try: - with io.open(root_component_path, "r") as filep: - root_component: ComponentDefinition = json.loads(filep.read()) - components.update({root_component["id"]: root_component}) - except Exception as e: - raise ValueError(f"Error reading root component file {root_component_path} : {e}") - files = os.listdir(os.path.join(app_path, ".wf")) - page_files = [file for file in files if file.startswith("components-page-")] - sorted_page_files = sorted(page_files, key=lambda x: int(x.split("-")[2])) - for page_file in sorted_page_files: - page_file_path = os.path.join(app_path, ".wf", page_file) + # read ui files + for root in roots: + root_component_path = os.path.join(app_path, ".wf", f"components-{root}.jsonl") + if not os.path.exists(root_component_path): + continue + try: - with io.open(page_file_path, "r") as filep: - for line in filep: - component: ComponentDefinition = json.loads(line) - components.update({component["id"]: component}) + with io.open(root_component_path, "r") as filep: + root_component: ComponentDefinition = json.loads(filep.read()) + components.update({root_component["id"]: root_component}) except Exception as e: - raise ValueError(f"Error reading page component file {page_file_path} : {e}") + raise ValueError(f"Error reading root component file {root_component_path} : {e}") + + files = os.listdir(os.path.join(app_path, ".wf")) + for file in files: + for part_file_type in component_part_file_type: + if file.startswith(f"components-{part_file_type}-"): + page_file_path = os.path.join(app_path, ".wf", file) + try: + with io.open(page_file_path, "r") as filep: + for line in filep: + component: ComponentDefinition = json.loads(line) + components.update({component["id"]: component}) + except Exception as e: + raise ValueError(f"Error reading page component file {page_file_path} : {e}") return metadata, components diff --git a/tests/backend/test_core_ui.py b/tests/backend/test_core_ui.py index 72dc59bce..81ff2419a 100644 --- a/tests/backend/test_core_ui.py +++ b/tests/backend/test_core_ui.py @@ -6,25 +6,25 @@ from backend.fixtures import load_fixture_content -def test_lookup_page_for_component_should_retrieve_the_page_for_a_specific_component_id(): +def test_lookup_parent_type_for_component_should_retrieve_the_page_for_a_specific_component_id(): # Given components_list: List[ComponentDefinition] = load_fixture_content('components/components-page-1.jsonl') components = {c['id']: c for c in components_list} # When - page_id = core_ui.lookup_page_for_component(components, '42ab5c3d-21fc-4e88-befd-33e52fd15e8b') + page_id = core_ui.lookup_parent_type_for_component(components, '42ab5c3d-21fc-4e88-befd-33e52fd15e8b', parent_type="page") # Then assert page_id == '23bc1387-26ed-4ff2-8565-b027c2960c3c' -def test_lookup_page_for_component_should_return_nothing_when_the_component_match_nothing(): +def test_lookup_parent_type_for_component_should_return_nothing_when_the_component_match_nothing(): # Given components_list: List[ComponentDefinition] = load_fixture_content('components/components-page-1.jsonl') components = {c['id']: c for c in components_list} # When - page_id = core_ui.lookup_page_for_component(components, 'xxxxxxxxx-xxxxx-4e88-befd-33e52fd15e8b') + page_id = core_ui.lookup_parent_type_for_component(components, 'xxxxxxxxx-xxxxx-4e88-befd-33e52fd15e8b', parent_type="page") # Then assert page_id is None