Selaa lähdekoodia

Property to not show the creation dialog (#725)

* Property to not show a creation dialog
scenario to limit datanode_selector list

* mypy and fix tests

* mypy

* fix tests

* Fab's comment

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 1 vuosi sitten
vanhempi
säilyke
413be6ec14

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 328 - 220
frontend/taipy/package-lock.json


+ 31 - 26
frontend/taipy/src/ScenarioSelector.tsx

@@ -84,6 +84,7 @@ interface ScenarioSelectorProps {
     className?: string;
     className?: string;
     dynamicClassName?: string;
     dynamicClassName?: string;
     showPins?: boolean;
     showPins?: boolean;
+    showDialog?: boolean;
 }
 }
 
 
 interface ScenarioEditDialogProps {
 interface ScenarioEditDialogProps {
@@ -277,7 +278,7 @@ const ScenarioEditDialog = ({ scenario, submit, open, actionEdit, configs, close
                                         <DatePicker
                                         <DatePicker
                                             label="Date"
                                             label="Date"
                                             value={new Date(form.values.date)}
                                             value={new Date(form.values.date)}
-                                            onChange={(date) => form.setFieldValue("date", date?.toISOString())}
+                                            onChange={(date?:Date|null) => form.setFieldValue("date", date?.toISOString())}
                                             disabled={actionEdit}
                                             disabled={actionEdit}
                                         />
                                         />
                                     </LocalizationProvider>
                                     </LocalizationProvider>
@@ -410,7 +411,7 @@ const ScenarioEditDialog = ({ scenario, submit, open, actionEdit, configs, close
 };
 };
 
 
 const ScenarioSelector = (props: ScenarioSelectorProps) => {
 const ScenarioSelector = (props: ScenarioSelectorProps) => {
-    const { showAddButton = true, propagate = true, showPins = false } = props;
+    const { showAddButton = true, propagate = true, showPins = false, showDialog = true } = props;
     const [open, setOpen] = useState(false);
     const [open, setOpen] = useState(false);
     const [actionEdit, setActionEdit] = useState<boolean>(false);
     const [actionEdit, setActionEdit] = useState<boolean>(false);
 
 
@@ -419,32 +420,9 @@ const ScenarioSelector = (props: ScenarioSelectorProps) => {
     const dispatch = useDispatch();
     const dispatch = useDispatch();
     const module = useModule();
     const module = useModule();
 
 
-    const onDialogOpen = useCallback(() => {
-        setOpen(true);
-        setActionEdit(false);
-    }, []);
-
-    const onDialogClose = useCallback(() => {
-        setOpen(false);
-        setActionEdit(false);
-    }, []);
-
-    const openEditDialog = useCallback(
-        (e: React.MouseEvent<HTMLElement>) => {
-            e.stopPropagation();
-            const { id: scenId } = e.currentTarget?.dataset || {};
-            scenId &&
-                props.onScenarioSelect &&
-                dispatch(createSendActionNameAction(props.id, module, props.onScenarioSelect, scenId));
-            setOpen(true);
-            setActionEdit(true);
-        },
-        [props.onScenarioSelect, props.id, dispatch, module]
-    );
-
     const onSubmit = useCallback(
     const onSubmit = useCallback(
         (...values: unknown[]) => {
         (...values: unknown[]) => {
-            dispatch(createSendActionNameAction(props.id, module, props.onScenarioCrud, ...values, props.onCreation));
+            dispatch(createSendActionNameAction(props.id, module, props.onScenarioCrud, props.onCreation, ...values));
             if (values.length > 1 && values[1]) {
             if (values.length > 1 && values[1]) {
                 // delete requested => unselect current node
                 // delete requested => unselect current node
                 const lovVar = getUpdateVar(props.updateVars, "scenarios");
                 const lovVar = getUpdateVar(props.updateVars, "scenarios");
@@ -466,6 +444,33 @@ const ScenarioSelector = (props: ScenarioSelectorProps) => {
         ]
         ]
     );
     );
 
 
+    const onDialogOpen = useCallback(() => {
+        if (showDialog) {
+            setOpen(true);
+            setActionEdit(false);
+        } else {
+            onSubmit(false, false, {}, false);
+        }
+    }, [showDialog, onSubmit]);
+
+    const onDialogClose = useCallback(() => {
+        setOpen(false);
+        setActionEdit(false);
+    }, []);
+
+    const openEditDialog = useCallback(
+        (e: React.MouseEvent<HTMLElement>) => {
+            e.stopPropagation();
+            const { id: scenId } = e.currentTarget?.dataset || {};
+            scenId &&
+                props.onScenarioSelect &&
+                dispatch(createSendActionNameAction(props.id, module, props.onScenarioSelect, scenId));
+            setOpen(true);
+            setActionEdit(true);
+        },
+        [props.onScenarioSelect, props.id, dispatch, module]
+    );
+
     const EditScenario = useCallback(
     const EditScenario = useCallback(
         (props: EditProps) => (
         (props: EditProps) => (
             <Tooltip title="Edit Scenario">
             <Tooltip title="Edit Scenario">

+ 12 - 2
taipy/gui_core/_GuiCoreLib.py

@@ -16,7 +16,12 @@ from taipy.gui import Gui, State
 from taipy.gui.extension import Element, ElementLibrary, ElementProperty, PropertyType
 from taipy.gui.extension import Element, ElementLibrary, ElementProperty, PropertyType
 
 
 from ..version import _get_version
 from ..version import _get_version
-from ._adapters import _GuiCoreDatanodeAdapter, _GuiCoreScenarioAdapter, _GuiCoreScenarioDagAdapter
+from ._adapters import (
+    _GuiCoreDatanodeAdapter,
+    _GuiCoreScenarioAdapter,
+    _GuiCoreScenarioDagAdapter,
+    _GuiCoreScenarioNoUpdate,
+)
 from ._context import _GuiCoreContext
 from ._context import _GuiCoreContext
 
 
 
 
@@ -41,6 +46,7 @@ class _GuiCore(ElementLibrary):
                 "class_name": ElementProperty(PropertyType.dynamic_string),
                 "class_name": ElementProperty(PropertyType.dynamic_string),
                 "show_pins": ElementProperty(PropertyType.boolean, False),
                 "show_pins": ElementProperty(PropertyType.boolean, False),
                 "on_creation": ElementProperty(PropertyType.function),
                 "on_creation": ElementProperty(PropertyType.function),
+                "show_dialog": ElementProperty(PropertyType.boolean, True),
             },
             },
             inner_properties={
             inner_properties={
                 "scenarios": ElementProperty(PropertyType.lov, f"{{{__CTX_VAR_NAME}.get_scenarios()}}"),
                 "scenarios": ElementProperty(PropertyType.lov, f"{{{__CTX_VAR_NAME}.get_scenarios()}}"),
@@ -109,9 +115,13 @@ class _GuiCore(ElementLibrary):
                 "height": ElementProperty(PropertyType.string, "50vh"),
                 "height": ElementProperty(PropertyType.string, "50vh"),
                 "class_name": ElementProperty(PropertyType.dynamic_string),
                 "class_name": ElementProperty(PropertyType.dynamic_string),
                 "show_pins": ElementProperty(PropertyType.boolean, True),
                 "show_pins": ElementProperty(PropertyType.boolean, True),
+                _GuiCoreContext._DATANODE_SEL_SCENARIO_PROP: ElementProperty(_GuiCoreScenarioNoUpdate),
             },
             },
             inner_properties={
             inner_properties={
-                "datanodes": ElementProperty(PropertyType.lov, f"{{{__CTX_VAR_NAME}.get_datanodes_tree()}}"),
+                "datanodes": ElementProperty(
+                    PropertyType.lov,
+                    f"{{{__CTX_VAR_NAME}.get_datanodes_tree(<tp:prop:{_GuiCoreContext._DATANODE_SEL_SCENARIO_PROP}>)}}",
+                ),
                 "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
                 "core_changed": ElementProperty(PropertyType.broadcast, _GuiCoreContext._CORE_CHANGED_NAME),
                 "type": ElementProperty(PropertyType.inner, __DATANODE_ADAPTER),
                 "type": ElementProperty(PropertyType.inner, __DATANODE_ADAPTER),
             },
             },

+ 6 - 0
taipy/gui_core/_adapters.py

@@ -145,6 +145,12 @@ class _GuiCoreScenarioDagAdapter(_TaipyBase):
         return _TaipyBase._HOLDER_PREFIX + "ScG"
         return _TaipyBase._HOLDER_PREFIX + "ScG"
 
 
 
 
+class _GuiCoreScenarioNoUpdate(_TaipyBase, _DoNotUpdate):
+    @staticmethod
+    def get_hash():
+        return _TaipyBase._HOLDER_PREFIX + "ScN"
+
+
 class _GuiCoreDatanodeAdapter(_TaipyBase):
 class _GuiCoreDatanodeAdapter(_TaipyBase):
     __INNER_PROPS = ["name"]
     __INNER_PROPS = ["name"]
 
 

+ 81 - 78
taipy/gui_core/_context.py

@@ -33,6 +33,8 @@ from taipy.core import (
     ScenarioId,
     ScenarioId,
     Sequence,
     Sequence,
     SequenceId,
     SequenceId,
+    Submission,
+    SubmissionId,
     cancel_job,
     cancel_job,
     create_scenario,
     create_scenario,
     delete_job,
     delete_job,
@@ -53,8 +55,6 @@ from taipy.core.data._abstract_tabular import _AbstractTabularDataNode
 from taipy.core.notification import CoreEventConsumerBase, EventEntityType
 from taipy.core.notification import CoreEventConsumerBase, EventEntityType
 from taipy.core.notification.event import Event, EventOperation
 from taipy.core.notification.event import Event, EventOperation
 from taipy.core.notification.notifier import Notifier
 from taipy.core.notification.notifier import Notifier
-from taipy.core.submission._submission_manager_factory import _SubmissionManagerFactory
-from taipy.core.submission.submission import Submission
 from taipy.core.submission.submission_status import SubmissionStatus
 from taipy.core.submission.submission_status import SubmissionStatus
 from taipy.gui import Gui, State
 from taipy.gui import Gui, State
 from taipy.gui._warnings import _warn
 from taipy.gui._warnings import _warn
@@ -63,24 +63,6 @@ from taipy.gui.gui import _DoNotUpdate
 from ._adapters import _EntityType
 from ._adapters import _EntityType
 
 
 
 
-class _SubmissionDetails:
-    def __init__(
-        self,
-        client_id: str,
-        module_context: str,
-        callback: t.Callable,
-        submission_status: SubmissionStatus,
-    ) -> None:
-        self.client_id = client_id
-        self.module_context = module_context
-        self.callback = callback
-        self.submission_status = submission_status
-
-    def set_submission_status(self, submission_status: SubmissionStatus):
-        self.submission_status = submission_status
-        return self
-
-
 class _GuiCoreContext(CoreEventConsumerBase):
 class _GuiCoreContext(CoreEventConsumerBase):
     __PROP_ENTITY_ID = "id"
     __PROP_ENTITY_ID = "id"
     __PROP_ENTITY_COMMENT = "comment"
     __PROP_ENTITY_COMMENT = "comment"
@@ -102,6 +84,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
     _DATANODE_VIZ_DATA_ID_VAR = "gui_core_dv_data_id"
     _DATANODE_VIZ_DATA_ID_VAR = "gui_core_dv_data_id"
     _DATANODE_VIZ_DATA_CHART_ID_VAR = "gui_core_dv_data_chart_id"
     _DATANODE_VIZ_DATA_CHART_ID_VAR = "gui_core_dv_data_chart_id"
     _DATANODE_VIZ_DATA_NODE_PROP = "data_node"
     _DATANODE_VIZ_DATA_NODE_PROP = "data_node"
+    _DATANODE_SEL_SCENARIO_PROP = "scenario"
 
 
     def __init__(self, gui: Gui) -> None:
     def __init__(self, gui: Gui) -> None:
         self.gui = gui
         self.gui = gui
@@ -109,7 +92,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
         self.data_nodes_by_owner: t.Optional[t.Dict[t.Optional[str], DataNode]] = None
         self.data_nodes_by_owner: t.Optional[t.Dict[t.Optional[str], DataNode]] = None
         self.scenario_configs: t.Optional[t.List[t.Tuple[str, str]]] = None
         self.scenario_configs: t.Optional[t.List[t.Tuple[str, str]]] = None
         self.jobs_list: t.Optional[t.List[Job]] = None
         self.jobs_list: t.Optional[t.List[Job]] = None
-        self.client_submission: t.Dict[str, _SubmissionDetails] = dict()
+        self.client_submission: t.Dict[str, SubmissionStatus] = dict()
         # register to taipy core notification
         # register to taipy core notification
         reg_id, reg_queue = Notifier.register()
         reg_id, reg_queue = Notifier.register()
         # locks
         # locks
@@ -121,9 +104,6 @@ class _GuiCoreContext(CoreEventConsumerBase):
 
 
     def process_event(self, event: Event):
     def process_event(self, event: Event):
         if event.entity_type == EventEntityType.SCENARIO:
         if event.entity_type == EventEntityType.SCENARIO:
-            if event.operation == EventOperation.SUBMISSION:
-                self.scenario_status_callback(event.attribute_name)
-                return
             self.scenario_refresh(
             self.scenario_refresh(
                 event.entity_id
                 event.entity_id
                 if event.operation != EventOperation.DELETION and is_readable(t.cast(ScenarioId, event.entity_id))
                 if event.operation != EventOperation.DELETION and is_readable(t.cast(ScenarioId, event.entity_id))
@@ -147,6 +127,15 @@ class _GuiCoreContext(CoreEventConsumerBase):
         elif event.entity_type == EventEntityType.JOB:
         elif event.entity_type == EventEntityType.JOB:
             with self.lock:
             with self.lock:
                 self.jobs_list = None
                 self.jobs_list = None
+            if event.operation == EventOperation.UPDATE:
+                try:
+                    job_entity = t.cast(Job, core_get(str(event.entity_id)))
+                    self.gui._broadcast(
+                        _GuiCoreContext._CORE_CHANGED_NAME,
+                        {"task": {"id": job_entity.task.id, "status": job_entity.status.name}},
+                    )
+                except Exception as e:
+                    _warn(f"Access to sequence {event.entity_id} failed", e)
         elif event.entity_type == EventEntityType.SUBMISSION:
         elif event.entity_type == EventEntityType.SUBMISSION:
             self.scenario_status_callback(event.entity_id)
             self.scenario_status_callback(event.entity_id)
         elif event.entity_type == EventEntityType.DATA_NODE:
         elif event.entity_type == EventEntityType.DATA_NODE:
@@ -167,14 +156,14 @@ class _GuiCoreContext(CoreEventConsumerBase):
         )
         )
 
 
     def scenario_status_callback(self, submission_id: t.Optional[str]):
     def scenario_status_callback(self, submission_id: t.Optional[str]):
-        if not submission_id or not is_readable_submission(submission_id):
+        if not submission_id or not is_readable(t.cast(SubmissionId, submission_id)):
             return
             return
         try:
         try:
-            sub_details: t.Optional[_SubmissionDetails] = self.client_submission.get(submission_id)
-            if not sub_details:
+            last_status = self.client_submission.get(submission_id)
+            if not last_status:
                 return
                 return
 
 
-            submission = core_get_submission(submission_id)
+            submission = t.cast(Submission, core_get(submission_id))
             if not submission or not submission.entity_id:
             if not submission or not submission.entity_id:
                 return
                 return
 
 
@@ -183,13 +172,19 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 return
                 return
 
 
             new_status = submission.submission_status
             new_status = submission.submission_status
-            if sub_details.submission_status != new_status:
+            if last_status != new_status:
                 # callback
                 # callback
+                submission_name = submission.properties.get("on_submission")
+                if not submission_name:
+                    return
+                submission_fn = self.gui._get_user_function(submission_name)
+                if not callable(submission_fn):
+                    return
                 self.gui._call_user_callback(
                 self.gui._call_user_callback(
-                    sub_details.client_id,
-                    sub_details.callback,
+                    submission.properties.get("client_id"),
+                    submission_fn,
                     [entity, {"submission_status": new_status.name}],
                     [entity, {"submission_status": new_status.name}],
-                    sub_details.module_context,
+                    submission.properties.get("module_context"),
                 )
                 )
             with self.submissions_lock:
             with self.submissions_lock:
                 if new_status in (
                 if new_status in (
@@ -199,7 +194,7 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 ):
                 ):
                     self.client_submission.pop(submission_id, None)
                     self.client_submission.pop(submission_id, None)
                 else:
                 else:
-                    self.client_submission[submission_id] = sub_details.set_submission_status(new_status)
+                    self.client_submission[submission_id] = new_status
 
 
         except Exception as e:
         except Exception as e:
             _warn(f"Submission ({submission_id}) is not available", e)
             _warn(f"Submission ({submission_id}) is not available", e)
@@ -278,15 +273,16 @@ class _GuiCoreContext(CoreEventConsumerBase):
         if (
         if (
             args is None
             args is None
             or not isinstance(args, list)
             or not isinstance(args, list)
-            or len(args) < 3
-            or not isinstance(args[0], bool)
+            or len(args) < 4
             or not isinstance(args[1], bool)
             or not isinstance(args[1], bool)
-            or not isinstance(args[2], dict)
+            or not isinstance(args[2], bool)
+            or not isinstance(args[3], dict)
         ):
         ):
             return
             return
-        update = args[0]
-        delete = args[1]
-        data = args[2]
+        update = args[1]
+        delete = args[2]
+        data = args[3]
+        with_dialog = True if len(args) < 5 else bool(args[4])
         scenario = None
         scenario = None
 
 
         name = data.get(_GuiCoreContext.__PROP_ENTITY_NAME)
         name = data.get(_GuiCoreContext.__PROP_ENTITY_NAME)
@@ -309,21 +305,27 @@ class _GuiCoreContext(CoreEventConsumerBase):
                     return
                     return
                 scenario = core_get(scenario_id)
                 scenario = core_get(scenario_id)
         else:
         else:
-            config_id = data.get(_GuiCoreContext.__PROP_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
-            date_str = data.get(_GuiCoreContext.__PROP_DATE)
-            try:
-                date = parser.parse(date_str) if isinstance(date_str, str) else None
-            except Exception as e:
-                state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Invalid date ({date_str}).{e}")
-                return
+            if with_dialog:
+                config_id = data.get(_GuiCoreContext.__PROP_CONFIG_ID)
+                scenario_config = Config.scenarios.get(config_id)
+                if with_dialog and scenario_config is None:
+                    state.assign(
+                        _GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Invalid configuration id ({config_id})"
+                    )
+                    return
+                date_str = data.get(_GuiCoreContext.__PROP_DATE)
+                try:
+                    date = parser.parse(date_str) if isinstance(date_str, str) else None
+                except Exception as e:
+                    state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Invalid date ({date_str}).{e}")
+                    return
+            else:
+                scenario_config = None
+                date = None
             scenario_id = None
             scenario_id = None
             try:
             try:
                 gui: Gui = state._gui
                 gui: Gui = state._gui
-                on_creation = args[3] if len(args) > 3 and isinstance(args[3], str) else None
+                on_creation = args[0] if isinstance(args[0], str) else None
                 on_creation_function = gui._get_user_function(on_creation) if on_creation else None
                 on_creation_function = gui._get_user_function(on_creation) if on_creation else None
                 if callable(on_creation_function):
                 if callable(on_creation_function):
                     try:
                     try:
@@ -361,6 +363,17 @@ class _GuiCoreContext(CoreEventConsumerBase):
                         return
                         return
                 elif on_creation is not None:
                 elif on_creation is not None:
                     _warn(f"on_creation(): '{on_creation}' is not a function.")
                     _warn(f"on_creation(): '{on_creation}' is not a function.")
+                elif not with_dialog:
+                    if len(Config.scenarios) == 2:
+                        scenario_config = [sc for k, sc in Config.scenarios.items() if k != "default"][0]
+                    else:
+                        state.assign(
+                            _GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR,
+                            "Error creating Scenario: only one scenario config needed "
+                            + f"({len(Config.scenarios) - 1}) found.",
+                        )
+                        return
+
                 scenario = create_scenario(scenario_config, date, name)
                 scenario = create_scenario(scenario_config, date, name)
                 scenario_id = scenario.id
                 scenario_id = scenario.id
             except Exception as e:
             except Exception as e:
@@ -431,22 +444,19 @@ class _GuiCoreContext(CoreEventConsumerBase):
         entity = core_get(entity_id)
         entity = core_get(entity_id)
         if entity:
         if entity:
             try:
             try:
-                submission_entity = core_submit(entity)
-                if submission_cb := data.get("on_submission_change"):
-                    submission_fn = self.gui._get_user_function(submission_cb)
-                    if callable(submission_fn):
-                        client_id = self.gui._get_client_id()
-                        module_context = self.gui._get_locals_context()
-                        with self.submissions_lock:
-                            self.client_submission[submission_entity.id] = _SubmissionDetails(
-                                client_id,
-                                module_context,
-                                submission_fn,
-                                submission_entity.submission_status,
-                            )
-                    else:
-                        _warn(f"on_submission_change(): '{submission_cb}' is not a valid function.")
-                self.scenario_status_callback(submission_entity.id)
+                on_submission = data.get("on_submission_change")
+                submission_entity = core_submit(
+                    entity,
+                    on_submission=on_submission,
+                    client_id=self.gui._get_client_id(),
+                    module_context=self.gui._get_locals_context(),
+                )
+                if on_submission:
+                    with self.submissions_lock:
+                        self.client_submission[submission_entity.id] = submission_entity.submission_status
+                    if Config.core.mode == "development":
+                        self.client_submission[submission_entity.id] = SubmissionStatus.SUBMITTED
+                        self.scenario_status_callback(submission_entity.id)
                 state.assign(_GuiCoreContext._SCENARIO_VIZ_ERROR_VAR, "")
                 state.assign(_GuiCoreContext._SCENARIO_VIZ_ERROR_VAR, "")
             except Exception as e:
             except Exception as e:
                 state.assign(_GuiCoreContext._SCENARIO_VIZ_ERROR_VAR, f"Error submitting entity. {e}")
                 state.assign(_GuiCoreContext._SCENARIO_VIZ_ERROR_VAR, f"Error submitting entity. {e}")
@@ -457,10 +467,12 @@ class _GuiCoreContext(CoreEventConsumerBase):
             for dn in get_data_nodes():
             for dn in get_data_nodes():
                 self.data_nodes_by_owner[dn.owner_id].append(dn)
                 self.data_nodes_by_owner[dn.owner_id].append(dn)
 
 
-    def get_datanodes_tree(self):
+    def get_datanodes_tree(self, scenario: t.Optional[Scenario]):
         with self.lock:
         with self.lock:
             self.__do_datanodes_tree()
             self.__do_datanodes_tree()
-        return self.data_nodes_by_owner.get(None, []) + self.get_scenarios()
+        return (
+            self.data_nodes_by_owner.get(scenario.id if scenario else None, []) if self.data_nodes_by_owner else []
+        ) + (self.get_scenarios() if not scenario else [])
 
 
     def data_node_adapter(self, data):
     def data_node_adapter(self, data):
         try:
         try:
@@ -839,12 +851,3 @@ class _GuiCoreContext(CoreEventConsumerBase):
             state.assign(_GuiCoreContext._DATANODE_VIZ_DATA_ID_VAR, data_id)
             state.assign(_GuiCoreContext._DATANODE_VIZ_DATA_ID_VAR, data_id)
         elif chart_id := data.get("chart_id"):
         elif chart_id := data.get("chart_id"):
             state.assign(_GuiCoreContext._DATANODE_VIZ_DATA_CHART_ID_VAR, chart_id)
             state.assign(_GuiCoreContext._DATANODE_VIZ_DATA_CHART_ID_VAR, chart_id)
-
-
-# TODO remove when Submission is supported by Core API
-def is_readable_submission(id: str):
-    return _SubmissionManagerFactory._build_manager()._is_readable(t.cast(Submission, id))
-
-
-def core_get_submission(id: str):
-    return _SubmissionManagerFactory._build_manager()._get(id)

+ 11 - 0
taipy/gui_core/viselements.json

@@ -67,6 +67,12 @@
                       "type": "Callback",
                       "type": "Callback",
                       "doc": "The name of the function that is triggered when a scenario is about to be created.<br/><br/>All the parameters of that function are optional:\n<ul>\n<li>state (<code>State^</code>): the state instance.</li>\n<li>id (str): the identifier of the scenario selector.</li>\n<li>payload (dict): the details on this callback's invocation.<br/>\nThis dictionary has the following keys:\n<ul>\n<li>config: the name of the selected scenario configuration.</li>\n<li>date: the creation date for the new scenario.</li>\n<li>label: the user-specified label.</li>\n<li>properties: a dictionary containing all the user-defined custom properties.</li>\n</ul>\n</li>\n<li>The callback function can return a scenario, a string containing an error message (a scenario will not be created), or None (then a new scenario is created with the user parameters).</li>\n</ul>",
                       "doc": "The name of the function that is triggered when a scenario is about to be created.<br/><br/>All the parameters of that function are optional:\n<ul>\n<li>state (<code>State^</code>): the state instance.</li>\n<li>id (str): the identifier of the scenario selector.</li>\n<li>payload (dict): the details on this callback's invocation.<br/>\nThis dictionary has the following keys:\n<ul>\n<li>config: the name of the selected scenario configuration.</li>\n<li>date: the creation date for the new scenario.</li>\n<li>label: the user-specified label.</li>\n<li>properties: a dictionary containing all the user-defined custom properties.</li>\n</ul>\n</li>\n<li>The callback function can return a scenario, a string containing an error message (a scenario will not be created), or None (then a new scenario is created with the user parameters).</li>\n</ul>",
                       "signature": [["state", "State"], ["id", "str"], ["payload", "dict"]]
                       "signature": [["state", "State"], ["id", "str"], ["payload", "dict"]]
+                    },
+                    {
+                        "name": "show_dialog",
+                        "type": "bool",
+                        "default_value": "True",
+                        "doc": "If True, a dialog is shown when the user click on the 'Add scenario' button."
                     }
                     }
                 ]
                 ]
             }
             }
@@ -260,6 +266,11 @@
                         "type": "bool",
                         "type": "bool",
                         "default_value": "True",
                         "default_value": "True",
                         "doc": "If True, a pin is shown on each item of the selector and allows to restrict the number of displayed items."
                         "doc": "If True, a pin is shown on each item of the selector and allows to restrict the number of displayed items."
+                    },
+                    {
+                        "name": "scenario",
+                        "type": "dynamic(Scenario)",
+                        "doc": "If the <code>Scenario^</code> is set, the selector will only show datanodes owned by this scenario."
                     }
                     }
                 ]
                 ]
             }
             }

+ 2 - 0
tests/gui_core/test_context_is_deletable.py

@@ -58,6 +58,7 @@ class TestGuiCoreContext_is_deletable:
                 "",
                 "",
                 {
                 {
                     "args": [
                     "args": [
+                        "",
                         True,
                         True,
                         True,
                         True,
                         {"name": "name", "id": a_scenario.id},
                         {"name": "name", "id": a_scenario.id},
@@ -75,6 +76,7 @@ class TestGuiCoreContext_is_deletable:
                     "",
                     "",
                     {
                     {
                         "args": [
                         "args": [
+                            "",
                             True,
                             True,
                             True,
                             True,
                             {"name": "name", "id": a_scenario.id},
                             {"name": "name", "id": a_scenario.id},

+ 2 - 0
tests/gui_core/test_context_is_editable.py

@@ -57,6 +57,7 @@ class TestGuiCoreContext_is_editable:
                 "",
                 "",
                 {
                 {
                     "args": [
                     "args": [
+                        "",
                         True,
                         True,
                         False,
                         False,
                         {"name": "name", "id": a_scenario.id},
                         {"name": "name", "id": a_scenario.id},
@@ -72,6 +73,7 @@ class TestGuiCoreContext_is_editable:
                     "",
                     "",
                     {
                     {
                         "args": [
                         "args": [
+                            "",
                             True,
                             True,
                             False,
                             False,
                             {"name": "name", "id": a_scenario.id},
                             {"name": "name", "id": a_scenario.id},

+ 6 - 8
tests/gui_core/test_context_is_readable.py

@@ -17,7 +17,7 @@ from taipy.core import Job, JobId, Scenario, Task
 from taipy.core.data.pickle import PickleDataNode
 from taipy.core.data.pickle import PickleDataNode
 from taipy.core.submission.submission import Submission
 from taipy.core.submission.submission import Submission
 from taipy.gui import Gui
 from taipy.gui import Gui
-from taipy.gui_core._context import _GuiCoreContext, _SubmissionDetails
+from taipy.gui_core._context import _GuiCoreContext
 
 
 a_scenario = Scenario("scenario_config_id", None, {}, sequences={"sequence": {}})
 a_scenario = Scenario("scenario_config_id", None, {}, sequences={"sequence": {}})
 a_task = Task("task_config_id", {}, print)
 a_task = Task("task_config_id", {}, print)
@@ -83,6 +83,7 @@ class TestGuiCoreContext_is_readable:
                 "",
                 "",
                 {
                 {
                     "args": [
                     "args": [
+                        "",
                         True,
                         True,
                         False,
                         False,
                         {"name": "name", "id": a_scenario.id},
                         {"name": "name", "id": a_scenario.id},
@@ -98,6 +99,7 @@ class TestGuiCoreContext_is_readable:
                     "",
                     "",
                     {
                     {
                         "args": [
                         "args": [
+                            "",
                             True,
                             True,
                             False,
                             False,
                             {"name": "name", "id": a_scenario.id},
                             {"name": "name", "id": a_scenario.id},
@@ -141,18 +143,14 @@ class TestGuiCoreContext_is_readable:
                 assert str(assign.call_args.args[1]).endswith("is not readable.")
                 assert str(assign.call_args.args[1]).endswith("is not readable.")
 
 
     def test_scenario_status_callback(self):
     def test_scenario_status_callback(self):
-        with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget, patch(
-            "taipy.gui_core._context.core_get_submission", side_effect=mock_core_get
-        ):
+        with patch("taipy.gui_core._context.core_get", side_effect=mock_core_get) as mockget:
             mockget.reset_mock()
             mockget.reset_mock()
             gui_core_context = _GuiCoreContext(Mock())
             gui_core_context = _GuiCoreContext(Mock())
 
 
             def sub_cb():
             def sub_cb():
                 return True
                 return True
 
 
-            gui_core_context.client_submission[a_submission.id] = _SubmissionDetails(
-                "client_id", "", sub_cb, a_submission
-            )
+            gui_core_context.client_submission[a_submission.id] = a_submission.submission_status
             gui_core_context.scenario_status_callback(a_submission.id)
             gui_core_context.scenario_status_callback(a_submission.id)
             mockget.assert_called()
             mockget.assert_called()
             found = False
             found = False
@@ -163,7 +161,7 @@ class TestGuiCoreContext_is_readable:
             assert found is True
             assert found is True
             mockget.reset_mock()
             mockget.reset_mock()
 
 
-            with patch("taipy.gui_core._context.is_readable_submission", side_effect=mock_is_readable_false):
+            with patch("taipy.gui_core._context.is_readable", side_effect=mock_is_readable_false):
                 gui_core_context.scenario_status_callback(a_submission.id)
                 gui_core_context.scenario_status_callback(a_submission.id)
                 mockget.assert_not_called()
                 mockget.assert_not_called()
 
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä