ApiLogicServer 14.4.0__py3-none-any.whl → 14.5.3__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.
- api_logic_server_cli/add_cust/add_cust.py +269 -0
- api_logic_server_cli/api_logic_server.py +18 -238
- api_logic_server_cli/api_logic_server_info.yaml +3 -3
- api_logic_server_cli/cli.py +38 -28
- api_logic_server_cli/create_from_model/__pycache__/api_logic_server_utils.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/dbml.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/ont_build.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/__pycache__/ont_create.cpython-312.pyc +0 -0
- api_logic_server_cli/create_from_model/api_logic_server_utils.py +47 -0
- api_logic_server_cli/create_from_model/dbml.py +113 -58
- api_logic_server_cli/create_from_model/ont_build.py +83 -60
- api_logic_server_cli/create_from_model/ont_create.py +2 -1
- api_logic_server_cli/database/basic_demo.sqlite +0 -0
- api_logic_server_cli/database/basic_demo.txt +1 -0
- api_logic_server_cli/database/basic_demo_wg.sqlite +0 -0
- api_logic_server_cli/manager.py +3 -2
- api_logic_server_cli/prototypes/base/.vscode/launch.json +3 -2
- api_logic_server_cli/prototypes/base/config/config.py +66 -11
- api_logic_server_cli/prototypes/base/config/default.env +7 -1
- api_logic_server_cli/prototypes/base/database/test_data/readme.md +2 -1
- api_logic_server_cli/prototypes/base/integration/kafka/kafka_producer.py +5 -2
- api_logic_server_cli/prototypes/base/integration/n8n/n8n_producer.py +68 -21
- api_logic_server_cli/prototypes/base/integration/n8n/n8n_readme.md +19 -0
- api_logic_server_cli/prototypes/base/test/basic/server_test.py +1 -1
- api_logic_server_cli/prototypes/basic_demo/README.md +29 -52
- api_logic_server_cli/prototypes/basic_demo/customizations/api/.DS_Store +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/mcp_discovery.py +139 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/openapi.py +92 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/config/default.env +13 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/config/server_setup.py +388 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py +131 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/database/system/SAFRSBaseX.py +136 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/.DS_Store +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/.DS_Store +0 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/README_mcp.md +15 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_client_executor.py +350 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_schema.txt +47 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/mcp/mcp_server_discovery.json +9 -0
- api_logic_server_cli/prototypes/{nw_no_cust/integration/mcp → basic_demo/customizations/integration/openai_function}/3_executor_test_agent.py +20 -6
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/README_functon.md +201 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/ai_plugin.json +17 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/nw-swagger_3.json +1731 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/snippets.txt +5 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3 genai_demo_with_get.json +1731 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3.json +1782 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo.json +264 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/integration/openai_function/swagger_3_genai_demo_with_update.json +1782 -0
- api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py +79 -41
- api_logic_server_cli/prototypes/basic_demo/customizations/security/declare_security.py +11 -12
- api_logic_server_cli/prototypes/basic_demo/customizations/ui/admin/admin.yaml +166 -0
- api_logic_server_cli/prototypes/basic_demo/iteration/api/{customize_api.py → api_discovery/order_b2b.py} +17 -23
- api_logic_server_cli/prototypes/basic_demo/iteration/database/db.sqlite +0 -0
- api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderB2B.py +6 -5
- api_logic_server_cli/prototypes/basic_demo/iteration/integration/row_dict_maps/OrderShipping.py +4 -4
- api_logic_server_cli/prototypes/basic_demo/iteration/logic/declare_logic.py +69 -43
- api_logic_server_cli/prototypes/basic_demo/iteration/ui/admin/admin.yaml +125 -50
- api_logic_server_cli/prototypes/manager/README.md +4 -0
- api_logic_server_cli/prototypes/nw/logic/declare_logic.py +2 -2
- api_logic_server_cli/prototypes/nw_no_cust/.obsidian/app.json +1 -0
- api_logic_server_cli/prototypes/nw_no_cust/.obsidian/appearance.json +1 -0
- api_logic_server_cli/prototypes/nw_no_cust/.obsidian/core-plugins.json +31 -0
- api_logic_server_cli/prototypes/nw_no_cust/.obsidian/workspace.json +166 -0
- api_logic_server_cli/prototypes/nw_no_cust/Tutorial.md +45 -26
- api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/openapi.py +130 -0
- api_logic_server_cli/prototypes/nw_no_cust/api/api_discovery/proper_update_def.json +71 -0
- api_logic_server_cli/prototypes/nw_no_cust/config/default.env +13 -0
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/package-lock.json +9725 -1180
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/package.json +3 -6
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/app/shared/app.services.config.ts +1 -1
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/css/app.scss +4 -0
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/en.json +1 -1
- api_logic_server_cli/prototypes/ont_app/ontimize_seed/src/assets/i18n/es.json +14 -12
- api_logic_server_cli/prototypes/ont_app/templates/app_config.jinja +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/date_template.html +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/textarea_template.html +1 -1
- api_logic_server_cli/prototypes/ont_app/templates/timestamp_template.html +1 -1
- api_logic_server_cli/prototypes/sample_ai/logic/declare_logic.py +30 -13
- apilogicserver-14.5.3.dist-info/METADATA +168 -0
- {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/RECORD +84 -61
- {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/WHEEL +1 -1
- api_logic_server_cli/prototypes/basic_demo/apply_customizations.ps1 +0 -17
- api_logic_server_cli/prototypes/basic_demo/apply_customizations.sh +0 -14
- api_logic_server_cli/prototypes/basic_demo/apply_iteration.ps1 +0 -20
- api_logic_server_cli/prototypes/basic_demo/apply_iteration.sh +0 -15
- api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/1_langchain_loader.py +0 -19
- api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/2_gpt_mcp_prompt.txt +0 -19
- api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/README.md +0 -17
- api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/resources/curl.txt +0 -4
- api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/resources/nw_swagger_3.yaml +0 -16660
- api_logic_server_cli/prototypes/nw_no_cust/integration/mcp/run_executor.py +0 -23
- apilogicserver-14.4.0.dist-info/METADATA +0 -76
- {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/entry_points.txt +0 -0
- {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/licenses/LICENSE +0 -0
- {apilogicserver-14.4.0.dist-info → apilogicserver-14.5.3.dist-info}/top_level.txt +0 -0
|
@@ -80,7 +80,7 @@ class OntBuilder(object):
|
|
|
80
80
|
self.currency_symbol_position="left" # "right"
|
|
81
81
|
self.thousand_separator="," # "."
|
|
82
82
|
self.decimal_separator="." # ","
|
|
83
|
-
self.date_format="
|
|
83
|
+
self.date_format="YYYY-DD-MM" #not sure what this means
|
|
84
84
|
self.edit_on_mode = "dblclick" # edit or click
|
|
85
85
|
self.include_translation = False
|
|
86
86
|
self.row_height = "medium"
|
|
@@ -156,14 +156,15 @@ class OntBuilder(object):
|
|
|
156
156
|
with contextlib.suppress(Exception):
|
|
157
157
|
return self.template_env.get_template(template_name)
|
|
158
158
|
use_local=True
|
|
159
|
-
if use_local:
|
|
160
|
-
with contextlib.suppress(Exception):
|
|
161
|
-
return self.local_env.get_template(template_name)
|
|
162
159
|
try:
|
|
160
|
+
if use_local:
|
|
161
|
+
with contextlib.suppress(Exception):
|
|
162
|
+
return self.local_env.get_template(template_name)
|
|
163
|
+
|
|
163
164
|
return self.env.get_template(template_name)
|
|
164
165
|
except Exception as e:
|
|
165
166
|
log.error(f"Error loading template {template_name} - {e}")
|
|
166
|
-
|
|
167
|
+
return None
|
|
167
168
|
|
|
168
169
|
|
|
169
170
|
def build_application(self, show_messages: bool = True):
|
|
@@ -201,7 +202,7 @@ class OntBuilder(object):
|
|
|
201
202
|
for setting_name, each_setting in app_model.settings.style_guide.items():
|
|
202
203
|
#style guide
|
|
203
204
|
self.set_style(setting_name, each_setting)
|
|
204
|
-
self.global_values[setting_name] = each_setting
|
|
205
|
+
self.global_values[setting_name] = each_setting if setting_name is not DotMap() else None
|
|
205
206
|
|
|
206
207
|
'''
|
|
207
208
|
# Breaking change - added to app.config.ts - values may not be on older version
|
|
@@ -210,23 +211,25 @@ class OntBuilder(object):
|
|
|
210
211
|
applicationLocales = ["en","es"]
|
|
211
212
|
startSessionPath = "/auth/login"
|
|
212
213
|
'''
|
|
213
|
-
if getattr(self.global_values,"serviceType",None) is None:
|
|
214
|
+
if getattr(self.global_values,"serviceType",None) is None or getattr(self.global_values,"serviceType",None) == DotMap():
|
|
214
215
|
self.global_values["serviceType"] = "JSONAPI"
|
|
215
|
-
if getattr(self.global_values,"locale",None) is None:
|
|
216
|
-
self.global_values["locale"] =
|
|
217
|
-
if getattr(self.global_values,"applicationLocales",None) is None:
|
|
218
|
-
self.global_values["applicationLocales"] =
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if getattr(self.global_values,"exclude_listpicker",None) is None:
|
|
216
|
+
if getattr(self.global_values,"locale",None) is None or getattr(self.global_values,"locale",None) == DotMap():
|
|
217
|
+
self.global_values["locale"] = "en"
|
|
218
|
+
if getattr(self.global_values,"applicationLocales",None) is None or getattr(self.global_values,"applicationLocales",None) == DotMap():
|
|
219
|
+
self.global_values["applicationLocales"] = ['en','es']
|
|
220
|
+
|
|
221
|
+
if getattr(self.global_values,"exclude_listpicker",None) is None or getattr(self.global_values,"exclude_listpicker",None) == DotMap():
|
|
222
222
|
self.global_values["exclude_listpicker"] = False
|
|
223
|
+
|
|
224
|
+
self.global_values["startSessionPath"] = '/auth/login'
|
|
225
|
+
self.global_values["api_endpoint"] = self.apiEndpoint
|
|
223
226
|
|
|
224
227
|
# If the application yaml has been included = we will use the values from the yaml
|
|
225
228
|
if "application" in app_model:
|
|
226
229
|
for app in app_model.application:
|
|
227
230
|
# yaml may have multiple apps = only work on the one selected app-build --app={app}
|
|
228
|
-
if self.app != app:
|
|
229
|
-
|
|
231
|
+
#if self.app != app:
|
|
232
|
+
# continue
|
|
230
233
|
menu_group = app_model.application[app]["menu_group"]
|
|
231
234
|
for mg in menu_group:
|
|
232
235
|
for mi in menu_group[mg]["menu_item"]:
|
|
@@ -271,7 +274,8 @@ class OntBuilder(object):
|
|
|
271
274
|
# Generates KeyCloak or SQL Auth - if already set - do not overwrite - use rebuild=from
|
|
272
275
|
self.gen_auth_components(app_path, keycloak_args, self.use_keycloak,overwrite=False)
|
|
273
276
|
rv_app_config = self.gen_app_config()
|
|
274
|
-
|
|
277
|
+
apiEndpoint = self.global_values.api_endpoint or self.apiEndpoint
|
|
278
|
+
rv_environment = self.environment_template.render(apiEndpoint=apiEndpoint)
|
|
275
279
|
write_root_file(
|
|
276
280
|
app_path=app_path,
|
|
277
281
|
dir_name="environments",
|
|
@@ -318,20 +322,20 @@ class OntBuilder(object):
|
|
|
318
322
|
)
|
|
319
323
|
|
|
320
324
|
def build_entity_list_from_app(self):
|
|
321
|
-
entity_list = self.app_model.entities
|
|
325
|
+
entity_list = self.app_model.entities
|
|
322
326
|
if "application" in self.app_model:
|
|
323
|
-
entities =
|
|
327
|
+
entities = {}
|
|
324
328
|
for app in self.app_model.application:
|
|
325
329
|
# yaml may have multiple apps = only work on the one selected app-build --app={app}
|
|
326
|
-
if self.app != app:
|
|
327
|
-
|
|
330
|
+
#if self.app != app:
|
|
331
|
+
# continue
|
|
328
332
|
menu_group = self.app_model.application[app]["menu_group"]
|
|
329
333
|
for mg in menu_group:
|
|
330
334
|
for mi in menu_group[mg]["menu_item"]:
|
|
331
335
|
each_entity = self.app_model.entities[mi]
|
|
332
|
-
for each_entity_name, each_entity in entity_list:
|
|
336
|
+
for each_entity_name, each_entity in entity_list.items():
|
|
333
337
|
if each_entity_name == mi:
|
|
334
|
-
entities
|
|
338
|
+
entities[mi] = each_entity
|
|
335
339
|
return entities
|
|
336
340
|
|
|
337
341
|
return entity_list
|
|
@@ -439,7 +443,7 @@ class OntBuilder(object):
|
|
|
439
443
|
def build_entity_favorites(self):
|
|
440
444
|
entity_favorites = []
|
|
441
445
|
entity_list = self.build_entity_list_from_app()
|
|
442
|
-
for each_entity_name, each_entity in entity_list:
|
|
446
|
+
for each_entity_name, each_entity in entity_list.items():
|
|
443
447
|
datatype = 'INTEGER'
|
|
444
448
|
pkey_datatype = 'INTEGER'
|
|
445
449
|
primary_key = each_entity["primary_key"]
|
|
@@ -505,7 +509,7 @@ class OntBuilder(object):
|
|
|
505
509
|
|
|
506
510
|
def get_entity(self, entity_name):
|
|
507
511
|
entity_list = self.build_entity_list_from_app()
|
|
508
|
-
for each_entity_name, each_entity in entity_list:
|
|
512
|
+
for each_entity_name, each_entity in entity_list.items():
|
|
509
513
|
if each_entity_name == entity_name:
|
|
510
514
|
return each_entity
|
|
511
515
|
|
|
@@ -542,9 +546,9 @@ class OntBuilder(object):
|
|
|
542
546
|
return template.render(entity_vars)
|
|
543
547
|
|
|
544
548
|
def load_home_template(self, template_name: str, entity: any, entity_name:str, entity_favorites: any) -> str:
|
|
545
|
-
template = self.get_template(template_name)
|
|
549
|
+
template = self.get_template(template_name) or self.get_template("home_template.html")
|
|
546
550
|
entity_vars = self.get_entity_vars(entity_name=entity_name, entity=entity)
|
|
547
|
-
entity_vars["row_columns"] = self.get_entity_columns(entity)
|
|
551
|
+
entity_vars["row_columns"] = self.get_entity_columns(entity, entity_vars=entity_vars)
|
|
548
552
|
entity_vars["has_tabs"] = False
|
|
549
553
|
if template_name.endswith("_expand.html"):
|
|
550
554
|
self.gen_expanded_template(entity, entity_favorites, entity_vars)
|
|
@@ -572,13 +576,14 @@ class OntBuilder(object):
|
|
|
572
576
|
entity_vars["single_tab_panel"] = self.single_tab_panel.render(tab_vars)
|
|
573
577
|
entity_vars["has_tabs"] = True
|
|
574
578
|
|
|
575
|
-
def get_entity_columns(self, entity):
|
|
579
|
+
def get_entity_columns(self, entity, entity_vars: dict = None) -> list:
|
|
576
580
|
row_cols = []
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
581
|
+
|
|
582
|
+
visible_columns = entity_vars["visibleColumns"].split(";") if entity_vars else entity.columns
|
|
583
|
+
for col in visible_columns:
|
|
584
|
+
if column := find_column(entity, col):
|
|
585
|
+
rv = self.gen_home_columns(entity, entity, column)
|
|
586
|
+
row_cols.append(rv)
|
|
582
587
|
return row_cols
|
|
583
588
|
|
|
584
589
|
def get_entity_vars(self, entity_name:str, entity, page_name: str = "home") -> dict:
|
|
@@ -589,7 +594,7 @@ class OntBuilder(object):
|
|
|
589
594
|
fav_column = find_column(entity,favorite)
|
|
590
595
|
if page := self.get_page(page_name, entity.type):
|
|
591
596
|
cols = page.visible_columns.replace(",",";",100)
|
|
592
|
-
visible_columns = page.visible_columns.replace(",",";",100)
|
|
597
|
+
visible_columns = page.visible_columns.replace(" ","",100).replace(",",";",100)
|
|
593
598
|
else:
|
|
594
599
|
cols = self.get_columns(entity)
|
|
595
600
|
visible_columns = self.get_visible_columns(entity, True)
|
|
@@ -652,8 +657,7 @@ class OntBuilder(object):
|
|
|
652
657
|
|
|
653
658
|
def get_columns(self, entity) -> str:
|
|
654
659
|
cols = []
|
|
655
|
-
for column in entity.columns
|
|
656
|
-
cols.append(column.name)
|
|
660
|
+
cols.extend(column.name for column in entity.columns)
|
|
657
661
|
return ";".join(cols)
|
|
658
662
|
|
|
659
663
|
def get_page(self, page_name, entity_name: str) -> dict:
|
|
@@ -661,8 +665,8 @@ class OntBuilder(object):
|
|
|
661
665
|
if "application" in self.app_model:
|
|
662
666
|
for app in self.app_model.application:
|
|
663
667
|
# yaml may have multiple apps = only work on the one selected app-build --app={app}
|
|
664
|
-
if self.app != app:
|
|
665
|
-
|
|
668
|
+
#if self.app != app:
|
|
669
|
+
# continue
|
|
666
670
|
menu_group = self.app_model.application[app]["menu_group"]
|
|
667
671
|
for mg in menu_group:
|
|
668
672
|
for mi in menu_group[mg]["menu_item"]:
|
|
@@ -679,13 +683,13 @@ class OntBuilder(object):
|
|
|
679
683
|
if "application" in self.app_model:
|
|
680
684
|
for app in self.app_model.application:
|
|
681
685
|
# yaml may have multiple apps = only work on the one selected app-build --app={app}
|
|
682
|
-
if self.app != app:
|
|
683
|
-
|
|
686
|
+
#if self.app != app:
|
|
687
|
+
# continue
|
|
684
688
|
menu_group = self.app_model.application[app]["menu_group"]
|
|
685
689
|
for mg in menu_group:
|
|
686
690
|
entities = []
|
|
687
691
|
for mi in menu_group[mg]["menu_item"]:
|
|
688
|
-
for entity_name, each_entity in entity_list:
|
|
692
|
+
for entity_name, each_entity in entity_list.items():
|
|
689
693
|
if entity_name == mi:
|
|
690
694
|
get_group(menu_groups, mg, each_entity)
|
|
691
695
|
return menu_groups
|
|
@@ -697,6 +701,7 @@ class OntBuilder(object):
|
|
|
697
701
|
# Lookup real Entity Table Name Here
|
|
698
702
|
self.title_translation.append({title: entity_name})
|
|
699
703
|
def gen_home_columns(self, entity, parent_entity, column):
|
|
704
|
+
# sourcery skip: low-code-quality
|
|
700
705
|
col_var = self.get_column_attrs(column)
|
|
701
706
|
if getattr(entity,"tab_groups",None) != None:
|
|
702
707
|
for tg in entity["tab_groups"]:
|
|
@@ -767,9 +772,15 @@ class OntBuilder(object):
|
|
|
767
772
|
fks = get_foreign_keys(entity, favorites)
|
|
768
773
|
row_cols = []
|
|
769
774
|
defaultValues = {}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
775
|
+
if page := self.get_page("new", entity.type):
|
|
776
|
+
visible_columns = page.visible_columns.replace(" ","",100).replace(",",";",100)
|
|
777
|
+
else:
|
|
778
|
+
visible_columns = self.get_visible_columns(entity, True)
|
|
779
|
+
for col in visible_columns.split(";"):
|
|
780
|
+
for column in entity.columns:
|
|
781
|
+
if col == column.name:
|
|
782
|
+
rv = self.get_new_column(column, fks, entity)
|
|
783
|
+
row_cols.append(rv)
|
|
773
784
|
|
|
774
785
|
entity_vars["row_columns"] = row_cols
|
|
775
786
|
return template.render(entity_vars)
|
|
@@ -838,11 +849,17 @@ class OntBuilder(object):
|
|
|
838
849
|
entity_vars = self.get_entity_vars(entity_name, entity)
|
|
839
850
|
fks = get_foreign_keys(entity, favorites)
|
|
840
851
|
row_cols = []
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
852
|
+
if page := self.get_page("detail", entity.type):
|
|
853
|
+
visible_columns = page.visible_columns.replace(" ","",100).replace(",",";",100)
|
|
854
|
+
else:
|
|
855
|
+
visible_columns = self.get_visible_columns(entity, True)
|
|
856
|
+
for col in visible_columns.split(";"):
|
|
857
|
+
for column in entity.columns:
|
|
858
|
+
if col == column.name:
|
|
859
|
+
if column.get("exclude", "false") == "true":
|
|
860
|
+
continue
|
|
861
|
+
rv = self.gen_detail_rows(column, fks, entity)
|
|
862
|
+
row_cols.append(rv)
|
|
846
863
|
|
|
847
864
|
entity_vars["row_columns"] = row_cols
|
|
848
865
|
entity_vars["has_tabs"] = len(fks) > 0
|
|
@@ -898,12 +915,18 @@ class OntBuilder(object):
|
|
|
898
915
|
entity_vars = self.get_entity_vars(entity.type, entity, 'detail')
|
|
899
916
|
template_var |= entity_vars
|
|
900
917
|
row_cols = []
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
918
|
+
if page := self.get_page("home", entity.type):
|
|
919
|
+
visible_columns = page.visible_columns.replace(" ","",100).replace(",",";",100)
|
|
920
|
+
else:
|
|
921
|
+
visible_columns = self.get_visible_columns(entity, True)
|
|
922
|
+
for col in visible_columns.split(";"):
|
|
923
|
+
for column in entity.columns:
|
|
924
|
+
if col == column.name:
|
|
925
|
+
if column.get("exclude", "false") == "true":
|
|
926
|
+
continue
|
|
927
|
+
rv = self.gen_home_columns(entity,parent_entity, column)
|
|
928
|
+
row_cols.append(rv)
|
|
929
|
+
template_var['visibleColumns'] = visible_columns
|
|
907
930
|
template_var["row_columns"] = row_cols
|
|
908
931
|
return tab_template.render(template_var)
|
|
909
932
|
|
|
@@ -930,7 +953,7 @@ class OntBuilder(object):
|
|
|
930
953
|
tab_name, tab_vars = self.get_tab_attrs(entity, parent_entity, fk_tab)
|
|
931
954
|
primaryKey = make_keys(entity["primary_key"])
|
|
932
955
|
entity_list = self.build_entity_list_from_app()
|
|
933
|
-
for each_entity_name, each_entity in entity_list:
|
|
956
|
+
for each_entity_name, each_entity in entity_list.items():
|
|
934
957
|
if each_entity_name == tab_name:
|
|
935
958
|
template = self.load_tab_template(each_entity,entity,tab_vars, primaryKey )
|
|
936
959
|
panels.append(template)
|
|
@@ -1004,7 +1027,7 @@ class OntBuilder(object):
|
|
|
1004
1027
|
|
|
1005
1028
|
sidebarTemplate = self.sidebar_template
|
|
1006
1029
|
# sep = ","
|
|
1007
|
-
for each_entity_name, each_entity in entities:
|
|
1030
|
+
for each_entity_name, each_entity in entities.items():
|
|
1008
1031
|
name = each_entity_name
|
|
1009
1032
|
entity_first_cap = f"{name[:1].upper()}{name[1:]}"
|
|
1010
1033
|
var = {"entity": name, "entity_first_cap": entity_first_cap}
|
|
@@ -1086,7 +1109,7 @@ class OntBuilder(object):
|
|
|
1086
1109
|
if tg.direction == "tomany":
|
|
1087
1110
|
var["tab_name"] = tg.resource
|
|
1088
1111
|
var["tab_key"] = tg.fks[0]
|
|
1089
|
-
if next((e for e in entity_list if e
|
|
1112
|
+
if next((e for e in entity_list if e == tg.resource), None):
|
|
1090
1113
|
additional_routes += f",{self.detail_route_template.render(var)}"
|
|
1091
1114
|
|
|
1092
1115
|
var["additional_routes"] = additional_routes
|
|
@@ -1124,7 +1147,7 @@ class OntBuilder(object):
|
|
|
1124
1147
|
menu_separator = ""
|
|
1125
1148
|
groups = self.get_menu_group()
|
|
1126
1149
|
if len(groups) == 0:
|
|
1127
|
-
for each_entity_name, each_entity in entities:
|
|
1150
|
+
for each_entity_name, each_entity in entities.items():
|
|
1128
1151
|
group = getattr(each_entity, "group") or "data"
|
|
1129
1152
|
get_group(groups, group, each_entity)
|
|
1130
1153
|
|
|
@@ -1310,7 +1333,7 @@ def gen_app_service_config(entities: any) -> str:
|
|
|
1310
1333
|
sep = ""
|
|
1311
1334
|
config = ""
|
|
1312
1335
|
children = ""
|
|
1313
|
-
for each_entity_name, each_entity in entities:
|
|
1336
|
+
for each_entity_name, each_entity in entities.items():
|
|
1314
1337
|
name = each_entity_name
|
|
1315
1338
|
title = each_entity["label"].replace("*","") if hasattr(each_entity, "label") and each_entity.label != DotMap() else name
|
|
1316
1339
|
child = child_template.render(title=title, name=name)
|
|
@@ -316,6 +316,7 @@ class OntCreator(object):
|
|
|
316
316
|
def style_guide(self) -> DotMap:
|
|
317
317
|
style_guide = DotMap()
|
|
318
318
|
# GLOBAL Style settings for all forms
|
|
319
|
+
style_guide.api_endpoint = "http://localhost:5656/api" # "http://localhost:8080"
|
|
319
320
|
style_guide.mode = "tab" # "dialog"
|
|
320
321
|
style_guide.pick_style = "list" #"combo" or"list"
|
|
321
322
|
style_guide.style = "light" # "dark"
|
|
@@ -323,7 +324,7 @@ class OntCreator(object):
|
|
|
323
324
|
style_guide.currency_symbol_position="left" # "right"
|
|
324
325
|
style_guide.thousand_separator="," # "."
|
|
325
326
|
style_guide.decimal_separator="." # ","
|
|
326
|
-
style_guide.date_format="
|
|
327
|
+
style_guide.date_format="YYYY-MM-DD" #not sure what this means
|
|
327
328
|
style_guide.edit_on_mode = "dblclick" # edit #click
|
|
328
329
|
style_guide.min_decimal_digits="2"
|
|
329
330
|
style_guide.max_decimal_digits="4"
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
see tests/test_databases/basic_demo/basic_demo.sql
|
|
Binary file
|
api_logic_server_cli/manager.py
CHANGED
|
@@ -137,7 +137,7 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
|
|
|
137
137
|
else:
|
|
138
138
|
if project.is_docker:
|
|
139
139
|
log.debug(f" tutorial not created for docker\n\n")
|
|
140
|
-
|
|
140
|
+
elif create_manager := False:
|
|
141
141
|
tutorial_project = PR.ProjectRun(command="tutorial",
|
|
142
142
|
project_name='./samples',
|
|
143
143
|
db_url="",
|
|
@@ -145,7 +145,8 @@ def create_manager(clean: bool, open_with: str, api_logic_server_path: Path,
|
|
|
145
145
|
open_with="NO_AUTO_OPEN"
|
|
146
146
|
)
|
|
147
147
|
tutorial_project = tutorial_project.tutorial(msg="Creating:") ##, create='tutorial')
|
|
148
|
-
|
|
148
|
+
else:
|
|
149
|
+
log.debug(f"For Tutorial, use Northwind and basic_demo\n\n")
|
|
149
150
|
samples_project = PR.ProjectRun(command= "create", project_name=f'{docker_volume}samples/nw_sample', db_url='nw+', open_with="NO_AUTO_OPEN")
|
|
150
151
|
log.setLevel(mgr_save_level)
|
|
151
152
|
log.disabled = False # todo why was it reset?
|
|
@@ -95,7 +95,8 @@
|
|
|
95
95
|
"internalConsoleOptions": "openOnSessionStart"
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
|
-
"name": "
|
|
98
|
+
"name": "Test - test/basic/server_test.py",
|
|
99
|
+
// use this for test programs, eg to test the server
|
|
99
100
|
"type": "debugpy",
|
|
100
101
|
"request": "launch",
|
|
101
102
|
"cwd": "${workspaceFolder}",
|
|
@@ -112,7 +113,7 @@
|
|
|
112
113
|
"request": "launch",
|
|
113
114
|
"cwd": "${workspaceFolder}/ui/app",
|
|
114
115
|
"runtimeExecutable": "npm",
|
|
115
|
-
"runtimeArgs": ["install"],
|
|
116
|
+
"runtimeArgs": ["install --force"],
|
|
116
117
|
"console": "integratedTerminal"
|
|
117
118
|
},
|
|
118
119
|
{
|
|
@@ -223,17 +223,19 @@ class Config:
|
|
|
223
223
|
app_logger.info(f'config.py - KAFKA_SERVER: {KAFKA_SERVER}')
|
|
224
224
|
# N8N Webhook Args (for testing)
|
|
225
225
|
# see https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/?utm_source=n8n_app&utm_medium=node_settings_modal-credential_link&utm_campaign=n8n-nodes-base.webhook#path
|
|
226
|
+
# N8N is a workflow automation tool that allows you to connect different applications and automate tasks between them.
|
|
226
227
|
wh_scheme = "http"
|
|
227
228
|
wh_server = "localhost" # or cloud.n8n.io...
|
|
228
229
|
wh_port = 5678
|
|
229
|
-
wh_endpoint = "webhook-test"
|
|
230
|
-
wh_path = "002fa0e8-f7aa-4e04-b4e3-e81aa29c6e69"
|
|
231
|
-
|
|
232
|
-
N8N_PRODUCER = {"authorization": f"Basic {
|
|
230
|
+
wh_endpoint = "webhook-test" # This comes from the WebHook node in n8n
|
|
231
|
+
wh_path = "002fa0e8-f7aa-4e04-b4e3-e81aa29c6e69" # This comes from the WebHook node in n8n
|
|
232
|
+
wh_token = "YWRtaW46cA==" # This is the base64 encoded string of username:password (e.g. admin:password)
|
|
233
|
+
N8N_PRODUCER = {"authorization": f"Basic {wh_token}", "n8n_url": f'"{wh_scheme}://{wh_server}:{wh_port}/{wh_endpoint}/{wh_path}"'}
|
|
233
234
|
# Or enter the n8n_url directly:
|
|
234
|
-
N8N_PRODUCER = {"authorization": f"Basic {
|
|
235
|
+
#N8N_PRODUCER = {"authorization": f"Basic {wh_token}","n8n_url":"http://localhost:5678/webhook-test/002fa0e8-f7aa-4e04-b4e3-e81aa29c6e69"}
|
|
235
236
|
N8N_PRODUCER = None # comment out to enable N8N producer
|
|
236
|
-
#
|
|
237
|
+
# See integration/n8n/n8n_readme.md for more details
|
|
238
|
+
|
|
237
239
|
|
|
238
240
|
OPT_LOCKING = "optional"
|
|
239
241
|
if os.getenv('OPT_LOCKING'): # e.g. export OPT_LOCKING=required
|
|
@@ -298,14 +300,19 @@ class Args():
|
|
|
298
300
|
self.kafka_producer = Config.KAFKA_PRODUCER
|
|
299
301
|
self.kafka_consumer = Config.KAFKA_CONSUMER
|
|
300
302
|
self.kafka_consumer_group = Config.KAFKA_CONSUMER_GROUP
|
|
301
|
-
self.n8n_producer = Config.N8N_PRODUCER
|
|
302
303
|
self.keycloak_base = Config.KEYCLOAK_BASE
|
|
303
304
|
self.keycloak_realm = Config.KEYCLOAK_REALM
|
|
304
305
|
self.keycloak_base_url = Config.KEYCLOAK_BASE_URL
|
|
305
306
|
self.keycloak_client_id = Config.KEYCLOAK_CLIENT_ID
|
|
306
307
|
self.backtic_as_quote = Config.BACKTIC_AS_QUOTE
|
|
307
308
|
self.service_type = Config.ONTIMIZE_SERVICE_TYPE
|
|
308
|
-
|
|
309
|
+
self.wh_scheme = Config.wh_scheme
|
|
310
|
+
self.wh_server = Config.wh_server
|
|
311
|
+
self.wh_port = Config.wh_port
|
|
312
|
+
self.wh_endpoint = Config.wh_endpoint
|
|
313
|
+
self.wh_path = Config.wh_path
|
|
314
|
+
self.wh_token = Config.wh_token
|
|
315
|
+
self.n8n_producer = Config.N8N_PRODUCER
|
|
309
316
|
self.verbose = False
|
|
310
317
|
self.create_and_run = False
|
|
311
318
|
|
|
@@ -576,7 +583,56 @@ class Args():
|
|
|
576
583
|
def n8n_producer(self, a: str):
|
|
577
584
|
self.flask_app.config["N8N_PRODUCER"] = a
|
|
578
585
|
|
|
579
|
-
|
|
586
|
+
# WebHook Args (used by N8N producer - see n8n_producer above)
|
|
587
|
+
@property
|
|
588
|
+
def wh_scheme(self) -> str:
|
|
589
|
+
""" n8n connect string """
|
|
590
|
+
return self.flask_app.config["WH_SCHEME"]
|
|
591
|
+
@wh_scheme.setter
|
|
592
|
+
def wh_scheme(self, a: str):
|
|
593
|
+
self.flask_app.config["WH_SCHEME"] = a
|
|
594
|
+
|
|
595
|
+
@property
|
|
596
|
+
def wh_server(self) -> str:
|
|
597
|
+
""" n8n connect string """
|
|
598
|
+
return self.flask_app.config["WH_SERVER"]
|
|
599
|
+
@wh_server.setter
|
|
600
|
+
def wh_server(self, a: str):
|
|
601
|
+
self.flask_app.config["WH_SERVER"] = a
|
|
602
|
+
|
|
603
|
+
@property
|
|
604
|
+
def wh_port(self) -> str:
|
|
605
|
+
""" n8n connect string """
|
|
606
|
+
return self.flask_app.config["WH_PORT"]
|
|
607
|
+
|
|
608
|
+
@wh_port.setter
|
|
609
|
+
def wh_port(self, a: str):
|
|
610
|
+
self.flask_app.config["WH_PORT"] = a
|
|
611
|
+
|
|
612
|
+
@property
|
|
613
|
+
def wh_endpoint(self) -> str:
|
|
614
|
+
""" n8n connect string """
|
|
615
|
+
return self.flask_app.config["WH_ENDPOINT"]
|
|
616
|
+
@wh_endpoint.setter
|
|
617
|
+
def wh_endpoint(self, a: str):
|
|
618
|
+
self.flask_app.config["WH_ENDPOINT"] = a
|
|
619
|
+
@property
|
|
620
|
+
def wh_path(self) -> str:
|
|
621
|
+
""" n8n connect string """
|
|
622
|
+
return self.flask_app.config["WH_PATH"]
|
|
623
|
+
|
|
624
|
+
@wh_path.setter
|
|
625
|
+
def wh_path(self, a: str):
|
|
626
|
+
self.flask_app.config["WH_PATH"] = a
|
|
627
|
+
@property
|
|
628
|
+
def wh_token(self) -> str:
|
|
629
|
+
""" n8n connect string """
|
|
630
|
+
return self.flask_app.config["WH_TOKEN"]
|
|
631
|
+
@wh_token.setter
|
|
632
|
+
def wh_token(self, a: str):
|
|
633
|
+
self.flask_app.config["WH_TOKEN"] = a
|
|
634
|
+
|
|
635
|
+
|
|
580
636
|
def __str__(self) -> str:
|
|
581
637
|
rtn = f'.. flask_host: {self.flask_host}, port: {self.port}, \n'\
|
|
582
638
|
f'.. swagger_host: {self.swagger_host}, swagger_port: {self.swagger_port}, \n'\
|
|
@@ -695,5 +751,4 @@ class Args():
|
|
|
695
751
|
args.swagger_port = 443
|
|
696
752
|
args.http_scheme = 'https'
|
|
697
753
|
|
|
698
|
-
return
|
|
699
|
-
|
|
754
|
+
return
|
|
@@ -4,4 +4,10 @@ SQLAlCHEMY_ECHO = False
|
|
|
4
4
|
# AGGREGATE_DEFAULTS = True
|
|
5
5
|
# ALL_DEFAULTS = True
|
|
6
6
|
# APILOGICPROJECT_KAFKA_PRODUCER = "{\"bootstrap.servers\": \"localhost:9092\"}"
|
|
7
|
-
# SQLALCHEMY_DATABASE_URI=db.sqlite
|
|
7
|
+
# SQLALCHEMY_DATABASE_URI=db.sqlite
|
|
8
|
+
|
|
9
|
+
SECURITY_ENABLED = false
|
|
10
|
+
|
|
11
|
+
# if using tunnel for mcp, function, or ai_plugin
|
|
12
|
+
# eg, https://tunnel_url.ngrok-free.app
|
|
13
|
+
API_LOGIC_SERVER_TUNNEL = "TUNNEL_URL"
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
This rebuilds test data into `database/test_data/db.sqlite`, for example as used by genai project creation.
|
|
2
|
+
|
|
1
3
|
ChatGPT sometimes fails to build proper test data that matches the derivation rules.
|
|
2
4
|
|
|
3
5
|
You can rebuild the test data, using Logic Bank rules for proper derivations, to rebuild your `database/db.sqlite` (make a copy first to preserve your existing data).
|
|
4
6
|
|
|
5
|
-
|
|
6
7
|
```
|
|
7
8
|
als genai-utils --rebuild-test-data
|
|
8
9
|
```
|
|
@@ -12,7 +12,7 @@ You do not normally need to alter this file
|
|
|
12
12
|
from config.config import Args
|
|
13
13
|
from confluent_kafka import Producer
|
|
14
14
|
import socket
|
|
15
|
-
import logging
|
|
15
|
+
import logging, os
|
|
16
16
|
from logic_bank.exec_row_logic.logic_row import LogicRow
|
|
17
17
|
from integration.system.RowDictMapper import RowDictMapper
|
|
18
18
|
from flask import jsonify
|
|
@@ -82,7 +82,10 @@ def send_kafka_message(kafka_topic: str, kafka_key: str = None, msg: str="", jso
|
|
|
82
82
|
json_root_name (str, optional): json name for json payload root; default is logic_row.name
|
|
83
83
|
"""
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
if '1' == os.getenv("APILOGICPROJECT_NO_FLASK", None):
|
|
86
|
+
logger.debug("kafka_producer#send_kafka_message: not safrs class (e.g. database/test_data/test_data_code.py)")
|
|
87
|
+
return
|
|
88
|
+
|
|
86
89
|
if isinstance(payload, dict):
|
|
87
90
|
row_obj_dict = payload
|
|
88
91
|
elif row_dict_mapper is not None:
|