|
@@ -10,17 +10,39 @@
|
|
|
# specific language governing permissions and limitations under the License.
|
|
|
|
|
|
import typing as t
|
|
|
-import warnings
|
|
|
|
|
|
from dateutil import parser
|
|
|
|
|
|
import taipy as tp
|
|
|
-from taipy.core import Scenario
|
|
|
+from taipy.core import Cycle, Scenario
|
|
|
from taipy.core.notification import CoreEventConsumerBase, EventEntityType
|
|
|
from taipy.core.notification.event import Event
|
|
|
from taipy.core.notification.notifier import Notifier
|
|
|
from taipy.gui import Gui, State
|
|
|
from taipy.gui.extension import Element, ElementLibrary, ElementProperty, PropertyType
|
|
|
+from taipy.gui.utils import _TaipyBase
|
|
|
+
|
|
|
+
|
|
|
+class GuiCoreScenarioAdapter(_TaipyBase):
|
|
|
+ def get(self):
|
|
|
+ data = super().get()
|
|
|
+ if isinstance(data, Scenario):
|
|
|
+ return [
|
|
|
+ data.id,
|
|
|
+ data.is_primary,
|
|
|
+ data.config_id,
|
|
|
+ data.creation_date,
|
|
|
+ data.get_label(),
|
|
|
+ list(data.tags),
|
|
|
+ list(data.properties.items()),
|
|
|
+ [(p.id, p.get_simple_label()) for p in data.pipelines.values()],
|
|
|
+ list(data.properties.get("authorized_tags", set())),
|
|
|
+ ]
|
|
|
+ return data
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def get_hash():
|
|
|
+ return _TaipyBase._HOLDER_PREFIX + "Sc"
|
|
|
|
|
|
|
|
|
class GuiCoreContext(CoreEventConsumerBase):
|
|
@@ -33,9 +55,7 @@ class GuiCoreContext(CoreEventConsumerBase):
|
|
|
|
|
|
def __init__(self, gui: Gui) -> None:
|
|
|
self.gui = gui
|
|
|
- self.scenarios: t.Optional[
|
|
|
- t.List[t.Tuple[str, str, int, bool, t.Optional[t.List[t.Tuple[str, str, int, bool, None]]]]]
|
|
|
- ] = None
|
|
|
+ self.cycles_scenarios: t.Optional[t.List[t.Union[Cycle, Scenario]]] = None
|
|
|
self.scenario_configs: t.Optional[t.List[t.Tuple[str, str]]] = None
|
|
|
# register to taipy core notification
|
|
|
reg_id, reg_queue = Notifier.register()
|
|
@@ -44,24 +64,26 @@ class GuiCoreContext(CoreEventConsumerBase):
|
|
|
|
|
|
def process_event(self, event: Event):
|
|
|
if event.entity_type == EventEntityType.SCENARIO or event.entity_type == EventEntityType.CYCLE:
|
|
|
- self.scenarios = None
|
|
|
+ self.cycles_scenarios = None
|
|
|
self.gui.broadcast(GuiCoreContext._CORE_CHANGED_NAME, {"scenario": True})
|
|
|
|
|
|
- def get_scenarios(self):
|
|
|
- if self.scenarios is None:
|
|
|
-
|
|
|
- def add_scenarios(res, scens):
|
|
|
- for scenario in scens:
|
|
|
- res.append((scenario.id, scenario.name, 1, scenario.is_primary, None))
|
|
|
- return res
|
|
|
+ @staticmethod
|
|
|
+ def scenario_adapter(data):
|
|
|
+ if isinstance(data, Cycle):
|
|
|
+ return (data.id, data.name, tp.get_scenarios(data), 0, False)
|
|
|
+ elif isinstance(data, Scenario):
|
|
|
+ return (data.id, data.name, None, 1, data.is_primary)
|
|
|
+ return data
|
|
|
|
|
|
- self.scenarios = []
|
|
|
+ def get_scenarios(self):
|
|
|
+ if self.cycles_scenarios is None:
|
|
|
+ self.cycles_scenarios = []
|
|
|
for cycle, scenarios in tp.get_cycles_scenarios().items():
|
|
|
if cycle is None:
|
|
|
- add_scenarios(self.scenarios, scenarios)
|
|
|
+ self.cycles_scenarios.extend(scenarios)
|
|
|
else:
|
|
|
- self.scenarios.append((cycle.id, cycle.name, 0, False, add_scenarios([], scenarios)))
|
|
|
- return self.scenarios
|
|
|
+ self.cycles_scenarios.append(cycle)
|
|
|
+ return self.cycles_scenarios
|
|
|
|
|
|
def get_scenario_configs(self):
|
|
|
if self.scenario_configs is None:
|
|
@@ -71,7 +93,6 @@ class GuiCoreContext(CoreEventConsumerBase):
|
|
|
return self.scenario_configs
|
|
|
|
|
|
def create_new_scenario(self, state: State, id: str, action: str, payload: t.Dict[str, str]):
|
|
|
- print(f"create_new_scenario(state, {id}, {action}, {payload}")
|
|
|
args = payload.get("args")
|
|
|
if args is None or not isinstance(args, list) or len(args) == 0 or not isinstance(args[0], dict):
|
|
|
return
|
|
@@ -87,48 +108,17 @@ class GuiCoreContext(CoreEventConsumerBase):
|
|
|
except Exception as e:
|
|
|
state.assign(GuiCoreContext._ERROR_VAR, f"Invalid date ({date_str}).{e}")
|
|
|
return
|
|
|
- scenario = tp.create_scenario(scenario_config, date, data.get(GuiCoreContext.__PROP_SCENARIO_NAME))
|
|
|
- if props := data.get("properties"):
|
|
|
- with scenario as sc:
|
|
|
- for prop in props:
|
|
|
- key = prop.get("key")
|
|
|
- if key and key not in GuiCoreContext.__SCENARIO_PROPS:
|
|
|
- sc._properties[key] = prop.get("value")
|
|
|
- state.assign(GuiCoreContext._ERROR_VAR, "")
|
|
|
-
|
|
|
- def select_scenario(self, state: State, id: str, action: str, payload: t.Dict[str, str]):
|
|
|
- print(f"select_scenario(state, {id}, {action}, {payload}")
|
|
|
- args = payload.get("args")
|
|
|
- if args is None or not isinstance(args, list) or len(args) == 0 or not isinstance(args[0], dict):
|
|
|
- return
|
|
|
- data = args[0]
|
|
|
- action = data.get("user_action")
|
|
|
- action_function = None
|
|
|
- if action:
|
|
|
- action_function = self.gui._get_user_function(action)
|
|
|
- if not callable(action_function):
|
|
|
- action_function = None
|
|
|
- warnings.warn(f"on_select ({action_function}) function is not callable.")
|
|
|
- return
|
|
|
- if action_function is None:
|
|
|
- if not hasattr(self.gui, "on_action"):
|
|
|
- return
|
|
|
- action_function = self.gui.on_action
|
|
|
- ids = data.get("ids")
|
|
|
- if not isinstance(ids, list) or len(ids) == 0:
|
|
|
- state.assign(GuiCoreContext._ERROR_VAR, "Invalid selection.")
|
|
|
- return
|
|
|
- scenarios: t.List[Scenario] = []
|
|
|
- for id in ids:
|
|
|
- try:
|
|
|
- entity = tp.get(id)
|
|
|
- if isinstance(entity, Scenario):
|
|
|
- scenarios.append(entity)
|
|
|
- except Exception:
|
|
|
- pass
|
|
|
- if len(scenarios) == 0:
|
|
|
- return
|
|
|
- self.gui._call_function_with_state(action_function, [id, action_function.__name__, scenarios[0]])
|
|
|
+ try:
|
|
|
+ scenario = tp.create_scenario(scenario_config, date, data.get(GuiCoreContext.__PROP_SCENARIO_NAME))
|
|
|
+ if props := data.get("properties"):
|
|
|
+ with scenario as sc:
|
|
|
+ for prop in props:
|
|
|
+ key = prop.get("key")
|
|
|
+ if key and key not in GuiCoreContext.__SCENARIO_PROPS:
|
|
|
+ sc._properties[key] = prop.get("value")
|
|
|
+ state.assign(GuiCoreContext._ERROR_VAR, "")
|
|
|
+ except Exception as e:
|
|
|
+ state.assign(GuiCoreContext._ERROR_VAR, f"Error creating Scenario. {e}")
|
|
|
|
|
|
def broadcast_core_changed(self):
|
|
|
self.gui.broadcast(GuiCoreContext._CORE_CHANGED_NAME, "")
|
|
@@ -140,21 +130,25 @@ class GuiCore(ElementLibrary):
|
|
|
|
|
|
__elts = {
|
|
|
"scenario_selector": Element(
|
|
|
- "scenario_id",
|
|
|
+ "value",
|
|
|
{
|
|
|
"show_add_button": ElementProperty(PropertyType.dynamic_boolean, True),
|
|
|
"display_cycles": ElementProperty(PropertyType.dynamic_boolean, True),
|
|
|
"show_primary_flag": ElementProperty(PropertyType.dynamic_boolean, True),
|
|
|
- "scenario_id": ElementProperty(PropertyType.dynamic_string),
|
|
|
- "scenarios": ElementProperty(PropertyType.react, f"{{{__CTX_VAR_NAME}.get_scenarios()}}"),
|
|
|
+ "value": ElementProperty(PropertyType.lov_value),
|
|
|
+ "on_change": ElementProperty(PropertyType.function),
|
|
|
+ "scenario": ElementProperty(GuiCoreScenarioAdapter),
|
|
|
+ },
|
|
|
+ inner_properties={
|
|
|
+ "scenarios": ElementProperty(PropertyType.lov, f"{{{__CTX_VAR_NAME}.get_scenarios()}}"),
|
|
|
"on_scenario_create": ElementProperty(
|
|
|
PropertyType.function, f"{{{__CTX_VAR_NAME}.create_new_scenario}}"
|
|
|
),
|
|
|
"configs": ElementProperty(PropertyType.react, f"{{{__CTX_VAR_NAME}.get_scenario_configs()}}"),
|
|
|
"core_changed": ElementProperty(PropertyType.broadcast, GuiCoreContext._CORE_CHANGED_NAME),
|
|
|
- "error": ElementProperty(PropertyType.react, GuiCoreContext._ERROR_VAR),
|
|
|
- "on_ctx_selection": ElementProperty(PropertyType.function, f"{{{__CTX_VAR_NAME}.select_scenario}}"),
|
|
|
- "on_action": ElementProperty(PropertyType.function),
|
|
|
+ "error": ElementProperty(PropertyType.react, f"{{{GuiCoreContext._ERROR_VAR}}}"),
|
|
|
+ "type": ElementProperty(PropertyType.inner, Scenario),
|
|
|
+ "adapter": ElementProperty(PropertyType.inner, GuiCoreContext.scenario_adapter),
|
|
|
},
|
|
|
)
|
|
|
}
|