Bläddra i källkod

tooltips (#347)

* tooltips

* limit unnecessary renders

---------

Co-authored-by: Fred Lefévère-Laoide <Fred.Lefevere-Laoide@Taipy.io>
Fred Lefévère-Laoide 1 år sedan
förälder
incheckning
02183c81a2

+ 1 - 0
gui/src/CoreSelector.tsx

@@ -168,6 +168,7 @@ const CoreItem = (props: {
                                     data-id={id}
                                     data-pinned={isPinned ? "pinned" : undefined}
                                     onClick={props.onPin}
+                                    size="small"
                                     sx={isPinned ? tinySelPinIconButtonSx : tinyPinIconButtonSx}
                                 >
                                     <PushPinOutlined />

+ 12 - 2
gui/src/DataNodeViewer.tsx

@@ -528,12 +528,20 @@ const DataNodeViewer = (props: DataNodeViewerProps) => {
                                                     endAdornment: (
                                                         <InputAdornment position="end">
                                                             <Tooltip title="Apply">
-                                                                <IconButton sx={IconPaddingSx} onClick={editLabel}>
+                                                                <IconButton
+                                                                    sx={IconPaddingSx}
+                                                                    onClick={editLabel}
+                                                                    size="small"
+                                                                >
                                                                     <CheckCircle color="primary" />
                                                                 </IconButton>
                                                             </Tooltip>
                                                             <Tooltip title="Cancel">
-                                                                <IconButton sx={IconPaddingSx} onClick={cancelLabel}>
+                                                                <IconButton
+                                                                    sx={IconPaddingSx}
+                                                                    onClick={cancelLabel}
+                                                                    size="small"
+                                                                >
                                                                     <Cancel color="inherit" />
                                                                 </IconButton>
                                                             </Tooltip>
@@ -792,6 +800,7 @@ const DataNodeViewer = (props: DataNodeViewerProps) => {
                                                                             <IconButton
                                                                                 sx={IconPaddingSx}
                                                                                 onClick={editDataValue}
+                                                                                size="small"
                                                                             >
                                                                                 <CheckCircle color="primary" />
                                                                             </IconButton>
@@ -800,6 +809,7 @@ const DataNodeViewer = (props: DataNodeViewerProps) => {
                                                                             <IconButton
                                                                                 sx={IconPaddingSx}
                                                                                 onClick={cancelDataValue}
+                                                                                size="small"
                                                                             >
                                                                                 <Cancel color="inherit" />
                                                                             </IconButton>

+ 4 - 2
gui/src/PropertiesEditor.tsx

@@ -199,6 +199,7 @@ const PropertiesEditor = (props: PropertiesEditorProps) => {
                                                       sx={IconPaddingSx}
                                                       data-id={property.id}
                                                       onClick={editProperty}
+                                                      size="small"
                                                   >
                                                       <CheckCircle color="primary" />
                                                   </IconButton>
@@ -208,6 +209,7 @@ const PropertiesEditor = (props: PropertiesEditorProps) => {
                                                       sx={IconPaddingSx}
                                                       data-id={property.id}
                                                       onClick={cancelProperty}
+                                                      size="small"
                                                   >
                                                       <Cancel color="inherit" />
                                                   </IconButton>
@@ -296,12 +298,12 @@ const PropertiesEditor = (props: PropertiesEditorProps) => {
                                 justifyContent="center"
                             >
                                 <Tooltip title="Apply">
-                                    <IconButton sx={IconPaddingSx} onClick={editProperty}>
+                                    <IconButton sx={IconPaddingSx} onClick={editProperty} size="small">
                                         <CheckCircle color="primary" />
                                     </IconButton>
                                 </Tooltip>
                                 <Tooltip title="Cancel">
-                                    <IconButton sx={IconPaddingSx} onClick={cancelProperty}>
+                                    <IconButton sx={IconPaddingSx} onClick={cancelProperty} size="small">
                                         <Cancel color="inherit" />
                                     </IconButton>
                                 </Tooltip>

+ 1 - 1
gui/src/ScenarioDag.tsx

@@ -51,7 +51,7 @@ const DagTitle = (props: DagTitleProps) => (
         <Toolbar>
             <Box sx={titleSx} />
             <Tooltip title="Zoom to fit">
-                <IconButton edge="end" color="inherit" onClick={props.zoomToFit} title="Zoom to fit">
+                <IconButton edge="end" color="inherit" onClick={props.zoomToFit}>
                     <ZoomIn />
                 </IconButton>
             </Tooltip>

+ 1 - 1
gui/src/ScenarioSelector.tsx

@@ -223,7 +223,7 @@ const ScenarioEditDialog = ({ scenario, submit, open, actionEdit, configs, close
                     <Grid container direction="row" justifyContent="space-between" alignItems="center">
                         <Typography variant="h5">{`${actionEdit ? `Edit` : `Create`} scenario`}</Typography>
                         <Tooltip title="close">
-                            <IconButton aria-label="close" onClick={close} sx={IconButtonSx}>
+                            <IconButton onClick={close} sx={IconButtonSx}>
                                 <Close />
                             </IconButton>
                         </Tooltip>

+ 74 - 80
gui/src/ScenarioViewer.tsx

@@ -11,16 +11,7 @@
  * specific language governing permissions and limitations under the License.
  */
 
-import React, {
-    useState,
-    useCallback,
-    useEffect,
-    useMemo,
-    ChangeEvent,
-    SyntheticEvent,
-    MouseEvent,
-    KeyboardEvent,
-} from "react";
+import React, { useState, useCallback, useEffect, ChangeEvent, SyntheticEvent, MouseEvent, KeyboardEvent } from "react";
 import Accordion from "@mui/material/Accordion";
 import AccordionDetails from "@mui/material/AccordionDetails";
 import AccordionSummary from "@mui/material/AccordionSummary";
@@ -36,6 +27,7 @@ import TextField from "@mui/material/TextField";
 import Tooltip from "@mui/material/Tooltip";
 import Typography from "@mui/material/Typography";
 import { FlagOutlined, Send, CheckCircle, Cancel, ArrowForwardIosSharp } from "@mui/icons-material";
+import deepEqual from "fast-deep-equal/es6";
 
 import {
     createRequestUpdateAction,
@@ -157,7 +149,7 @@ const SequenceRow = ({
         [submitEntity, id]
     );
     const onKeyDown = useCallback(
-        (e: KeyboardEvent<HTMLDivElement>) => {
+        (e: KeyboardEvent<HTMLInputElement>) => {
             if (!e.shiftKey && !e.ctrlKey && !e.altKey) {
                 if (e.key == "Enter") {
                     onSaveField();
@@ -187,20 +179,20 @@ const SequenceRow = ({
                         variant="outlined"
                         value={sequence}
                         onChange={onChange}
-                        onKeyDown={onKeyDown}
                         sx={FieldNoMaxWidth}
                         disabled={!enableScenarioFields || !active}
                         fullWidth
                         InputProps={{
+                            onKeyDown: onKeyDown,
                             endAdornment: (
                                 <InputAdornment position="end">
                                     <Tooltip title="Apply">
-                                        <IconButton sx={IconPaddingSx} onClick={onSaveField}>
+                                        <IconButton sx={IconPaddingSx} onClick={onSaveField} size="small">
                                             <CheckCircle color="primary" />
                                         </IconButton>
                                     </Tooltip>
                                     <Tooltip title="Cancel">
-                                        <IconButton sx={IconPaddingSx} onClick={onCancelField}>
+                                        <IconButton sx={IconPaddingSx} onClick={onCancelField} size="small">
                                             <Cancel color="inherit" />
                                         </IconButton>
                                     </Tooltip>
@@ -216,12 +208,7 @@ const SequenceRow = ({
                 {submit ? (
                     <Tooltip title={disabled ? "Cannot submit Sequence" : "Submit Sequence"}>
                         <span>
-                            <IconButton
-                                size="small"
-                                onClick={onSubmitSequence}
-                                disabled={disabled}
-                                title="Submit Sequence"
-                            >
+                            <IconButton size="small" onClick={onSubmitSequence} disabled={disabled}>
                                 <Send color={disableColor("info", disabled)} />
                             </IconButton>
                         </span>
@@ -239,6 +226,8 @@ const getValidScenario = (scenar: ScenarioFull | ScenarioFull[]) =>
         ? (scenar[0] as ScenarioFull)
         : undefined;
 
+const invalidScenario: ScenarioFull = ["", false, "", "", "", "", [], [], [], [], false, false, false, false, false];
+
 const ScenarioViewer = (props: ScenarioViewerProps) => {
     const {
         id = "",
@@ -258,6 +247,24 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     const dispatch = useDispatch();
     const module = useModule();
 
+    const [scenario, setScenario] = useState<ScenarioFull>();
+    const [valid, setValid] = useState(false);
+
+    useEffect(() => {
+        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
+            }
+        }
+        setValid(!!sc);
+        setScenario((oldSc) => (sc ? (deepEqual(oldSc, sc) ? oldSc : sc) : invalidScenario));
+    }, [props.scenario, props.defaultScenario]);
+
     const [
         scId,
         scPrimary,
@@ -274,20 +281,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
         scSubmittable,
         scReadable,
         scEditable,
-        isScenario,
-    ] = useMemo(() => {
-        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, false, false, false, false];
-    }, [props.scenario, props.defaultScenario]);
+    ] = scenario || invalidScenario;
 
     const active = useDynamicProperty(props.active, props.defaultActive, true) && scReadable;
     const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
@@ -297,23 +291,23 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     const closeDeleteDialog = useCallback(() => setDeleteDialogOpen(false), []);
     const onDeleteScenario = useCallback(() => {
         setDeleteDialogOpen(false);
-        if (isScenario) {
+        if (valid) {
             dispatch(createSendActionNameAction(id, module, props.onDelete, true, true, { id: scId }));
         }
-    }, [isScenario, props.onDelete, scId, id, dispatch, module]);
+    }, [valid, props.onDelete, scId, id, dispatch, module]);
 
     const [primaryDialog, setPrimaryDialog] = useState(false);
     const openPrimaryDialog = useCallback(() => setPrimaryDialog(true), []);
     const closePrimaryDialog = useCallback(() => setPrimaryDialog(false), []);
     const onPromote = useCallback(() => {
         setPrimaryDialog(false);
-        if (isScenario) {
+        if (valid) {
             dispatch(createSendActionNameAction(id, module, props.onEdit, { id: scId, primary: true }));
         }
-    }, [isScenario, props.onEdit, scId, id, dispatch, module]);
+    }, [valid, props.onEdit, scId, id, dispatch, module]);
 
     // userExpanded
-    const [userExpanded, setUserExpanded] = useState(isScenario && expanded);
+    const [userExpanded, setUserExpanded] = useState(valid && expanded);
     const onExpand = useCallback(
         (e: SyntheticEvent, expand: boolean) => expandable && setUserExpanded(expand),
         [expandable]
@@ -336,7 +330,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     const submitScenario = useCallback(
         (e: React.MouseEvent<HTMLElement>) => {
             e.stopPropagation();
-            if (isScenario) {
+            if (valid) {
                 dispatch(
                     createSendActionNameAction(id, module, props.onSubmit, {
                         id: scId,
@@ -345,7 +339,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                 );
             }
         },
-        [isScenario, props.onSubmit, props.onSubmissionChange, id, scId, dispatch, module]
+        [valid, props.onSubmit, props.onSubmissionChange, id, scId, dispatch, module]
     );
 
     // focus
@@ -360,12 +354,12 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     const editLabel = useCallback(
         (e?: MouseEvent<HTMLElement>) => {
             e && e.stopPropagation();
-            if (isScenario) {
+            if (valid) {
                 dispatch(createSendActionNameAction(id, module, props.onEdit, { id: scId, name: label }));
                 setFocusName("");
             }
         },
-        [isScenario, props.onEdit, scId, label, id, dispatch, module]
+        [valid, props.onEdit, scId, label, id, dispatch, module]
     );
     const cancelLabel = useCallback(
         (e?: MouseEvent<HTMLElement>) => {
@@ -377,7 +371,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     );
     const onLabelChange = useCallback((e: ChangeEvent<HTMLInputElement>) => setLabel(e.target.value), []);
     const onLabelKeyDown = useCallback(
-        (e: KeyboardEvent<HTMLDivElement>) => {
+        (e: KeyboardEvent<HTMLInputElement>) => {
             if (!e.shiftKey && !e.ctrlKey && !e.altKey) {
                 if (e.key == "Enter") {
                     editLabel();
@@ -398,12 +392,12 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     const editTags = useCallback(
         (e: MouseEvent<HTMLElement>) => {
             e.stopPropagation();
-            if (isScenario) {
+            if (valid) {
                 dispatch(createSendActionNameAction(id, module, props.onEdit, { id: scId, tags: tags }));
                 setFocusName("");
             }
         },
-        [isScenario, props.onEdit, scId, tags, id, dispatch, module]
+        [valid, props.onEdit, scId, tags, id, dispatch, module]
     );
     const cancelTags = useCallback(
         (e: MouseEvent<HTMLElement>) => {
@@ -418,22 +412,22 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
     // sequences
     const editSequence = useCallback(
         (id: string, label: string) => {
-            if (isScenario) {
+            if (valid) {
                 dispatch(
                     createSendActionNameAction(id, module, props.onEdit, { id: id, name: label, type: "Sequence" })
                 );
                 setFocusName("");
             }
         },
-        [isScenario, props.onEdit, dispatch, module]
+        [valid, props.onEdit, dispatch, module]
     );
 
     // on scenario change
     useEffect(() => {
         showTags && setTags(scTags);
         setLabel(scLabel);
-        setUserExpanded(expanded && isScenario);
-    }, [scTags, scLabel, isScenario, showTags, expanded]);
+        setUserExpanded(expanded && valid);
+    }, [scTags, scLabel, valid, showTags, expanded]);
 
     // Refresh on broadcast
     useEffect(() => {
@@ -443,17 +437,12 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
         }
     }, [props.coreChanged, props.updateVarName, id, module, dispatch, scId]);
 
-    const disabled = !isScenario || !active || !scSubmittable;
+    const disabled = !valid || !active || !scSubmittable;
 
     return (
         <>
             <Box sx={MainBoxSx} id={id} onClick={onFocus} className={className}>
-                <Accordion
-                    defaultExpanded={expanded}
-                    expanded={userExpanded}
-                    onChange={onExpand}
-                    disabled={!isScenario}
-                >
+                <Accordion defaultExpanded={expanded} expanded={userExpanded} onChange={onExpand} disabled={!valid}>
                     <AccordionSummary
                         expandIcon={expandable ? <ArrowForwardIosSharp sx={AccordionIconSx} /> : null}
                         sx={AccordionSummarySx}
@@ -479,14 +468,9 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                             </Grid>
                             <Grid item>
                                 {showSubmit ? (
-                                    <Tooltip title={disabled ? "Cannot submit Sequence" : "Submit Scenario"}>
+                                    <Tooltip title={disabled ? "Cannot submit Scenario" : "Submit Scenario"}>
                                         <span>
-                                            <IconButton
-                                                sx={IconPaddingSx}
-                                                onClick={submitScenario}
-                                                disabled={disabled}
-                                                title="Submit Scenario"
-                                            >
+                                            <IconButton sx={IconPaddingSx} onClick={submitScenario} disabled={disabled}>
                                                 <Send fontSize="medium" color={disableColor("info", disabled)} />
                                             </IconButton>
                                         </span>
@@ -545,24 +529,32 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                             sx={FieldNoMaxWidth}
                                             value={label || ""}
                                             onChange={onLabelChange}
-                                            onKeyDown={onLabelKeyDown}
                                             InputProps={{
+                                                onKeyDown: onLabelKeyDown,
                                                 endAdornment: (
                                                     <InputAdornment position="end">
                                                         <Tooltip title="Apply">
-                                                            <IconButton sx={IconPaddingSx} onClick={editLabel}>
+                                                            <IconButton
+                                                                sx={IconPaddingSx}
+                                                                onClick={editLabel}
+                                                                size="small"
+                                                            >
                                                                 <CheckCircle color="primary" />
                                                             </IconButton>
                                                         </Tooltip>
                                                         <Tooltip title="Cancel">
-                                                            <IconButton sx={IconPaddingSx} onClick={cancelLabel}>
+                                                            <IconButton
+                                                                sx={IconPaddingSx}
+                                                                onClick={cancelLabel}
+                                                                size="small"
+                                                            >
                                                                 <Cancel color="inherit" />
                                                             </IconButton>
                                                         </Tooltip>
                                                     </InputAdornment>
                                                 ),
                                             }}
-                                            disabled={!isScenario}
+                                            disabled={!valid}
                                         />
                                     ) : (
                                         <>
@@ -621,6 +613,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                                                         <IconButton
                                                                             sx={IconPaddingSx}
                                                                             onClick={editTags}
+                                                                            size="small"
                                                                         >
                                                                             <CheckCircle color="primary" />
                                                                         </IconButton>
@@ -629,6 +622,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                                                         <IconButton
                                                                             sx={IconPaddingSx}
                                                                             onClick={cancelTags}
+                                                                            size="small"
                                                                         >
                                                                             <Cancel color="inherit" />
                                                                         </IconButton>
@@ -638,7 +632,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                                         }}
                                                     />
                                                 )}
-                                                disabled={!isScenario}
+                                                disabled={!valid}
                                             />
                                         ) : (
                                             <>
@@ -662,7 +656,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                             <PropertiesEditor
                                 entityId={scId}
                                 active={active}
-                                isDefined={isScenario}
+                                isDefined={valid}
                                 entProperties={scProperties}
                                 show={showProperties}
                                 focusName={focusName}
@@ -688,7 +682,7 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                                                     label={value}
                                                     key={key}
                                                     submitEntity={submitSequence}
-                                                    enableScenarioFields={isScenario}
+                                                    enableScenarioFields={valid}
                                                     submit={showSubmitSequences}
                                                     editLabel={editSequence}
                                                     onFocus={onFocus}
@@ -707,19 +701,19 @@ const ScenarioViewer = (props: ScenarioViewerProps) => {
                             ) : null}
                             <Grid item xs={12} container justifyContent="space-between">
                                 {showDelete ? (
-                                            <Button
-                                                variant="outlined"
-                                                color="primary"
-                                                disabled={!active || !isScenario || !scDeletable}
-                                                onClick={openDeleteDialog}
-                                            >
-                                                DELETE
-                                            </Button>
+                                    <Button
+                                        variant="outlined"
+                                        color="primary"
+                                        disabled={!active || !valid || !scDeletable}
+                                        onClick={openDeleteDialog}
+                                    >
+                                        DELETE
+                                    </Button>
                                 ) : null}
                                 <Button
                                     variant="outlined"
                                     color="primary"
-                                    disabled={!active || !isScenario || scPrimary || !scPromotable}
+                                    disabled={!active || !valid || scPrimary || !scPromotable}
                                     onClick={openPrimaryDialog}
                                 >
                                     PROMOTE TO PRIMARY

+ 1 - 1
gui/src/utils/ConfirmDialog.tsx

@@ -27,7 +27,7 @@ const ConfirmDialog = ({ title, message, confirm, open, onClose, onConfirm }: Co
             <Grid container direction="row" justifyContent="space-between" alignItems="center">
                 <Typography variant="h5">{title}</Typography>
                 <Tooltip title="close">
-                    <IconButton aria-label="close" onClick={onClose} sx={IconButtonSx}>
+                    <IconButton onClick={onClose} sx={IconButtonSx}>
                         <Close />
                     </IconButton>
                 </Tooltip>