浏览代码

Fix property loosing keyboard focus (#216) (#217)

* #216 fix visu property key focus
- handle property key rename

* flake8

* #167 item selection visual clue

* remove default from scenario config

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 1 年之前
父节点
当前提交
7054429536
共有 3 个文件被更改,包括 38 次插入36 次删除
  1. 31 26
      gui/src/ScenarioViewer.tsx
  2. 0 7
      gui/src/utils.ts
  3. 7 3
      src/taipy/gui_core/GuiCoreLib.py

+ 31 - 26
gui/src/ScenarioViewer.tsx

@@ -35,9 +35,20 @@ import {
     useModule,
 } from "taipy-gui";
 
-import { FlagSx, Property, ScFProps, ScenarioFull, ScenarioFullLength, useClassNames } from "./utils";
+import { FlagSx, ScFProps, ScenarioFull, ScenarioFullLength, useClassNames } from "./utils";
 import ConfirmDialog from "./utils/ConfirmDialog";
 
+type Property = {
+    id: string;
+    key: string;
+    value: string;
+};
+type ScenarioEditPayload = {
+    id: string;
+    properties?: Property[];
+    deleted_properties?: Array<Partial<Property>>;
+};
+
 interface ScenarioViewerProps {
     id?: string;
     expandable?: boolean;
@@ -353,14 +364,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
         const { id = "", name = "" } = e.currentTarget.parentElement?.parentElement?.dataset || {};
         if (name) {
             if (id) {
-                setProperties((ps) =>
-                    ps.map((p) => {
-                        if (id == p.id) {
-                            p[name as keyof Property] = e.target.value;
-                        }
-                        return p;
-                    })
-                );
+                setProperties((ps) => ps.map((p) => (id === p.id ? { ...p, [name]: e.target.value } : p)));
             } else {
                 setNewProp((np) => ({ ...np, [name]: e.target.value }));
             }
@@ -373,10 +377,14 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
             if (isScenario) {
                 const { id: propId = "" } = e.currentTarget.dataset || {};
                 const property = propId ? properties.find((p) => p.id === propId) : newProp;
-                property &&
-                    dispatch(
-                        createSendActionNameAction(id, module, props.onEdit, { id: scId, properties: [property] })
-                    );
+                if (property) {
+                    const oldId = property.id;
+                    const payload: ScenarioEditPayload = { id: scId, properties: [property] };
+                    if (oldId && oldId != property.key) {
+                        payload.deleted_properties = [{ key: oldId }];
+                    }
+                    dispatch(createSendActionNameAction(id, module, props.onEdit, payload));
+                }
                 setNewProp((np) => ({ ...np, key: "", value: "" }));
                 setFocusName("");
             }
@@ -388,24 +396,21 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
             e.stopPropagation();
             if (isScenario) {
                 const { id: propId = "" } = e.currentTarget.dataset || {};
-                const propertyIdx = properties.findIndex((p) => p.id === propId);
-                propertyIdx > -1 &&
-                    propertyIdx < scProperties.length &&
+                const property = scProperties.find(([key]) => key === propId);
+                property &&
                     setProperties((ps) =>
-                        ps.map((p, idx) =>
-                            idx == propertyIdx ? { ...p, key: scProperties[idx][0], value: scProperties[idx][1] } : p
-                        )
+                        ps.map((p) => (p.id === property[0] ? { ...p, key: property[0], value: property[1] } : p))
                     );
                 setFocusName("");
             }
         },
-        [isScenario, properties, scProperties]
+        [isScenario, scProperties]
     );
 
     const deleteProperty = useCallback(
         (e: React.MouseEvent<HTMLElement>) => {
             e.stopPropagation();
-            const { id: propId = "-1" } = e.currentTarget.dataset;
+            const { id: propId = "" } = e.currentTarget.dataset;
             setProperties((ps) => ps.filter((item) => item.id !== propId));
             const property = properties.find((p) => p.id === propId);
             property &&
@@ -436,8 +441,8 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
         showTags && setTags(scTags);
         showProperties &&
             setProperties(
-                scProperties.map(([k, v], i) => ({
-                    id: i + "",
+                scProperties.map(([k, v]) => ({
+                    id: k,
                     key: k,
                     value: v,
                 }))
@@ -654,7 +659,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                                           spacing={1}
                                                           container
                                                           justifyContent="space-between"
-                                                          key={property.key}
+                                                          key={property.id}
                                                           data-focus={propName}
                                                           onClick={onFocus}
                                                           sx={hoverSx}
@@ -757,11 +762,11 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                             spacing={1}
                                             container
                                             justifyContent="space-between"
-                                            data-focus="property-new"
+                                            data-focus="new-property"
                                             onClick={onFocus}
                                             sx={hoverSx}
                                         >
-                                            {active && focusName == "property-new" ? (
+                                            {active && focusName == "new-property" ? (
                                                 <>
                                                     <Grid item xs={4}>
                                                         <TextField

+ 0 - 7
gui/src/utils.ts

@@ -48,12 +48,6 @@ export interface ScenarioDict {
     properties: Array<[string, string]>;
 }
 
-export type Property = {
-    id: string;
-    key: string;
-    value: string;
-};
-
 export const FlagSx = {
     color: "common.white",
     fontSize: "0.75em",
@@ -89,7 +83,6 @@ export const BaseTreeViewSx = {
         py: 1,
         px: 2,
         borderRadius: 0.5,
-        backgroundColor: "background.paper",
     },
 
     "& .MuiTreeItem-iconContainer:empty": {

+ 7 - 3
src/taipy/gui_core/GuiCoreLib.py

@@ -198,10 +198,10 @@ class _GuiCoreContext(CoreEventConsumerBase):
             if self.scenario_configs is None:
                 configs = tp.Config.scenarios
                 if isinstance(configs, dict):
-                    self.scenario_configs = [(id, f"{c.id}") for id, c in configs.items()]
+                    self.scenario_configs = [(id, f"{c.id}") for id, c in configs.items() if id != "default"]
             return self.scenario_configs
 
-    def crud_scenario(self, state: State, id: str, action: str, payload: t.Dict[str, str]):
+    def crud_scenario(self, state: State, id: str, action: str, payload: t.Dict[str, str]):  # noqa: C901
         args = payload.get("args")
         if (
             args is None
@@ -244,9 +244,13 @@ class _GuiCoreContext(CoreEventConsumerBase):
                 state.assign(_GuiCoreContext._SCENARIO_SELECTOR_ERROR_VAR, f"Error creating Scenario. {e}")
         if scenario:
             with scenario as sc:
-                sc._properties[_GuiCoreContext.__PROP_ENTITY_NAME] = name
+                sc.properties[_GuiCoreContext.__PROP_ENTITY_NAME] = name
                 if props := data.get("properties"):
                     try:
+                        new_keys = [prop.get("key") for prop in props]
+                        for key in t.cast(dict, sc.properties).keys():
+                            if key and key not in _GuiCoreContext.__SCENARIO_PROPS and key not in new_keys:
+                                t.cast(dict, sc.properties).pop(key, None)
                         for prop in props:
                             key = prop.get("key")
                             if key and key not in _GuiCoreContext.__SCENARIO_PROPS: