Skip to content

Commit

Permalink
Backport to 4.0 of Taipy GUI issues #2212, #2242, #2281, #2286, #2302,…
Browse files Browse the repository at this point in the history
… and #2305.
  • Loading branch information
FabienLelaquais committed Dec 16, 2024
1 parent 6678003 commit dd8e34c
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 59 deletions.
2 changes: 1 addition & 1 deletion frontend/taipy-gui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "taipy-gui",
"version": "4.0.1",
"version": "4.0.2",
"private": true,
"dependencies": {
"@emotion/react": "^11.10.0",
Expand Down
2 changes: 1 addition & 1 deletion frontend/taipy-gui/public/stylekit/controls/selector.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
**************************************************/

.taipy-selector {
margin: 4px 0;
margin: 0;
}


Expand Down
3 changes: 3 additions & 0 deletions frontend/taipy-gui/public/stylekit/controls/slider.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@
**************************************************/

.taipy-slider {
display: inline-flex;
max-width: 100%;
min-height: 48px;
align-items: center;
}
28 changes: 28 additions & 0 deletions frontend/taipy-gui/public/stylekit/controls/status.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2021-2024 Avaiga Private Limited
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* 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.
*/

/**************************************************************
TAIPY STATUS
***************************************************************/

/*************************************************
OVERRIDES / NORMALIZATION
**************************************************/

.taipy-status {
display: inline-flex;
min-height: 48px;
padding-top: 0.5em;
}
3 changes: 3 additions & 0 deletions frontend/taipy-gui/public/stylekit/controls/toggle.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
.taipy-toggle {
display: inline-flex;
z-index: 10;
min-height: 48px;
align-items: center;
gap: 0.3em;
}

.taipy-toggle .MuiToggleButtonGroup-root[aria-label='Theme mode'] {
Expand Down
1 change: 1 addition & 0 deletions frontend/taipy-gui/public/stylekit/stylekit.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
@import 'controls/number.css';
@import 'controls/slider.css';
@import 'controls/selector.css';
@import 'controls/status.css';
@import 'controls/toggle.css';
@import 'controls/file_download.css';
@import 'controls/file_selector.css';
Expand Down
38 changes: 20 additions & 18 deletions frontend/taipy-gui/src/components/Taipy/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useTheme } from "@mui/material";
import Box from "@mui/material/Box";
import Skeleton from "@mui/material/Skeleton";
import Tooltip from "@mui/material/Tooltip";
import merge from "lodash/merge";
import { nanoid } from "nanoid";
import {
Config,
Expand Down Expand Up @@ -279,6 +280,11 @@ const updateArrays = (sel: number[][], val: number[], idx: number) => {
return sel;
};

const getDataKey = (columns: Record<string, ColumnDesc>, decimators?: string[]): [string[], string] => {
const backCols = Object.values(columns).map((col) => col.dfid);
return [backCols, backCols.join("-") + (decimators ? `--${decimators.join("")}` : "")];
};

const Chart = (props: ChartProp) => {
const {
title = "",
Expand Down Expand Up @@ -347,9 +353,8 @@ const Chart = (props: ChartProp) => {
const config = useDynamicJsonProperty(props.config, props.defaultConfig, defaultConfig);

useEffect(() => {
if (updateVarName && (refresh || !data[dataKey])) {
const backCols = Object.values(config.columns).map((col) => col.dfid);
const dtKey = backCols.join("-") + (config.decimators ? `--${config.decimators.join("")}` : "");
if (updateVarName) {
const [backCols, dtKey] = getDataKey(config.columns, config.decimators);
setDataKey(dtKey);
if (refresh || !data[dtKey]) {
dispatch(
Expand Down Expand Up @@ -394,12 +399,10 @@ const Chart = (props: ChartProp) => {
layout.template = template;
}
if (props.figure) {
return {
...(props.figure[0].layout as Partial<Layout>),
...layout,
return merge({}, props.figure[0].layout as Partial<Layout>, layout, {
title: title || layout.title || (props.figure[0].layout as Partial<Layout>).title,
clickmode: "event+select",
} as Layout;
});
}
return {
...layout,
Expand Down Expand Up @@ -446,8 +449,12 @@ const Chart = (props: ChartProp) => {
if (props.figure) {
return lastDataPl.current;
}
if (data.__taipy_refresh !== undefined && lastDataPl.current) {
return lastDataPl.current;
if (data.__taipy_refresh !== undefined) {
return lastDataPl.current || [];
}
const dtKey = getDataKey(config.columns, config.decimators)[1];
if (!dataKey.startsWith(dtKey)) {
return lastDataPl.current || [];
}
const datum = data[dataKey];
lastDataPl.current = datum
Expand Down Expand Up @@ -529,7 +536,7 @@ const Chart = (props: ChartProp) => {
}
return ret as Data;
})
: [];
: lastDataPl.current || [];
return lastDataPl.current;
}, [props.figure, selected, data, config, dataKey]);

Expand Down Expand Up @@ -560,15 +567,10 @@ const Chart = (props: ChartProp) => {
(eventData: PlotRelayoutEvent) => {
onRangeChange && dispatch(createSendActionNameAction(id, module, { action: onRangeChange, ...eventData }));
if (config.decimators && !config.types.includes("scatter3d")) {
const backCols = Object.values(config.columns).map((col) => col.dfid);
const eventDataKey = Object.entries(eventData)
const [backCols, dtKeyBase] = getDataKey(config.columns, config.decimators);
const dtKey = `${dtKeyBase}--${Object.entries(eventData)
.map(([k, v]) => `${k}=${v}`)
.join("-");
const dtKey =
backCols.join("-") +
(config.decimators ? `--${config.decimators.join("")}` : "") +
"--" +
eventDataKey;
.join("-")}`;
setDataKey(dtKey);
dispatch(
createRequestChartUpdateAction(
Expand Down
13 changes: 10 additions & 3 deletions frontend/taipy-gui/src/components/Taipy/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import React, {
useEffect,
ReactNode,
lazy,
UIEvent,
} from "react";
import { SxProps, Theme, darken, lighten } from "@mui/material/styles";
import Avatar from "@mui/material/Avatar";
Expand Down Expand Up @@ -226,6 +227,7 @@ const Chat = (props: ChatProps) => {
const isAnchorDivVisible = useElementVisible(anchorDivRef);
const [showMessage, setShowMessage] = useState(false);
const [anchorPopup, setAnchorPopup] = useState<HTMLDivElement | null>(null);
const userScrolled = useRef(false);

const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
const active = useDynamicProperty(props.active, props.defaultActive, true);
Expand Down Expand Up @@ -341,7 +343,7 @@ const Chat = (props: ChatProps) => {
);

const showBottom = useCallback(() => {
anchorDivRef.current?.scrollIntoView();
anchorDivRef.current?.scrollIntoView && anchorDivRef.current?.scrollIntoView();
setShowMessage(false);
}, []);

Expand All @@ -367,8 +369,9 @@ const Chat = (props: ChatProps) => {
}
}
page.current.key = getChatKey(0, pageSize);
!userScrolled.current && showBottom();
}
}, [refresh, pageSize, props.messages]);
}, [refresh, pageSize, props.messages, showBottom]);

useEffect(() => {
if (showMessage && !isAnchorDivVisible) {
Expand Down Expand Up @@ -399,10 +402,14 @@ const Chat = (props: ChatProps) => {
[loadMoreItems]
);

const handleOnScroll = useCallback((evt: UIEvent) => {
userScrolled.current = (evt.target as HTMLDivElement).scrollHeight - (evt.target as HTMLDivElement).offsetHeight - (evt.target as HTMLDivElement).scrollTop > 1;
}, []);

return (
<Tooltip title={hover || ""}>
<Paper className={className} sx={boxSx} id={id}>
<Grid container rowSpacing={2} sx={gridSx} ref={scrollDivRef}>
<Grid container rowSpacing={2} sx={gridSx} ref={scrollDivRef} onScroll={handleOnScroll}>
{rows.length && !rows[0] ? (
<Grid className={getSuffixedClassNames(className, "-load")} size={12} sx={noAnchorSx}>
<Box sx={loadMoreSx}>
Expand Down
58 changes: 32 additions & 26 deletions frontend/taipy-gui/src/components/Taipy/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const verticalDivStyle: CSSProperties = {
flexDirection: "column",
gap: 0,
};
const noPaddingYSx = {py: 0};

const Input = (props: TaipyInputProps) => {
const {
Expand Down Expand Up @@ -264,32 +265,36 @@ const Input = (props: TaipyInputProps) => {
() =>
type == "number"
? {
htmlInput: {
step: step ? step : 1,
min: min,
max: max,
},
input: {
endAdornment: (
<div style={verticalDivStyle}>
<IconButton
aria-label="Increment value"
size="small"
onMouseDown={handleUpStepperMouseDown}
>
<ArrowDropUpIcon fontSize="inherit" />
</IconButton>
<IconButton
aria-label="Decrement value"
size="small"
onMouseDown={handleDownStepperMouseDown}
>
<ArrowDropDownIcon fontSize="inherit" />
</IconButton>
</div>
),
},
}
htmlInput: {
step: step ? step : 1,
min: min,
max: max,
},
input: {
endAdornment: (
<div style={verticalDivStyle}>
<IconButton
aria-label="Increment value"
size="small"
onMouseDown={handleUpStepperMouseDown}
disabled={!active}
sx={noPaddingYSx}
>
<ArrowDropUpIcon fontSize="inherit" />
</IconButton>
<IconButton
aria-label="Decrement value"
size="small"
onMouseDown={handleDownStepperMouseDown}
disabled={!active}
sx={noPaddingYSx}
>
<ArrowDropDownIcon fontSize="inherit" />
</IconButton>
</div>
),
},
}
: type == "password"
? {
htmlInput: { autoComplete: "current-password" },
Expand All @@ -308,6 +313,7 @@ const Input = (props: TaipyInputProps) => {
}
: undefined,
[
active,
type,
step,
min,
Expand Down
2 changes: 1 addition & 1 deletion frontend/taipy-gui/src/components/Taipy/PaginatedTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ const PaginatedTable = (props: TaipyPaginatedTableProps) => {
sortDirection={orderBy === columns[col].dfid && order}
sx={
columns[col].width
? { width: columns[col].width }
? { minWidth: columns[col].width }
: nbWidth
? { minWidth: `${100 / nbWidth}%` }
: undefined
Expand Down
12 changes: 11 additions & 1 deletion frontend/taipy-gui/src/components/Taipy/Selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,17 @@ const Selector = (props: SelTreeProps) => {
return sx;
}, [height]);
const controlSx = useMemo(
() => ({ my: 1, mx: 0, maxWidth: width, display: "flex", "& .MuiFormControl-root": { maxWidth: "unset" } }),
() => ({
my: 1,
mx: 0,
maxWidth: width,
display: "flex",
"& .MuiFormControl-root": {
maxWidth: "unset",
my: 0,
"& .MuiInputBase-root": { minHeight: 48, "& input": { minHeight: "unset" } },
},
}),
[width]
);

Expand Down
6 changes: 3 additions & 3 deletions frontend/taipy-gui/src/components/Taipy/StatusList.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe("StatusList Component", () => {
it("uses the class", async () => {
const { getByText } = render(<StatusList value={statuses} className="taipy-status" />);
const elt = getByText("4 statuses");
expect(elt.parentElement).toHaveClass("taipy-status");
expect(elt.parentElement?.parentElement).toHaveClass("taipy-status");
});
it("can be opened when more than 1 status", async () => {
const { getByTestId } = render(<StatusList value={statuses} />);
Expand All @@ -57,8 +57,8 @@ describe("StatusList Component", () => {
const { getByTestId, getByText } = render(<StatusList value={statuses} />);
const elt = getByTestId("ArrowDownwardIcon");
await userEvent.click(elt);
const selt = getByText("info");
expect(selt.parentElement?.parentElement?.childElementCount).toBe(4);
const infoElt = getByText("info");
expect(infoElt.parentElement?.parentElement?.childElementCount).toBe(4);
});
it("hide closed statuses", async () => {
const { getByTestId, queryAllByTestId } = render(<StatusList value={statuses} />);
Expand Down
16 changes: 11 additions & 5 deletions frontend/taipy-gui/src/components/Taipy/StatusList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
*/

import React, { MouseEvent, useCallback, useEffect, useMemo, useState } from "react";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import ArrowDownward from "@mui/icons-material/ArrowDownward";
import ArrowUpward from "@mui/icons-material/ArrowUpward";
import Tooltip from "@mui/material/Tooltip";
import Popover, { PopoverOrigin } from "@mui/material/Popover";

import Status, { StatusType } from "./Status";
import { TaipyBaseProps, TaipyHoverProps } from "./utils";
import { getSuffixedClassNames, TaipyBaseProps, TaipyHoverProps } from "./utils";
import { useClassNames, useDynamicProperty } from "../../utils/hooks";

export const getStatusIntValue = (status: string) => {
Expand Down Expand Up @@ -157,8 +158,13 @@ const StatusList = (props: StatusListProps) => {

return (
<Tooltip title={hover || ""}>
<>
<Status id={props.id} value={getGlobalStatus(values)} className={className} {...globalProps} />
<Box className={className}>
<Status
id={props.id}
value={getGlobalStatus(values)}
className={getSuffixedClassNames(className, "-main")}
{...globalProps}
/>
<Popover open={opened} anchorEl={anchorEl} onClose={onOpen} anchorOrigin={ORIGIN}>
<Stack direction="column" spacing={1}>
{values
Expand All @@ -170,14 +176,14 @@ const StatusList = (props: StatusListProps) => {
key={getId(props.id, idx)}
id={getId(props.id, idx)}
value={val}
className={className}
className={getSuffixedClassNames(className, `-${idx}`)}
{...closeProp}
/>
);
})}
</Stack>
</Popover>
</>
</Box>
</Tooltip>
);
};
Expand Down
Loading

0 comments on commit dd8e34c

Please sign in to comment.