Flowfile 0.3.3.1__py3-none-any.whl → 0.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Flowfile might be problematic. Click here for more details.
- flowfile/__init__.py +2 -2
- flowfile/__main__.py +0 -2
- flowfile/api.py +94 -46
- flowfile/web/__init__.py +4 -1
- flowfile/web/static/assets/{AirbyteReader-2b1cf2d8.js → AirbyteReader-e08044e5.js} +8 -8
- flowfile/web/static/assets/{CrossJoin-cc3ab73c.js → CrossJoin-dfcf7351.js} +8 -8
- flowfile/web/static/assets/{DatabaseConnectionSettings-307c4652.js → DatabaseConnectionSettings-b2afb1d7.js} +2 -2
- flowfile/web/static/assets/{DatabaseManager-69faa6e1.js → DatabaseManager-824a49b2.js} +2 -2
- flowfile/web/static/assets/{DatabaseReader-e4134cd0.js → DatabaseReader-a48124d8.js} +9 -9
- flowfile/web/static/assets/{DatabaseWriter-d32d75b1.js → DatabaseWriter-b47cbae2.js} +9 -9
- flowfile/web/static/assets/{ExploreData-5eb48389.js → ExploreData-fdfc45a4.js} +5 -5
- flowfile/web/static/assets/{ExternalSource-29489051.js → ExternalSource-861b0e71.js} +6 -6
- flowfile/web/static/assets/{Filter-031332bb.js → Filter-f87bb897.js} +8 -9
- flowfile/web/static/assets/{Formula-3b900540.js → Formula-1e2ed720.js} +9 -10
- flowfile/web/static/assets/{FuzzyMatch-dee31153.js → FuzzyMatch-b6cc4fdd.js} +9 -9
- flowfile/web/static/assets/{GraphSolver-ca74eb47.js → GraphSolver-6a371f4c.js} +5 -5
- flowfile/web/static/assets/{GroupBy-081b6591.js → GroupBy-f7b7f472.js} +6 -6
- flowfile/web/static/assets/{Join-b467376f.js → Join-eec38203.js} +9 -9
- flowfile/web/static/assets/{ManualInput-ffffb80a.js → ManualInput-9aaa46fb.js} +5 -5
- flowfile/web/static/assets/{Output-9a87d4ba.js → Output-3b2ca045.js} +4 -4
- flowfile/web/static/assets/{Pivot-ee3e6093.js → Pivot-a4f5d88f.js} +6 -6
- flowfile/web/static/assets/PolarsCode-49ce444f.js +306 -0
- flowfile/web/static/assets/{Read-67fee3a0.js → Read-07acdc9a.js} +6 -6
- flowfile/web/static/assets/{RecordCount-a2acd02d.js → RecordCount-6a21da56.js} +5 -5
- flowfile/web/static/assets/{RecordId-0c8bcd77.js → RecordId-949bdc17.js} +6 -6
- flowfile/web/static/assets/{Sample-60594a3a.js → Sample-7afca6e1.js} +5 -5
- flowfile/web/static/assets/{SecretManager-bbcec2ac.js → SecretManager-b41c029d.js} +2 -2
- flowfile/web/static/assets/{Select-9540e6ca.js → Select-32b28406.js} +8 -8
- flowfile/web/static/assets/{SettingsSection-48f28104.js → SettingsSection-a0f15a05.js} +1 -1
- flowfile/web/static/assets/{Sort-6dbe3633.js → Sort-fc6ba0e2.js} +6 -6
- flowfile/web/static/assets/{TextToRows-27aab4a8.js → TextToRows-23127596.js} +8 -8
- flowfile/web/static/assets/{UnavailableFields-8143044b.js → UnavailableFields-c42880a3.js} +2 -2
- flowfile/web/static/assets/{Union-52460248.js → Union-39eecc6c.js} +5 -5
- flowfile/web/static/assets/{Unique-f6962644.js → Unique-a0e8fe61.js} +8 -8
- flowfile/web/static/assets/{Unpivot-1ff1e938.js → Unpivot-1e2d43f0.js} +5 -5
- flowfile/web/static/assets/{api-3b345d92.js → api-44ca9e9c.js} +1 -1
- flowfile/web/static/assets/{designer-2394122a.css → designer-186f2e71.css} +64 -9
- flowfile/web/static/assets/{designer-4736134f.js → designer-267d44f1.js} +2835 -105
- flowfile/web/static/assets/{documentation-b9545eba.js → documentation-6c0810a2.js} +1 -1
- flowfile/web/static/assets/{dropDown-d5a4014c.js → dropDown-52790b15.js} +1 -1
- flowfile/web/static/assets/{dropDownGeneric-1f4e32ec.js → dropDownGeneric-60f56a8a.js} +2 -2
- flowfile/web/static/assets/{fullEditor-f4791c23.js → fullEditor-e272b506.js} +2 -3
- flowfile/web/static/assets/{genericNodeSettings-1d456350.js → genericNodeSettings-4bdcf98e.js} +3 -3
- flowfile/web/static/assets/{index-f25c9283.js → index-e235a8bc.js} +12 -12
- flowfile/web/static/assets/{nodeTitle-cad6fd9d.js → nodeTitle-fc3fc4b7.js} +3 -3
- flowfile/web/static/assets/{secretApi-01f07e2c.js → secretApi-cdc2a3fd.js} +1 -1
- flowfile/web/static/assets/{selectDynamic-f46a4e3f.js → selectDynamic-96aa82cd.js} +3 -3
- flowfile/web/static/assets/{vue-codemirror.esm-eb98fc8b.js → vue-codemirror.esm-25e75a08.js} +610 -29
- flowfile/web/static/assets/{vue-content-loader.es-860c0380.js → vue-content-loader.es-6c4b1c24.js} +1 -1
- flowfile/web/static/index.html +1 -1
- {flowfile-0.3.3.1.dist-info → flowfile-0.3.4.dist-info}/METADATA +16 -3
- {flowfile-0.3.3.1.dist-info → flowfile-0.3.4.dist-info}/RECORD +74 -74
- flowfile_core/flowfile/code_generator/__init__.py +0 -0
- flowfile_core/flowfile/code_generator/code_generator.py +723 -0
- flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +1 -1
- flowfile_core/flowfile/flow_data_engine/flow_file_column/main.py +1 -1
- flowfile_core/flowfile/{FlowfileFlow.py → flow_graph.py} +3 -3
- flowfile_core/flowfile/flow_graph_utils.py +1 -1
- flowfile_core/flowfile/handler.py +1 -1
- flowfile_core/flowfile/manage/open_flowfile.py +1 -1
- flowfile_core/flowfile/util/calculate_layout.py +1 -1
- flowfile_core/routes/routes.py +11 -1
- flowfile_core/schemas/input_schema.py +2 -1
- flowfile_frame/adapters.py +1 -1
- flowfile_frame/expr.py +19 -0
- flowfile_frame/flow_frame.py +1 -4
- flowfile_frame/flow_frame.pyi +1 -1
- flowfile_frame/flow_frame_methods.py +1 -1
- flowfile_frame/lazy.py +1 -1
- flowfile_frame/utils.py +1 -1
- flowfile/readme.md +0 -127
- flowfile/web/static/assets/PolarsCode-03921254.js +0 -2865
- flowfile/web/static/assets/PopOver-3bdf8951.js +0 -577
- /flowfile/web/static/assets/{PopOver-bccfde04.css → vue-codemirror-bccfde04.css} +0 -0
- {flowfile-0.3.3.1.dist-info → flowfile-0.3.4.dist-info}/LICENSE +0 -0
- {flowfile-0.3.3.1.dist-info → flowfile-0.3.4.dist-info}/WHEEL +0 -0
- {flowfile-0.3.3.1.dist-info → flowfile-0.3.4.dist-info}/entry_points.txt +0 -0
|
@@ -200,7 +200,7 @@ class FlowDataEngine:
|
|
|
200
200
|
polars_schema = pl.Schema([(flowfile_column.column_name, flowfile_column.get_polars_type().pl_datatype)
|
|
201
201
|
for flowfile_column in flowfile_schema])
|
|
202
202
|
try:
|
|
203
|
-
df = pl.DataFrame(raw_data.data, polars_schema)
|
|
203
|
+
df = pl.DataFrame(raw_data.data, polars_schema, strict=False)
|
|
204
204
|
except TypeError as e:
|
|
205
205
|
logger.warning(f"Could not parse the data with the schema:\n{e}")
|
|
206
206
|
df = pl.DataFrame(raw_data.data)
|
|
@@ -5,7 +5,7 @@ from flowfile_core.flowfile.flow_data_engine.flow_file_column.utils import cast_
|
|
|
5
5
|
from flowfile_core.flowfile.flow_data_engine.flow_file_column.polars_type import PlType
|
|
6
6
|
from polars import datatypes
|
|
7
7
|
import polars as pl
|
|
8
|
-
|
|
8
|
+
# TODO: rename flow_file_column to flowfile_column
|
|
9
9
|
DataTypeGroup = Literal['numeric', 'str', 'date']
|
|
10
10
|
|
|
11
11
|
|
|
@@ -3,7 +3,6 @@ import pickle
|
|
|
3
3
|
import polars as pl
|
|
4
4
|
import fastexcel
|
|
5
5
|
import copy
|
|
6
|
-
|
|
7
6
|
from fastapi.exceptions import HTTPException
|
|
8
7
|
from time import time
|
|
9
8
|
from functools import partial
|
|
@@ -420,7 +419,7 @@ class FlowGraph:
|
|
|
420
419
|
input_columns=[],
|
|
421
420
|
node_type='unique',
|
|
422
421
|
setting_input=unique_settings,
|
|
423
|
-
input_node_ids=[unique_settings.
|
|
422
|
+
input_node_ids=[unique_settings.depending_on_id])
|
|
424
423
|
|
|
425
424
|
def add_graph_solver(self, graph_solver_settings: input_schema.NodeGraphSolver):
|
|
426
425
|
def _func(fl: FlowDataEngine) -> FlowDataEngine:
|
|
@@ -429,7 +428,8 @@ class FlowGraph:
|
|
|
429
428
|
self.add_node_step(node_id=graph_solver_settings.node_id,
|
|
430
429
|
function=_func,
|
|
431
430
|
node_type='graph_solver',
|
|
432
|
-
setting_input=graph_solver_settings
|
|
431
|
+
setting_input=graph_solver_settings,
|
|
432
|
+
input_node_ids=[graph_solver_settings.depending_on_id])
|
|
433
433
|
|
|
434
434
|
def add_formula(self, function_settings: input_schema.NodeFormula):
|
|
435
435
|
error = ""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Dict, Tuple, Optional, List, Set, Callable
|
|
2
2
|
from copy import deepcopy
|
|
3
3
|
from flowfile_core.schemas import input_schema, schemas
|
|
4
|
-
from flowfile_core.flowfile.
|
|
4
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph, add_connection
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def combine_flow_graphs_with_mapping(
|
|
@@ -10,7 +10,7 @@ import os
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
from flowfile_core.flowfile.manage.open_flowfile import open_flow
|
|
13
|
-
from flowfile_core.flowfile.
|
|
13
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
14
14
|
from flowfile_core.schemas.schemas import FlowSettings
|
|
15
15
|
from flowfile_core.configs import logger
|
|
16
16
|
|
|
@@ -2,7 +2,7 @@ from flowfile_core.schemas import schemas, input_schema
|
|
|
2
2
|
from typing import List, Tuple
|
|
3
3
|
from flowfile_core.flowfile.manage.compatibility_enhancements import ensure_compatibility
|
|
4
4
|
import pickle
|
|
5
|
-
from flowfile_core.flowfile.
|
|
5
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
|
|
@@ -5,7 +5,7 @@ from typing import List, Dict, Set, Tuple, TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
if TYPE_CHECKING:
|
|
7
7
|
# Make sure this import path is correct for your project structure
|
|
8
|
-
from flowfile_core.flowfile.
|
|
8
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def calculate_layered_layout(
|
flowfile_core/routes/routes.py
CHANGED
|
@@ -22,7 +22,8 @@ from flowfile_core.fileExplorer.funcs import (
|
|
|
22
22
|
FileInfo,
|
|
23
23
|
get_files_from_directory
|
|
24
24
|
)
|
|
25
|
-
from flowfile_core.flowfile.
|
|
25
|
+
from flowfile_core.flowfile.flow_graph import add_connection, delete_connection
|
|
26
|
+
from flowfile_core.flowfile.code_generator.code_generator import export_flow_to_polars
|
|
26
27
|
from flowfile_core.flowfile.analytics.analytics_processor import AnalyticsProcessor
|
|
27
28
|
from flowfile_core.flowfile.extensions import get_instant_func_results
|
|
28
29
|
# Flow handling
|
|
@@ -362,6 +363,15 @@ def get_flow(flow_id: int):
|
|
|
362
363
|
return result
|
|
363
364
|
|
|
364
365
|
|
|
366
|
+
@router.get("/editor/code_to_polars", tags=[], response_model=str)
|
|
367
|
+
def get_generated_code(flow_id: int) -> str:
|
|
368
|
+
flow_id = int(flow_id)
|
|
369
|
+
flow = flow_file_handler.get_flow(flow_id)
|
|
370
|
+
if flow is None:
|
|
371
|
+
raise HTTPException(404, 'could not find the flow')
|
|
372
|
+
return export_flow_to_polars(flow)
|
|
373
|
+
|
|
374
|
+
|
|
365
375
|
@router.post('/editor/create_flow/', tags=['editor'])
|
|
366
376
|
def create_flow(flow_path: str):
|
|
367
377
|
flow_path = Path(flow_path)
|
|
@@ -154,7 +154,7 @@ class OutputSettings(BaseModel):
|
|
|
154
154
|
|
|
155
155
|
def set_absolute_filepath(self):
|
|
156
156
|
base_path = Path(self.directory)
|
|
157
|
-
|
|
157
|
+
|
|
158
158
|
if not base_path.is_absolute():
|
|
159
159
|
base_path = Path.cwd() / base_path
|
|
160
160
|
|
|
@@ -179,6 +179,7 @@ class NodeBase(BaseModel):
|
|
|
179
179
|
is_setup: Optional[bool] = True
|
|
180
180
|
description: Optional[str] = ''
|
|
181
181
|
user_id: Optional[int] = None
|
|
182
|
+
is_flow_output: Optional[bool] = False
|
|
182
183
|
|
|
183
184
|
@classmethod
|
|
184
185
|
def overridden_hash(cls):
|
flowfile_frame/adapters.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""Adapters to connect FlowFrame with the flowfile-core library."""
|
|
3
3
|
|
|
4
4
|
# Import from your existing project
|
|
5
|
-
from flowfile_core.flowfile.
|
|
5
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph, add_connection
|
|
6
6
|
from flowfile_core.flowfile.flow_data_engine.flow_data_engine import FlowDataEngine
|
|
7
7
|
from flowfile_core.schemas import input_schema, schemas, transform_schema
|
|
8
8
|
|
flowfile_frame/expr.py
CHANGED
|
@@ -126,6 +126,25 @@ class StringMethods:
|
|
|
126
126
|
res_expr = self.expr.to_titlecase() if self.expr is not None else None
|
|
127
127
|
return self._create_next_expr(method_name="to_titlecase", result_expr=res_expr, is_complex=True)
|
|
128
128
|
|
|
129
|
+
def to_date(self, format: str, *, strict: bool = True, exact: bool = True, cache: bool = True):
|
|
130
|
+
res_expr = self.expr.to_date(format, strict=strict, exact=exact, cache=cache) if self.expr is not None else None
|
|
131
|
+
return self._create_next_expr(method_name="to_date", result_expr=res_expr, is_complex=True,
|
|
132
|
+
format=format, strict=strict, exact=exact, cache=cache)
|
|
133
|
+
|
|
134
|
+
def to_datetime(self, format: str | None = None,
|
|
135
|
+
*,
|
|
136
|
+
time_unit: Literal["ns", "us", "ms"] | None = None,
|
|
137
|
+
time_zone: str | None = None,
|
|
138
|
+
strict: bool = True,
|
|
139
|
+
exact: bool = True,
|
|
140
|
+
cache: bool = True,
|
|
141
|
+
ambiguous: Literal["earliest", "latest", "raise", "null"] | Expr = "raise",):
|
|
142
|
+
res_expr = self.expr.to_datetime(format, time_unit=time_unit, time_zone=time_zone, strict=strict,
|
|
143
|
+
exact=exact, cache=cache, ambiguous=ambiguous)
|
|
144
|
+
return self._create_next_expr(method_name="to_datetime", result_expr=res_expr, is_complex=True,
|
|
145
|
+
format=format, time_unit=time_unit, time_zone=time_zone, strict=strict,
|
|
146
|
+
exact=exact, cache=cache, ambiguous=ambiguous)
|
|
147
|
+
|
|
129
148
|
def __getattr__(self, name):
|
|
130
149
|
if self.expr is None or not hasattr(self.expr, name):
|
|
131
150
|
if self.expr is None:
|
flowfile_frame/flow_frame.py
CHANGED
|
@@ -10,7 +10,7 @@ from flowfile_frame.lazy_methods import add_lazyframe_methods
|
|
|
10
10
|
|
|
11
11
|
from polars._typing import (FrameInitTypes, SchemaDefinition, SchemaDict, Orientation)
|
|
12
12
|
from collections.abc import Iterator
|
|
13
|
-
from flowfile_core.flowfile.
|
|
13
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph, add_connection
|
|
14
14
|
from flowfile_core.flowfile.flow_graph_utils import combine_flow_graphs_with_mapping
|
|
15
15
|
from flowfile_core.flowfile.flow_data_engine.flow_data_engine import FlowDataEngine
|
|
16
16
|
from flowfile_core.flowfile.flow_node.flow_node import FlowNode
|
|
@@ -1027,7 +1027,6 @@ class FlowFrame:
|
|
|
1027
1027
|
) -> "FlowFrame":
|
|
1028
1028
|
|
|
1029
1029
|
new_node_id = generate_node_id()
|
|
1030
|
-
|
|
1031
1030
|
is_path_input = isinstance(file, (str, os.PathLike))
|
|
1032
1031
|
if isinstance(file, os.PathLike):
|
|
1033
1032
|
file_str = str(file)
|
|
@@ -1041,7 +1040,6 @@ class FlowFrame:
|
|
|
1041
1040
|
file_name = file_str.split(os.sep)[-1] if is_path_input else "output.csv"
|
|
1042
1041
|
|
|
1043
1042
|
use_polars_code = bool(kwargs) or not is_path_input
|
|
1044
|
-
|
|
1045
1043
|
output_settings = input_schema.OutputSettings(
|
|
1046
1044
|
file_type='csv',
|
|
1047
1045
|
name=file_name,
|
|
@@ -1051,7 +1049,6 @@ class FlowFrame:
|
|
|
1051
1049
|
output_excel_table=input_schema.OutputExcelTable(),
|
|
1052
1050
|
output_parquet_table=input_schema.OutputParquetTable()
|
|
1053
1051
|
)
|
|
1054
|
-
|
|
1055
1052
|
if is_path_input:
|
|
1056
1053
|
try:
|
|
1057
1054
|
output_settings.set_absolute_filepath()
|
flowfile_frame/flow_frame.pyi
CHANGED
|
@@ -19,7 +19,7 @@ from polars.type_aliases import (Schema, IntoExpr, ClosedInterval, Label, StartB
|
|
|
19
19
|
|
|
20
20
|
# Local application/library specific imports
|
|
21
21
|
import flowfile_frame
|
|
22
|
-
from flowfile_core.flowfile.
|
|
22
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
23
23
|
from flowfile_core.flowfile.flow_node.flow_node import FlowNode
|
|
24
24
|
from flowfile_frame import group_frame
|
|
25
25
|
from flowfile_frame.expr import Expr
|
|
@@ -8,7 +8,7 @@ import polars as pl
|
|
|
8
8
|
from polars._typing import (SchemaDict, IO,PolarsDataType,
|
|
9
9
|
Sequence, CsvEncoding)
|
|
10
10
|
|
|
11
|
-
from flowfile_core.flowfile.
|
|
11
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
12
12
|
from flowfile_core.flowfile.flow_data_engine.flow_data_engine import FlowDataEngine
|
|
13
13
|
from flowfile_core.schemas import input_schema, transform_schema
|
|
14
14
|
|
flowfile_frame/lazy.py
CHANGED
|
@@ -2,7 +2,7 @@ import inspect
|
|
|
2
2
|
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union
|
|
3
3
|
import polars as pl
|
|
4
4
|
from flowfile_frame.flow_frame import FlowFrame, can_be_expr, generate_node_id
|
|
5
|
-
from flowfile_core.flowfile.
|
|
5
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
6
6
|
from flowfile_frame.expr import Expr
|
|
7
7
|
from flowfile_frame.utils import _get_function_source
|
|
8
8
|
from typing import cast
|
flowfile_frame/utils.py
CHANGED
|
@@ -7,7 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
import polars as pl
|
|
8
8
|
from typing import Iterable, Any, List, Optional
|
|
9
9
|
|
|
10
|
-
from flowfile_core.flowfile.
|
|
10
|
+
from flowfile_core.flowfile.flow_graph import FlowGraph
|
|
11
11
|
from flowfile_core.schemas import schemas
|
|
12
12
|
from tempfile import TemporaryDirectory
|
|
13
13
|
import inspect
|
flowfile/readme.md
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# Flowfile Web UI Documentation
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Flowfile now supports a web-based user interface that can be launched directly from the pip-installed package. This enhancement allows users to quickly get started with the visual ETL tool without needing to install the desktop application, set up Docker, or manually configure the services.
|
|
6
|
-
|
|
7
|
-
## Key Features
|
|
8
|
-
|
|
9
|
-
- **Integrated Web UI**: Launch the Flowfile interface directly in your browser
|
|
10
|
-
- **Unified Service**: Combined API that serves both the web UI and processes worker operations
|
|
11
|
-
- **Easy Installation**: Simple pip installation and startup process
|
|
12
|
-
- **Visual ETL**: Access to all the visual ETL capabilities through a web interface
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
15
|
-
|
|
16
|
-
Install Flowfile from PyPI using pip:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
pip install Flowfile
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Starting the Web UI
|
|
23
|
-
|
|
24
|
-
You can start the Flowfile web UI using either the Python module or the command-line interface:
|
|
25
|
-
|
|
26
|
-
### Using the Command-Line Interface
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# Start the web UI with default settings
|
|
30
|
-
flowfile run ui
|
|
31
|
-
|
|
32
|
-
# Start without automatically opening a browser window
|
|
33
|
-
flowfile run ui --no-browser
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Using Python
|
|
37
|
-
|
|
38
|
-
```python
|
|
39
|
-
import flowfile
|
|
40
|
-
|
|
41
|
-
# Start the web UI with default settings
|
|
42
|
-
flowfile.start_web_ui()
|
|
43
|
-
|
|
44
|
-
# Customize host, port, and browser launch
|
|
45
|
-
flowfile.start_web_ui(host="0.0.0.0", port=63578, open_browser=False)
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Architecture Overview
|
|
49
|
-
|
|
50
|
-
The web UI functionality combines multiple components:
|
|
51
|
-
|
|
52
|
-
1. **Core Service**: The main ETL engine (flowfile_core) that processes data transformations
|
|
53
|
-
2. **Worker Service**: Handles computation and caching of data operations (flowfile_worker)
|
|
54
|
-
3. **Web UI**: A Vue.js frontend that provides the visual interface
|
|
55
|
-
|
|
56
|
-
When you start the web UI, all these services are launched together in a unified mode, making it simple to get started without configuration.
|
|
57
|
-
|
|
58
|
-
## Using the Web UI with FlowFrame API
|
|
59
|
-
|
|
60
|
-
You can create data pipelines programmatically with the FlowFrame API and then visualize them in the web UI:
|
|
61
|
-
|
|
62
|
-
```python
|
|
63
|
-
import flowfile as ff
|
|
64
|
-
from flowfile import open_graph_in_editor
|
|
65
|
-
|
|
66
|
-
# Create a data pipeline
|
|
67
|
-
df = ff.from_dict({
|
|
68
|
-
"id": [1, 2, 3, 4, 5],
|
|
69
|
-
"category": ["A", "B", "A", "C", "B"],
|
|
70
|
-
"value": [100, 200, 150, 300, 250]
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
# Process the data
|
|
74
|
-
result = df.filter(ff.col("value") > 150).with_columns([
|
|
75
|
-
(ff.col("value") * 2).alias("double_value")
|
|
76
|
-
])
|
|
77
|
-
|
|
78
|
-
# Open the graph in the web UI (starts the server if it's not running)
|
|
79
|
-
open_graph_in_editor(result.flow_graph)
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
The `open_graph_in_editor` function automatically:
|
|
83
|
-
1. Saves the flow graph to a temporary file
|
|
84
|
-
2. Starts the Flowfile server if it's not already running
|
|
85
|
-
3. Imports the flow into the editor
|
|
86
|
-
4. Opens a browser tab with the imported flow
|
|
87
|
-
|
|
88
|
-
## Advanced Server Configuration
|
|
89
|
-
|
|
90
|
-
For advanced users who need to customize the server behavior:
|
|
91
|
-
|
|
92
|
-
### Environment Variables
|
|
93
|
-
|
|
94
|
-
- `FLOWFILE_HOST`: Host to bind the server to (default: "127.0.0.1")
|
|
95
|
-
- `FLOWFILE_PORT`: Port to bind the server to (default: 63578)
|
|
96
|
-
- `FLOWFILE_MODE`: Set to "electron" to enable browser auto-opening behavior
|
|
97
|
-
- `WORKER_URL`: URL for the worker service
|
|
98
|
-
- `SINGLE_FILE_MODE`: Set to "1" to run in unified mode with worker functionality
|
|
99
|
-
- `FLOWFILE_MODULE_NAME`: Module name to run (default: "flowfile")
|
|
100
|
-
|
|
101
|
-
### Running Individual Components
|
|
102
|
-
|
|
103
|
-
For development or specialized deployments, you can run the components separately:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
# Run only the core service
|
|
107
|
-
flowfile run core --host 0.0.0.0 --port 63578
|
|
108
|
-
|
|
109
|
-
# Run only the worker service
|
|
110
|
-
flowfile run worker --host 0.0.0.0 --port 63579
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Troubleshooting
|
|
114
|
-
|
|
115
|
-
- If the web UI doesn't open automatically, manually navigate to http://localhost:63578/ui
|
|
116
|
-
- If you encounter connection issues, check if the port is already in use
|
|
117
|
-
- Look for server logs in the terminal where you started the service for error messages
|
|
118
|
-
- For issues with the API, navigate to http://localhost:63578/docs to verify the API is running
|
|
119
|
-
|
|
120
|
-
## Next Steps
|
|
121
|
-
|
|
122
|
-
Once you're familiar with the web UI, you might want to explore:
|
|
123
|
-
|
|
124
|
-
1. The desktop application for a more native experience
|
|
125
|
-
2. Docker deployment for production environments
|
|
126
|
-
3. Advanced ETL operations using the FlowFrame API
|
|
127
|
-
4. Custom node development for specialized transformations
|