_GuiCoreLib.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. # Copyright 2021-2024 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. import typing as t
  12. from datetime import datetime
  13. from taipy.core import Cycle, DataNode, Job, Scenario, Sequence, Task
  14. from taipy.gui import Gui
  15. from taipy.gui.extension import Element, ElementLibrary, ElementProperty, PropertyType
  16. from ..version import _get_version
  17. from ._adapters import (
  18. _GuiCoreDatanodeAdapter,
  19. _GuiCoreDatanodeFilter,
  20. _GuiCoreDatanodeSort,
  21. _GuiCoreDoNotUpdate,
  22. _GuiCoreScenarioAdapter,
  23. _GuiCoreScenarioDagAdapter,
  24. _GuiCoreScenarioFilter,
  25. _GuiCoreScenarioSort,
  26. )
  27. from ._context import _GuiCoreContext
  28. Scenario.__bases__ += (_GuiCoreDoNotUpdate,)
  29. Sequence.__bases__ += (_GuiCoreDoNotUpdate,)
  30. DataNode.__bases__ += (_GuiCoreDoNotUpdate,)
  31. Cycle.__bases__ += (_GuiCoreDoNotUpdate,)
  32. Job.__bases__ += (_GuiCoreDoNotUpdate,)
  33. Task.__bases__ += (_GuiCoreDoNotUpdate,)
  34. class _GuiCore(ElementLibrary):
  35. __LIB_NAME = "taipy_gui_core"
  36. __CTX_VAR_NAME = f"__{__LIB_NAME}_Ctx"
  37. __SCENARIO_ADAPTER = "tgc_scenario"
  38. __DATANODE_ADAPTER = "tgc_datanode"
  39. __JOB_ADAPTER = "tgc_job"
  40. __SCENARIO_SELECTOR_ERROR_VAR = "__tpgc_sc_error"
  41. __SCENARIO_SELECTOR_ID_VAR = "__tpgc_sc_id"
  42. __SCENARIO_SELECTOR_FILTER_VAR = "__tpgc_sc_filter"
  43. __SCENARIO_SELECTOR_SORT_VAR = "__tpgc_sc_sort"
  44. __SCENARIO_VIZ_ERROR_VAR = "__tpgc_sv_error"
  45. __JOB_SELECTOR_ERROR_VAR = "__tpgc_js_error"
  46. __DATANODE_VIZ_ERROR_VAR = "__tpgc_dv_error"
  47. __DATANODE_VIZ_OWNER_ID_VAR = "__tpgc_dv_owner_id"
  48. __DATANODE_VIZ_HISTORY_ID_VAR = "__tpgc_dv_history_id"
  49. __DATANODE_VIZ_PROPERTIES_ID_VAR = "__tpgc_dv_properties_id"
  50. __DATANODE_VIZ_DATA_ID_VAR = "__tpgc_dv_data_id"
  51. __DATANODE_VIZ_DATA_CHART_ID_VAR = "__tpgc_dv_data_chart_id"
  52. __DATANODE_VIZ_DATA_NODE_PROP = "data_node"
  53. __DATANODE_SEL_SCENARIO_PROP = "scenario"
  54. __SEL_SCENARIOS_PROP = "scenarios"
  55. __SEL_DATANODES_PROP = "datanodes"
  56. __DATANODE_SELECTOR_FILTER_VAR = "__tpgc_dn_filter"
  57. __DATANODE_SELECTOR_SORT_VAR = "__tpgc_dn_sort"
  58. __DATANODE_SELECTOR_ERROR_VAR = "__tpgc_dn_error"
  59. __elts = {
  60. "scenario_selector": Element(
  61. "value",
  62. {
  63. "id": ElementProperty(PropertyType.string),
  64. "show_add_button": ElementProperty(PropertyType.boolean, True),
  65. "display_cycles": ElementProperty(PropertyType.boolean, True),
  66. "show_primary_flag": ElementProperty(PropertyType.boolean, True),
  67. "value": ElementProperty(PropertyType.lov_value),
  68. "on_change": ElementProperty(PropertyType.function),
  69. "height": ElementProperty(PropertyType.string, "50vh"),
  70. "class_name": ElementProperty(PropertyType.dynamic_string),
  71. "show_pins": ElementProperty(PropertyType.boolean, False),
  72. "on_creation": ElementProperty(PropertyType.function),
  73. "show_dialog": ElementProperty(PropertyType.boolean, True),
  74. __SEL_SCENARIOS_PROP: ElementProperty(PropertyType.dynamic_list),
  75. "multiple": ElementProperty(PropertyType.boolean, False),
  76. "filter": ElementProperty(_GuiCoreScenarioFilter, "*"),
  77. "sort": ElementProperty(_GuiCoreScenarioSort, "*"),
  78. "show_search": ElementProperty(PropertyType.boolean, True),
  79. },
  80. inner_properties={
  81. "inner_scenarios": ElementProperty(
  82. PropertyType.lov_no_default,
  83. f"{{{__CTX_VAR_NAME}.get_scenarios(<tp:prop:{__SEL_SCENARIOS_PROP}>, "
  84. + f"{__SCENARIO_SELECTOR_FILTER_VAR}<tp:uniq:sc>, "
  85. + f"{__SCENARIO_SELECTOR_SORT_VAR}<tp:uniq:sc>)}}",
  86. ),
  87. "on_scenario_crud": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.crud_scenario}}"),
  88. "configs": ElementProperty(PropertyType.react, f"{{{__CTX_VAR_NAME}.get_scenario_configs()}}"),
  89. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  90. "error": ElementProperty(PropertyType.react, f"{{{__SCENARIO_SELECTOR_ERROR_VAR}<tp:uniq:sc>}}"),
  91. "type": ElementProperty(PropertyType.inner, __SCENARIO_ADAPTER),
  92. "scenario_edit": ElementProperty(
  93. _GuiCoreScenarioAdapter,
  94. f"{{{__CTX_VAR_NAME}.get_scenario_by_id({__SCENARIO_SELECTOR_ID_VAR}<tp:uniq:sc>)}}",
  95. ),
  96. "on_scenario_select": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.select_scenario}}"),
  97. "creation_not_allowed": ElementProperty(
  98. PropertyType.string, f"{{{__CTX_VAR_NAME}.get_creation_reason()}}"
  99. ),
  100. "update_sc_vars": ElementProperty(
  101. PropertyType.string,
  102. f"filter={__SCENARIO_SELECTOR_FILTER_VAR}<tp:uniq:sc>;"
  103. + f"sort={__SCENARIO_SELECTOR_SORT_VAR}<tp:uniq:sc>;"
  104. + f"sc_id={__SCENARIO_SELECTOR_ID_VAR}<tp:uniq:sc>;"
  105. + f"error_id={__SCENARIO_SELECTOR_ERROR_VAR}<tp:uniq:sc>",
  106. ),
  107. },
  108. ),
  109. "scenario": Element(
  110. "scenario",
  111. {
  112. "id": ElementProperty(PropertyType.string),
  113. "scenario": ElementProperty(_GuiCoreScenarioAdapter),
  114. "active": ElementProperty(PropertyType.dynamic_boolean, True),
  115. "expandable": ElementProperty(PropertyType.boolean, True),
  116. "expanded": ElementProperty(PropertyType.boolean, True),
  117. "show_submit": ElementProperty(PropertyType.boolean, True),
  118. "show_delete": ElementProperty(PropertyType.boolean, True),
  119. "show_config": ElementProperty(PropertyType.boolean, False),
  120. "show_cycle": ElementProperty(PropertyType.boolean, False),
  121. "show_tags": ElementProperty(PropertyType.boolean, True),
  122. "show_properties": ElementProperty(PropertyType.boolean, True),
  123. "show_sequences": ElementProperty(PropertyType.boolean, True),
  124. "show_submit_sequences": ElementProperty(PropertyType.boolean, True),
  125. "class_name": ElementProperty(PropertyType.dynamic_string),
  126. "on_submission_change": ElementProperty(PropertyType.function),
  127. },
  128. inner_properties={
  129. "on_edit": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.edit_entity}}"),
  130. "on_submit": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.submit_entity}}"),
  131. "on_delete": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.crud_scenario}}"),
  132. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  133. "error": ElementProperty(PropertyType.react, f"{{{__SCENARIO_VIZ_ERROR_VAR}<tp:uniq:sv>}}"),
  134. "update_sc_vars": ElementProperty(
  135. PropertyType.string,
  136. f"error_id={__SCENARIO_SELECTOR_ERROR_VAR}<tp:uniq:sv>",
  137. ),
  138. },
  139. ),
  140. "scenario_dag": Element(
  141. "scenario",
  142. {
  143. "id": ElementProperty(PropertyType.string),
  144. "scenario": ElementProperty(_GuiCoreScenarioDagAdapter),
  145. "render": ElementProperty(PropertyType.dynamic_boolean, True),
  146. "show_toolbar": ElementProperty(PropertyType.boolean, True),
  147. "width": ElementProperty(PropertyType.string),
  148. "height": ElementProperty(PropertyType.string),
  149. "class_name": ElementProperty(PropertyType.dynamic_string),
  150. "on_action": ElementProperty(PropertyType.function),
  151. },
  152. inner_properties={
  153. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  154. "on_select": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.on_dag_select}}"),
  155. },
  156. ),
  157. "data_node_selector": Element(
  158. "value",
  159. {
  160. "id": ElementProperty(PropertyType.string),
  161. "display_cycles": ElementProperty(PropertyType.boolean, True),
  162. "show_primary_flag": ElementProperty(PropertyType.boolean, True),
  163. "value": ElementProperty(PropertyType.lov_value),
  164. "on_change": ElementProperty(PropertyType.function),
  165. "height": ElementProperty(PropertyType.string, "50vh"),
  166. "class_name": ElementProperty(PropertyType.dynamic_string),
  167. "show_pins": ElementProperty(PropertyType.boolean, True),
  168. __DATANODE_SEL_SCENARIO_PROP: ElementProperty(PropertyType.dynamic_list),
  169. __SEL_DATANODES_PROP: ElementProperty(PropertyType.dynamic_list),
  170. "multiple": ElementProperty(PropertyType.boolean, False),
  171. "filter": ElementProperty(_GuiCoreDatanodeFilter, "*"),
  172. "sort": ElementProperty(_GuiCoreDatanodeSort, "*"),
  173. "show_search": ElementProperty(PropertyType.boolean, True),
  174. },
  175. inner_properties={
  176. "inner_datanodes": ElementProperty(
  177. PropertyType.lov_no_default,
  178. f"{{{__CTX_VAR_NAME}.get_datanodes_tree(<tp:prop:{__DATANODE_SEL_SCENARIO_PROP}>, "
  179. + f"<tp:prop:{__SEL_DATANODES_PROP}>, "
  180. + f"{__DATANODE_SELECTOR_FILTER_VAR}<tp:uniq:dns>, "
  181. + f"{__DATANODE_SELECTOR_SORT_VAR}<tp:uniq:dns>)}}",
  182. ),
  183. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  184. "type": ElementProperty(PropertyType.inner, __DATANODE_ADAPTER),
  185. "error": ElementProperty(PropertyType.react, f"{{{__DATANODE_SELECTOR_ERROR_VAR}<tp:uniq:dns>}}"),
  186. "update_dn_vars": ElementProperty(
  187. PropertyType.string,
  188. f"filter={__DATANODE_SELECTOR_FILTER_VAR}<tp:uniq:dns>;"
  189. + f"sort={__DATANODE_SELECTOR_SORT_VAR}<tp:uniq:dns>;"
  190. + f"error_id={__DATANODE_SELECTOR_ERROR_VAR}<tp:uniq:dns>",
  191. ),
  192. },
  193. ),
  194. "data_node": Element(
  195. __DATANODE_VIZ_DATA_NODE_PROP,
  196. {
  197. "id": ElementProperty(PropertyType.string),
  198. __DATANODE_VIZ_DATA_NODE_PROP: ElementProperty(_GuiCoreDatanodeAdapter),
  199. "active": ElementProperty(PropertyType.dynamic_boolean, True),
  200. "expandable": ElementProperty(PropertyType.boolean, True),
  201. "expanded": ElementProperty(PropertyType.boolean, True),
  202. "show_config": ElementProperty(PropertyType.boolean, False),
  203. "show_owner": ElementProperty(PropertyType.boolean, True),
  204. "show_edit_date": ElementProperty(PropertyType.boolean, False),
  205. "show_expiration_date": ElementProperty(PropertyType.boolean, False),
  206. "show_properties": ElementProperty(PropertyType.boolean, True),
  207. "show_history": ElementProperty(PropertyType.boolean, True),
  208. "show_data": ElementProperty(PropertyType.boolean, True),
  209. "chart_configs": ElementProperty(PropertyType.dict),
  210. "class_name": ElementProperty(PropertyType.dynamic_string),
  211. "scenario": ElementProperty(PropertyType.lov_value, "optional"),
  212. "width": ElementProperty(PropertyType.string),
  213. },
  214. inner_properties={
  215. "on_edit": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.edit_data_node}}"),
  216. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  217. "error": ElementProperty(PropertyType.react, f"{{{__DATANODE_VIZ_ERROR_VAR}<tp:uniq:dn>}}"),
  218. "scenarios": ElementProperty(
  219. PropertyType.lov,
  220. f"{{{__CTX_VAR_NAME}.get_scenarios_for_owner({__DATANODE_VIZ_OWNER_ID_VAR}<tp:uniq:dn>)}}",
  221. ),
  222. "type": ElementProperty(PropertyType.inner, __SCENARIO_ADAPTER),
  223. "dn_properties": ElementProperty(
  224. PropertyType.react,
  225. f"{{{__CTX_VAR_NAME}.get_data_node_properties("
  226. + f"{__DATANODE_VIZ_PROPERTIES_ID_VAR}<tp:uniq:dn>)}}",
  227. ),
  228. "history": ElementProperty(
  229. PropertyType.react,
  230. f"{{{__CTX_VAR_NAME}.get_data_node_history(" + f"{__DATANODE_VIZ_HISTORY_ID_VAR}<tp:uniq:dn>)}}",
  231. ),
  232. "tabular_data": ElementProperty(
  233. PropertyType.data,
  234. f"{{{__CTX_VAR_NAME}.get_data_node_tabular_data(" + f"{__DATANODE_VIZ_DATA_ID_VAR}<tp:uniq:dn>)}}",
  235. ),
  236. "tabular_columns": ElementProperty(
  237. PropertyType.dynamic_string,
  238. f"{{{__CTX_VAR_NAME}.get_data_node_tabular_columns("
  239. + f"{__DATANODE_VIZ_DATA_ID_VAR}<tp:uniq:dn>)}}",
  240. with_update=True,
  241. ),
  242. "chart_config": ElementProperty(
  243. PropertyType.dynamic_string,
  244. f"{{{__CTX_VAR_NAME}.get_data_node_chart_config("
  245. + f"{__DATANODE_VIZ_DATA_CHART_ID_VAR}<tp:uniq:dn>)}}",
  246. with_update=True,
  247. ),
  248. "on_data_value": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.update_data}}"),
  249. "on_tabular_data_edit": ElementProperty(
  250. PropertyType.function, f"{{{__CTX_VAR_NAME}.tabular_data_edit}}"
  251. ),
  252. "on_lock": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.lock_datanode_for_edit}}"),
  253. "update_dn_vars": ElementProperty(
  254. PropertyType.string,
  255. f"data_id={__DATANODE_VIZ_DATA_ID_VAR}<tp:uniq:dn>;"
  256. + f"history_id={__DATANODE_VIZ_HISTORY_ID_VAR}<tp:uniq:dn>;"
  257. + f"owner_id={__DATANODE_VIZ_OWNER_ID_VAR}<tp:uniq:dn>;"
  258. + f"chart_id={__DATANODE_VIZ_DATA_CHART_ID_VAR}<tp:uniq:dn>;"
  259. + f"properties_id={__DATANODE_VIZ_PROPERTIES_ID_VAR}<tp:uniq:dn>;"
  260. + f"error_id={__DATANODE_VIZ_ERROR_VAR}<tp:uniq:dn>",
  261. ),
  262. },
  263. ),
  264. "job_selector": Element(
  265. "value",
  266. {
  267. "id": ElementProperty(PropertyType.string),
  268. "class_name": ElementProperty(PropertyType.dynamic_string),
  269. "value": ElementProperty(PropertyType.lov_value),
  270. "show_id": ElementProperty(PropertyType.boolean, True),
  271. "show_submitted_label": ElementProperty(PropertyType.boolean, True),
  272. "show_submitted_id": ElementProperty(PropertyType.boolean, False),
  273. "show_submission_id": ElementProperty(PropertyType.boolean, False),
  274. "show_date": ElementProperty(PropertyType.boolean, True),
  275. "show_cancel": ElementProperty(PropertyType.boolean, True),
  276. "show_delete": ElementProperty(PropertyType.boolean, True),
  277. "on_change": ElementProperty(PropertyType.function),
  278. "height": ElementProperty(PropertyType.string, "50vh"),
  279. },
  280. inner_properties={
  281. "jobs": ElementProperty(PropertyType.lov, f"{{{__CTX_VAR_NAME}.get_jobs_list()}}"),
  282. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  283. "type": ElementProperty(PropertyType.inner, __JOB_ADAPTER),
  284. "on_job_action": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.act_on_jobs}}"),
  285. "error": ElementProperty(PropertyType.dynamic_string, f"{{{__JOB_SELECTOR_ERROR_VAR}<tp:uniq:jb>}}"),
  286. "update_jb_vars": ElementProperty(
  287. PropertyType.string, f"error_id={__JOB_SELECTOR_ERROR_VAR}<tp:uniq:jb>"
  288. ),
  289. },
  290. ),
  291. }
  292. def get_name(self) -> str:
  293. return _GuiCore.__LIB_NAME
  294. def get_elements(self) -> t.Dict[str, Element]:
  295. return _GuiCore.__elts
  296. def get_scripts(self) -> t.List[str]:
  297. return ["lib/taipy-gui-core.js"]
  298. def on_init(self, gui: Gui) -> t.Optional[t.Tuple[str, t.Any]]:
  299. ctx = _GuiCoreContext(gui)
  300. gui._add_adapter_for_type(_GuiCore.__SCENARIO_ADAPTER, ctx.scenario_adapter)
  301. gui._add_adapter_for_type(_GuiCore.__DATANODE_ADAPTER, ctx.data_node_adapter)
  302. gui._add_adapter_for_type(_GuiCore.__JOB_ADAPTER, ctx.job_adapter)
  303. return _GuiCore.__CTX_VAR_NAME, ctx
  304. def get_version(self) -> str:
  305. if not hasattr(self, "version"):
  306. self.version = _get_version()
  307. if "dev" in self.version:
  308. self.version += str(datetime.now().timestamp())
  309. return self.version