_GuiCoreLib.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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, State
  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. __JOB_DETAIL_ID_VAR = "__tpgc_jd_id"
  47. __DATANODE_VIZ_ERROR_VAR = "__tpgc_dv_error"
  48. __DATANODE_VIZ_OWNER_ID_VAR = "__tpgc_dv_owner_id"
  49. __DATANODE_VIZ_HISTORY_ID_VAR = "__tpgc_dv_history_id"
  50. __DATANODE_VIZ_PROPERTIES_ID_VAR = "__tpgc_dv_properties_id"
  51. __DATANODE_VIZ_DATA_ID_VAR = "__tpgc_dv_data_id"
  52. __DATANODE_VIZ_DATA_CHART_ID_VAR = "__tpgc_dv_data_chart_id"
  53. __DATANODE_VIZ_DATA_NODE_PROP = "data_node"
  54. __DATANODE_SEL_SCENARIO_PROP = "scenario"
  55. __SEL_SCENARIOS_PROP = "scenarios"
  56. __SEL_DATANODES_PROP = "datanodes"
  57. __DATANODE_SELECTOR_FILTER_VAR = "__tpgc_dn_filter"
  58. __DATANODE_SELECTOR_SORT_VAR = "__tpgc_dn_sort"
  59. __DATANODE_SELECTOR_ERROR_VAR = "__tpgc_dn_error"
  60. __elements = {
  61. "scenario_selector": Element(
  62. "value",
  63. {
  64. "id": ElementProperty(PropertyType.string),
  65. "show_add_button": ElementProperty(PropertyType.boolean, True),
  66. "display_cycles": ElementProperty(PropertyType.boolean, True),
  67. "show_primary_flag": ElementProperty(PropertyType.boolean, True),
  68. "value": ElementProperty(PropertyType.lov_value),
  69. "on_change": ElementProperty(PropertyType.function),
  70. "height": ElementProperty(PropertyType.string, "50vh"),
  71. "class_name": ElementProperty(PropertyType.dynamic_string),
  72. "show_pins": ElementProperty(PropertyType.boolean, False),
  73. "on_creation": ElementProperty(PropertyType.function),
  74. "show_dialog": ElementProperty(PropertyType.boolean, True),
  75. __SEL_SCENARIOS_PROP: ElementProperty(PropertyType.dynamic_list),
  76. "multiple": ElementProperty(PropertyType.boolean, False),
  77. "filter": ElementProperty(_GuiCoreScenarioFilter, "*"),
  78. "sort": ElementProperty(_GuiCoreScenarioSort, "*"),
  79. "show_search": ElementProperty(PropertyType.boolean, True),
  80. },
  81. inner_properties={
  82. "inner_scenarios": ElementProperty(
  83. PropertyType.lov_no_default,
  84. f"{{{__CTX_VAR_NAME}.get_scenarios(<tp:prop:{__SEL_SCENARIOS_PROP}>, "
  85. + f"{__SCENARIO_SELECTOR_FILTER_VAR}<tp:uniq:sc>, "
  86. + f"{__SCENARIO_SELECTOR_SORT_VAR}<tp:uniq:sc>)}}",
  87. ),
  88. "on_scenario_crud": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.crud_scenario}}"),
  89. "configs": ElementProperty(PropertyType.react, f"{{{__CTX_VAR_NAME}.get_scenario_configs()}}"),
  90. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  91. "error": ElementProperty(PropertyType.react, f"{{{__SCENARIO_SELECTOR_ERROR_VAR}<tp:uniq:sc>}}"),
  92. "type": ElementProperty(PropertyType.inner, __SCENARIO_ADAPTER),
  93. "scenario_edit": ElementProperty(
  94. _GuiCoreScenarioAdapter,
  95. f"{{{__CTX_VAR_NAME}.get_scenario_by_id({__SCENARIO_SELECTOR_ID_VAR}<tp:uniq:sc>)}}",
  96. ),
  97. "on_scenario_select": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.select_scenario}}"),
  98. "creation_not_allowed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._AUTH_CHANGED_NAME),
  99. "update_sc_vars": ElementProperty(
  100. PropertyType.string,
  101. f"filter={__SCENARIO_SELECTOR_FILTER_VAR}<tp:uniq:sc>;"
  102. + f"sort={__SCENARIO_SELECTOR_SORT_VAR}<tp:uniq:sc>;"
  103. + f"sc_id={__SCENARIO_SELECTOR_ID_VAR}<tp:uniq:sc>;"
  104. + f"error_id={__SCENARIO_SELECTOR_ERROR_VAR}<tp:uniq:sc>",
  105. ),
  106. },
  107. ),
  108. "scenario": Element(
  109. "scenario",
  110. {
  111. "id": ElementProperty(PropertyType.string),
  112. "scenario": ElementProperty(_GuiCoreScenarioAdapter),
  113. "active": ElementProperty(PropertyType.dynamic_boolean, True),
  114. "expandable": ElementProperty(PropertyType.boolean, True),
  115. "expanded": ElementProperty(PropertyType.boolean, True),
  116. "show_submit": ElementProperty(PropertyType.boolean, True),
  117. "show_delete": ElementProperty(PropertyType.boolean, True),
  118. "show_config": ElementProperty(PropertyType.boolean, False),
  119. "show_cycle": ElementProperty(PropertyType.boolean, False),
  120. "show_tags": ElementProperty(PropertyType.boolean, True),
  121. "show_properties": ElementProperty(PropertyType.boolean, True),
  122. "show_sequences": ElementProperty(PropertyType.boolean, True),
  123. "show_submit_sequences": ElementProperty(PropertyType.boolean, True),
  124. "class_name": ElementProperty(PropertyType.dynamic_string),
  125. "on_submission_change": ElementProperty(PropertyType.function),
  126. },
  127. inner_properties={
  128. "on_edit": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.edit_entity}}"),
  129. "on_submit": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.submit_entity}}"),
  130. "on_delete": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.crud_scenario}}"),
  131. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  132. "error": ElementProperty(PropertyType.react, f"{{{__SCENARIO_VIZ_ERROR_VAR}<tp:uniq:sv>}}"),
  133. "update_sc_vars": ElementProperty(
  134. PropertyType.string,
  135. f"error_id={__SCENARIO_SELECTOR_ERROR_VAR}<tp:uniq:sv>",
  136. ),
  137. },
  138. ),
  139. "scenario_dag": Element(
  140. "scenario",
  141. {
  142. "id": ElementProperty(PropertyType.string),
  143. "scenario": ElementProperty(_GuiCoreScenarioDagAdapter),
  144. "render": ElementProperty(PropertyType.dynamic_boolean, True),
  145. "show_toolbar": ElementProperty(PropertyType.boolean, True),
  146. "width": ElementProperty(PropertyType.string),
  147. "height": ElementProperty(PropertyType.string),
  148. "class_name": ElementProperty(PropertyType.dynamic_string),
  149. "on_action": ElementProperty(PropertyType.function),
  150. },
  151. inner_properties={
  152. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  153. "on_select": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.on_dag_select}}"),
  154. },
  155. ),
  156. "data_node_selector": Element(
  157. "value",
  158. {
  159. "id": ElementProperty(PropertyType.string),
  160. "display_cycles": ElementProperty(PropertyType.boolean, True),
  161. "show_primary_flag": ElementProperty(PropertyType.boolean, True),
  162. "value": ElementProperty(PropertyType.lov_value),
  163. "on_change": ElementProperty(PropertyType.function),
  164. "height": ElementProperty(PropertyType.string, "50vh"),
  165. "class_name": ElementProperty(PropertyType.dynamic_string),
  166. "show_pins": ElementProperty(PropertyType.boolean, True),
  167. __DATANODE_SEL_SCENARIO_PROP: ElementProperty(PropertyType.dynamic_list),
  168. __SEL_DATANODES_PROP: ElementProperty(PropertyType.dynamic_list),
  169. "multiple": ElementProperty(PropertyType.boolean, False),
  170. "filter": ElementProperty(_GuiCoreDatanodeFilter, "*"),
  171. "sort": ElementProperty(_GuiCoreDatanodeSort, "*"),
  172. "show_search": ElementProperty(PropertyType.boolean, True),
  173. },
  174. inner_properties={
  175. "inner_datanodes": ElementProperty(
  176. PropertyType.lov_no_default,
  177. f"{{{__CTX_VAR_NAME}.get_datanodes_tree(<tp:prop:{__DATANODE_SEL_SCENARIO_PROP}>, "
  178. + f"<tp:prop:{__SEL_DATANODES_PROP}>, "
  179. + f"{__DATANODE_SELECTOR_FILTER_VAR}<tp:uniq:dns>, "
  180. + f"{__DATANODE_SELECTOR_SORT_VAR}<tp:uniq:dns>)}}",
  181. ),
  182. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  183. "type": ElementProperty(PropertyType.inner, __DATANODE_ADAPTER),
  184. "error": ElementProperty(PropertyType.react, f"{{{__DATANODE_SELECTOR_ERROR_VAR}<tp:uniq:dns>}}"),
  185. "update_dn_vars": ElementProperty(
  186. PropertyType.string,
  187. f"filter={__DATANODE_SELECTOR_FILTER_VAR}<tp:uniq:dns>;"
  188. + f"sort={__DATANODE_SELECTOR_SORT_VAR}<tp:uniq:dns>;"
  189. + f"error_id={__DATANODE_SELECTOR_ERROR_VAR}<tp:uniq:dns>",
  190. ),
  191. },
  192. ),
  193. "data_node": Element(
  194. __DATANODE_VIZ_DATA_NODE_PROP,
  195. {
  196. "id": ElementProperty(PropertyType.string),
  197. __DATANODE_VIZ_DATA_NODE_PROP: ElementProperty(_GuiCoreDatanodeAdapter),
  198. "active": ElementProperty(PropertyType.dynamic_boolean, True),
  199. "expandable": ElementProperty(PropertyType.boolean, True),
  200. "expanded": ElementProperty(PropertyType.boolean, True),
  201. "show_config": ElementProperty(PropertyType.boolean, False),
  202. "show_owner": ElementProperty(PropertyType.boolean, True),
  203. "show_edit_date": ElementProperty(PropertyType.boolean, False),
  204. "show_expiration_date": ElementProperty(PropertyType.boolean, False),
  205. "show_custom_properties": ElementProperty(PropertyType.boolean, True),
  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. "file_download": ElementProperty(PropertyType.boolean, False),
  214. "file_upload": ElementProperty(PropertyType.boolean, False),
  215. "upload_check": ElementProperty(PropertyType.function),
  216. "show_owner_label": ElementProperty(PropertyType.boolean, False),
  217. },
  218. inner_properties={
  219. "on_edit": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.edit_data_node}}"),
  220. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  221. "error": ElementProperty(PropertyType.react, f"{{{__DATANODE_VIZ_ERROR_VAR}<tp:uniq:dn>}}"),
  222. "scenarios": ElementProperty(
  223. PropertyType.lov,
  224. f"{{{__CTX_VAR_NAME}.get_scenarios_for_owner({__DATANODE_VIZ_OWNER_ID_VAR}<tp:uniq:dn>)}}",
  225. ),
  226. "type": ElementProperty(PropertyType.inner, __SCENARIO_ADAPTER),
  227. "dn_properties": ElementProperty(
  228. PropertyType.react,
  229. f"{{{__CTX_VAR_NAME}.get_data_node_properties("
  230. + f"{__DATANODE_VIZ_PROPERTIES_ID_VAR}<tp:uniq:dn>)}}",
  231. ),
  232. "history": ElementProperty(
  233. PropertyType.react,
  234. f"{{{__CTX_VAR_NAME}.get_data_node_history(" + f"{__DATANODE_VIZ_HISTORY_ID_VAR}<tp:uniq:dn>)}}",
  235. ),
  236. "tabular_data": ElementProperty(
  237. PropertyType.data,
  238. f"{{{__CTX_VAR_NAME}.get_data_node_tabular_data(" + f"{__DATANODE_VIZ_DATA_ID_VAR}<tp:uniq:dn>)}}",
  239. ),
  240. "tabular_columns": ElementProperty(
  241. PropertyType.dynamic_string,
  242. f"{{{__CTX_VAR_NAME}.get_data_node_tabular_columns("
  243. + f"{__DATANODE_VIZ_DATA_ID_VAR}<tp:uniq:dn>)}}",
  244. with_update=True,
  245. ),
  246. "chart_config": ElementProperty(
  247. PropertyType.dynamic_string,
  248. f"{{{__CTX_VAR_NAME}.get_data_node_chart_config("
  249. + f"{__DATANODE_VIZ_DATA_CHART_ID_VAR}<tp:uniq:dn>)}}",
  250. with_update=True,
  251. ),
  252. "on_data_value": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.update_data}}"),
  253. "on_tabular_data_edit": ElementProperty(
  254. PropertyType.function, f"{{{__CTX_VAR_NAME}.tabular_data_edit}}"
  255. ),
  256. "on_lock": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.lock_datanode_for_edit}}"),
  257. "on_file_action": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.on_file_action}}"),
  258. "update_dn_vars": ElementProperty(
  259. PropertyType.string,
  260. f"data_id={__DATANODE_VIZ_DATA_ID_VAR}<tp:uniq:dn>;"
  261. + f"history_id={__DATANODE_VIZ_HISTORY_ID_VAR}<tp:uniq:dn>;"
  262. + f"owner_id={__DATANODE_VIZ_OWNER_ID_VAR}<tp:uniq:dn>;"
  263. + f"chart_id={__DATANODE_VIZ_DATA_CHART_ID_VAR}<tp:uniq:dn>;"
  264. + f"properties_id={__DATANODE_VIZ_PROPERTIES_ID_VAR}<tp:uniq:dn>;"
  265. + f"error_id={__DATANODE_VIZ_ERROR_VAR}<tp:uniq:dn>",
  266. ),
  267. },
  268. ),
  269. "job_selector": Element(
  270. "value",
  271. {
  272. "id": ElementProperty(PropertyType.string),
  273. "class_name": ElementProperty(PropertyType.dynamic_string),
  274. "value": ElementProperty(PropertyType.lov_value),
  275. "show_id": ElementProperty(PropertyType.boolean, True),
  276. "show_submitted_label": ElementProperty(PropertyType.boolean, True),
  277. "show_submitted_id": ElementProperty(PropertyType.boolean, False),
  278. "show_submission_id": ElementProperty(PropertyType.boolean, False),
  279. "show_date": ElementProperty(PropertyType.boolean, True),
  280. "show_cancel": ElementProperty(PropertyType.boolean, True),
  281. "show_delete": ElementProperty(PropertyType.boolean, True),
  282. "on_change": ElementProperty(PropertyType.function),
  283. "on_details": ElementProperty(PropertyType.function),
  284. "height": ElementProperty(PropertyType.string, "50vh"),
  285. },
  286. inner_properties={
  287. "jobs": ElementProperty(PropertyType.lov, f"{{{__CTX_VAR_NAME}.get_jobs_list()}}"),
  288. "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
  289. "type": ElementProperty(PropertyType.inner, __JOB_ADAPTER),
  290. "on_job_action": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.act_on_jobs}}"),
  291. "error": ElementProperty(PropertyType.dynamic_string, f"{{{__JOB_SELECTOR_ERROR_VAR}<tp:uniq:jb>}}"),
  292. "details": ElementProperty(
  293. PropertyType.react,
  294. f"{{{__CTX_VAR_NAME}.get_job_details(" + f"{__JOB_DETAIL_ID_VAR}<tp:uniq:jb>)}}",
  295. ),
  296. "update_jb_vars": ElementProperty(
  297. PropertyType.string,
  298. f"error_id={__JOB_SELECTOR_ERROR_VAR}<tp:uniq:jb>;"
  299. + f"detail_id={__JOB_DETAIL_ID_VAR}<tp:uniq:jb>;",
  300. ),
  301. },
  302. ),
  303. }
  304. def get_name(self) -> str:
  305. return _GuiCore.__LIB_NAME
  306. def get_elements(self) -> t.Dict[str, Element]:
  307. return _GuiCore.__elements
  308. def get_scripts(self) -> t.List[str]:
  309. return ["lib/*.js"]
  310. def on_init(self, gui: Gui) -> t.Optional[t.Tuple[str, t.Any]]:
  311. self.ctx = _GuiCoreContext(gui)
  312. gui._add_adapter_for_type(_GuiCore.__SCENARIO_ADAPTER, self.ctx.scenario_adapter)
  313. gui._add_adapter_for_type(_GuiCore.__DATANODE_ADAPTER, self.ctx.data_node_adapter)
  314. gui._add_adapter_for_type(_GuiCore.__JOB_ADAPTER, self.ctx.job_adapter)
  315. return _GuiCore.__CTX_VAR_NAME, self.ctx
  316. def on_user_init(self, state: State):
  317. self.ctx.on_user_init(state)
  318. def get_version(self) -> str:
  319. if not hasattr(self, "version"):
  320. self.version = _get_version()
  321. if "dev" in self.version:
  322. self.version += str(datetime.now().timestamp())
  323. return self.version