Browse Source

Backport: init values (#222) (#224)

* #222 init values

* fix init

* backport mypy changes

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 1 year ago
parent
commit
f1c1c79f92

+ 26 - 12
gui/src/ScenarioDag.tsx

@@ -21,6 +21,7 @@ import { useClassNames } from "./utils";
 
 interface ScenarioDagProps {
     id?: string;
+    defaultScenario?: string;
     scenario?: DisplayModel | DisplayModel[];
     coreChanged?: Record<string, unknown>;
     updateVarName?: string;
@@ -59,6 +60,13 @@ const DagTitle = (props: DagTitleProps) => (
     </AppBar>
 );
 
+const getValidScenario = (scenar: DisplayModel | DisplayModel[]) =>
+    scenar.length == 3 && typeof scenar[0] === "string"
+        ? (scenar as DisplayModel)
+        : scenar.length == 1
+        ? (scenar[0] as DisplayModel)
+        : undefined;
+
 const ScenarioDag = (props: ScenarioDagProps) => {
     const { showToolbar = true } = props;
     const [scenarioId, setScenarioId] = useState("");
@@ -81,18 +89,24 @@ const ScenarioDag = (props: ScenarioDagProps) => {
         }
     }, [props.coreChanged, props.updateVarName, scenarioId, module, dispatch, props.id]);
 
-    useEffect(() => {
-        const displayModel = Array.isArray(props.scenario)
-            ? props.scenario.length == 3 && typeof props.scenario[0] === "string"
-                ? (props.scenario as DisplayModel)
-                : props.scenario.length == 1
-                ? (props.scenario[0] as DisplayModel)
-                : undefined
-            : undefined;
+    const displayModel = useMemo(() => {
+        let dm: DisplayModel | undefined = undefined;
+        if (Array.isArray(props.scenario)) {
+            dm = getValidScenario(props.scenario);
+        } else if (props.defaultScenario) {
+            try {
+                dm = getValidScenario(JSON.parse(props.defaultScenario));
+            } catch {
+                // Do nothing
+            }
+        }
+        return dm;
+    }, [props.scenario, props.defaultScenario]);
 
+    useEffect(() => {
         // clear model
         const model = new TaipyDiagramModel();
-        if (displayModel && props.scenario) {
+        if (displayModel) {
             setScenarioId(displayModel[0]);
             // populate model
             populateModel(displayModel, model);
@@ -102,16 +116,16 @@ const ScenarioDag = (props: ScenarioDagProps) => {
         //engine.getActionEventBus().registerAction(new DeleteItemsAction({ keyCodes: [1] }));
         model.setLocked(true);
         setTimeout(relayout, 500);
-    }, [props.scenario]);
+    }, [displayModel]);
 
     useEffect(() => {
         const showVar = getUpdateVar(props.updateVars, "show");
         showVar && dispatch(createSendUpdateAction(showVar, render, module));
     }, [render, props.updateVars, dispatch, module]);
 
-    return render ? (
+    return render && scenarioId ? (
         <Box sx={sizeSx} id={props.id} className={className}>
-            {showToolbar && scenarioId ? <DagTitle zoomToFit={zoomToFit} /> : null}
+            {showToolbar ? <DagTitle zoomToFit={zoomToFit} /> : null}
             <Box sx={boxSx}>
                 <CanvasWidget engine={engine} />
             </Box>

+ 13 - 2
gui/src/ScenarioSelector.tsx

@@ -612,10 +612,21 @@ const ScenarioSelector = (props: ScenarioSelectorProps) => {
     }, [props.coreChanged, props.updateVars, module, dispatch, id]);
 
     useEffect(() => {
-        if (value !== undefined) {
+        if (value !== undefined && value !== null) {
             setSelected(value);
         } else if (defaultValue) {
-            setSelected(defaultValue);
+            try {
+                const parsedValue = JSON.parse(defaultValue);
+                if (Array.isArray(parsedValue)) {
+                    parsedValue.length && setSelected(parsedValue[0]);
+                } else {
+                    setSelected(parsedValue);
+                }
+            } catch {
+                setSelected(defaultValue);
+            }
+        } else if (value === null) {
+            setSelected("");
         }
     }, [defaultValue, value]);
 

+ 19 - 8
gui/src/ScenarioViewer.tsx

@@ -55,6 +55,7 @@ interface ScenarioViewerProps {
     expanded?: boolean;
     defaultExpanded?: boolean;
     updateVarName?: string;
+    defaultScenario?: string;
     scenario?: ScenarioFull | Array<ScenarioFull>;
     onSubmit?: string;
     onEdit?: string;
@@ -215,6 +216,13 @@ const PipelineRow = ({
     );
 };
 
+const getValidScenario = (scenar: ScenarioFull | ScenarioFull[]) =>
+    scenar.length == ScenarioFullLength && typeof scenar[ScFProps.id] === "string"
+        ? (scenar as ScenarioFull)
+        : scenar.length == 1
+        ? (scenar[0] as ScenarioFull)
+        : undefined;
+
 const ScenarioViewer = (props: ScenarioViewerProps) => {
     const {
         id = "",
@@ -245,15 +253,18 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
         scDeletable,
         isScenario,
     ] = useMemo(() => {
-        const sc = Array.isArray(props.scenario)
-            ? props.scenario.length == ScenarioFullLength && typeof props.scenario[ScFProps.id] === "string"
-                ? (props.scenario as ScenarioFull)
-                : props.scenario.length == 1
-                ? (props.scenario[0] as ScenarioFull)
-                : undefined
-            : undefined;
+        let sc: ScenarioFull | undefined = undefined;
+        if (Array.isArray(props.scenario)) {
+            sc = getValidScenario(props.scenario);
+        } else if (props.defaultScenario) {
+            try {
+                sc = getValidScenario(JSON.parse(props.defaultScenario));
+            } catch {
+                // DO nothing
+            }
+        }
         return sc ? [...sc, true] : ["", false, "", "", "", [], [], [], [], false, false];
-    }, [props.scenario]);
+    }, [props.scenario, props.defaultScenario]);
 
     const active = useDynamicProperty(props.active, props.defaultActive, true);
     const expanded = useDynamicProperty(props.expanded, props.defaultExpanded, false);

+ 28 - 25
src/taipy/gui_core/GuiCoreLib.py

@@ -16,9 +16,12 @@ from threading import Lock
 
 from dateutil import parser
 
-import taipy as tp
 from taipy.config import Config
-from taipy.core import Cycle, DataNode, Pipeline, Scenario
+from taipy.core import Cycle, DataNode, Pipeline, Scenario, create_scenario
+from taipy.core import delete as core_delete
+from taipy.core import get as core_get
+from taipy.core import get_cycles_scenarios, get_data_nodes, get_scenarios, is_deletable, set_primary
+from taipy.core import submit as core_submit
 from taipy.core.notification import CoreEventConsumerBase, EventEntityType
 from taipy.core.notification.event import Event
 from taipy.core.notification.notifier import Notifier
@@ -55,7 +58,7 @@ class _GuiCoreScenarioAdapter(_TaipyBase):
     def get(self):
         data = super().get()
         if isinstance(data, Scenario):
-            scenario = tp.get(data.id)
+            scenario = core_get(data.id)
             if scenario:
                 return [
                     scenario.id,
@@ -67,7 +70,7 @@ class _GuiCoreScenarioAdapter(_TaipyBase):
                     [(k, v) for k, v in scenario.properties.items() if k not in _GuiCoreScenarioAdapter.__INNER_PROPS],
                     [(p.id, p.get_simple_label()) for p in scenario.pipelines.values()],
                     list(scenario.properties.get("authorized_tags", set())),
-                    tp.is_deletable(scenario),  # deletable
+                    is_deletable(scenario),  # deletable
                 ]
         return None
 
@@ -84,7 +87,7 @@ class _GuiCoreScenarioDagAdapter(_TaipyBase):
     def get(self):
         data = super().get()
         if isinstance(data, Scenario):
-            scenario = tp.get(data.id)
+            scenario = core_get(data.id)
             if scenario:
                 dag = data._get_dag()
                 nodes = dict()
@@ -145,14 +148,14 @@ class _GuiCoreContext(CoreEventConsumerBase):
     def process_event(self, event: Event):
         if event.entity_type == EventEntityType.SCENARIO:
             self.scenarios_base_level = None
-            scenario = tp.get(event.entity_id) if event.operation.value != 3 else None
+            scenario = core_get(event.entity_id) if event.operation.value != 3 else None
             self.gui.broadcast(
                 _GuiCoreContext._CORE_CHANGED_NAME,
                 {"scenario": event.entity_id if scenario else True},
             )
             self.data_nodes_base_level = None
         elif event.entity_type == EventEntityType.PIPELINE and event.entity_id:  # TODO import EventOperation
-            pipeline = tp.get(event.entity_id) if event.operation.value != 3 else None
+            pipeline = core_get(event.entity_id) if event.operation.value != 3 else None
             if pipeline:
                 if hasattr(pipeline, "parent_ids") and pipeline.parent_ids:
                     self.gui.broadcast(
@@ -161,9 +164,9 @@ class _GuiCoreContext(CoreEventConsumerBase):
 
     @staticmethod
     def scenario_adapter(data):
-        if hasattr(data, "id") and tp.get(data.id) is not None:
+        if hasattr(data, "id") and core_get(data.id) is not None:
             if isinstance(data, Cycle):
-                return (data.id, data.get_simple_label(), tp.get_scenarios(data), _EntityType.CYCLE.value, False)
+                return (data.id, data.get_simple_label(), get_scenarios(data), _EntityType.CYCLE.value, False)
             elif isinstance(data, Scenario):
                 return (data.id, data.get_simple_label(), None, _EntityType.SCENARIO.value, data.is_primary)
         return None
@@ -172,7 +175,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
         with self.lock:
             if self.scenarios_base_level is None:
                 self.scenarios_base_level = []
-                for cycle, scenarios in tp.get_cycles_scenarios().items():
+                for cycle, scenarios in get_cycles_scenarios().items():
                     if cycle is None:
                         self.scenarios_base_level.extend(scenarios)
                     else:
@@ -189,14 +192,14 @@ class _GuiCoreContext(CoreEventConsumerBase):
         if not id:
             return None
         try:
-            return tp.get(id)
+            return core_get(id)
         except Exception:
             return None
 
     def get_scenario_configs(self):
         with self.lock:
             if self.scenario_configs is None:
-                configs = tp.Config.scenarios
+                configs = Config.scenarios
                 if isinstance(configs, dict):
                     self.scenario_configs = [(id, f"{c.id}") for id, c in configs.items() if id != "default"]
             return self.scenario_configs
@@ -221,14 +224,14 @@ class _GuiCoreContext(CoreEventConsumerBase):
             scenario_id = data.get(_GuiCoreContext.__PROP_ENTITY_ID)
             if delete:
                 try:
-                    tp.delete(scenario_id)
+                    core_delete(scenario_id)
                 except Exception as e:
                     state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Error deleting Scenario. {e}")
             else:
-                scenario = tp.get(scenario_id)
+                scenario = core_get(scenario_id)
         else:
             config_id = data.get(_GuiCoreContext.__PROP_SCENARIO_CONFIG_ID)
-            scenario_config = tp.Config.scenarios.get(config_id)
+            scenario_config = Config.scenarios.get(config_id)
             if scenario_config is None:
                 state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Invalid configuration id ({config_id})")
                 return
@@ -239,7 +242,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Invalid date ({date_str}).{e}")
                 return
             try:
-                scenario = tp.create_scenario(scenario_config, date, name)
+                scenario = create_scenario(scenario_config, date, name)
             except Exception as e:
                 state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Error creating Scenario. {e}")
         if scenario:
@@ -265,13 +268,13 @@ class _GuiCoreContext(CoreEventConsumerBase):
             return
         data = args[0]
         entity_id = data.get(_GuiCoreContext.__PROP_ENTITY_ID)
-        entity: t.Union[Scenario, Pipeline] = tp.get(entity_id)
+        entity: t.Union[Scenario, Pipeline] = core_get(entity_id)
         if entity:
             try:
                 if isinstance(entity, Scenario):
                     primary = data.get(_GuiCoreContext.__PROP_SCENARIO_PRIMARY)
                     if primary is True:
-                        tp.set_primary(entity)
+                        set_primary(entity)
                 with entity as ent:
                     if isinstance(ent, Scenario):
                         tags = data.get(_GuiCoreContext.__PROP_SCENARIO_TAGS)
@@ -302,10 +305,10 @@ class _GuiCoreContext(CoreEventConsumerBase):
             return
         data = args[0]
         entity_id = data.get(_GuiCoreContext.__PROP_ENTITY_ID)
-        entity = tp.get(entity_id)
+        entity = core_get(entity_id)
         if entity:
             try:
-                tp.submit(entity)
+                core_submit(entity)
                 state.assign(_GuiCoreContext._SCENARIO_VIZ_ERROR_VAR, "")
             except Exception as e:
                 state.assign(_GuiCoreContext._SCENARIO_VIZ_ERROR_VAR, f"Error submitting entity. {e}")
@@ -314,7 +317,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
         with self.lock:
             if self.data_nodes_base_level is None:
                 self.data_nodes_base_level = _GuiCoreContext.__get_data_nodes()
-                for cycle, scenarios in tp.get_cycles_scenarios().items():
+                for cycle, scenarios in get_cycles_scenarios().items():
                     if cycle is None:
                         self.data_nodes_base_level.extend(scenarios)
                     else:
@@ -328,16 +331,16 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 return True
             return False if id is None or dn.owner_id is None else dn.owner_id == id
 
-        return [x for x in tp.get_data_nodes() if from_parent(x)]
+        return [x for x in get_data_nodes() if from_parent(x)]
 
     @staticmethod
     def data_node_adapter(data):
-        if hasattr(data, "id") and tp.get(data.id) is not None:
+        if hasattr(data, "id") and core_get(data.id) is not None:
             if isinstance(data, Cycle):
                 return (
                     data.id,
                     data.get_simple_label(),
-                    _GuiCoreContext.__get_data_nodes(data.id) + tp.get_scenarios(data),
+                    _GuiCoreContext.__get_data_nodes(data.id) + get_scenarios(data),
                     _EntityType.CYCLE.value,
                     False,
                 )
@@ -345,7 +348,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 return (
                     data.id,
                     data.get_simple_label(),
-                    _GuiCoreContext.__get_data_nodes(data.id) + [tp.get(p) for p in data._pipelines],
+                    _GuiCoreContext.__get_data_nodes(data.id) + [core_get(p) for p in data._pipelines],
                     _EntityType.SCENARIO.value,
                     data.is_primary,
                 )

+ 1 - 1
src/taipy/gui_core/__init__.py

@@ -9,4 +9,4 @@
 # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # specific language governing permissions and limitations under the License.
 
-from _init import *
+from ._init import *