Skip to content

Commit

Permalink
Merge branch 'develop' into feature/#2017-editor-id
Browse files Browse the repository at this point in the history
  • Loading branch information
jrobinAV authored Nov 25, 2024
2 parents 2ba8014 + 348d86d commit 39660ad
Show file tree
Hide file tree
Showing 20 changed files with 324 additions and 142 deletions.
16 changes: 16 additions & 0 deletions doc/gui/examples/controls/status_icons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from taipy.gui import Gui

status = [
("warning", "Task is launched."),
("warning", "Tasks is waiting."),
("error", "Task timeout."),
("success", "Task Succeeded"),
("info", "Process was cancelled.")
]

page = """
<|{status}|status|use_icon|>
"""

if __name__ == "__main__":
Gui(page).run(title="Status - With icons")
20 changes: 20 additions & 0 deletions doc/gui/examples/controls/status_mixed_icons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from taipy.gui import Gui

status = [
("warning", "Task is launched."),
("warning", "Tasks is waiting."),
("error", "Task timeout."),
("success", "Task Succeeded"),
("info", "Process was cancelled.")
]

# Info: svg icon (pants.svg)
# success: no icon
# warning: default icon
# error: inline svg icon (red disc)
page = """
<|{status}|status|don't use_icon|use_icon[info]=https://www.svgrepo.com/show/530594/pants.svg|use_icon[success]|use_icon[error]=<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><circle cx='12' cy='12' r='10' fill='red'/></svg>|>
""" # noqa: E501

if __name__ == "__main__":
Gui(page).run(title="Status - With mixed icons")
16 changes: 16 additions & 0 deletions doc/gui/examples/controls/status_simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from taipy.gui import Gui

status = [
("warning", "Task is launched."),
("warning", "Tasks is waiting."),
("error", "Task timeout."),
("success", "Task Succeeded"),
("info", "Process was cancelled.")
]

page = """
<|{status}|status|>
"""

if __name__ == "__main__":
Gui(page).run(title="Status - Simple")
20 changes: 20 additions & 0 deletions doc/gui/examples/controls/status_svg_icons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from taipy.gui import Gui

status = [
("warning", "Task is launched."),
("warning", "Tasks is waiting."),
("error", "Task timeout."),
("success", "Task Succeeded"),
("info", "Process was cancelled.")
]

# Info: svg icon (pants.svg)
# success: svg icon (hotel.svg)
# warning: svg icon (diving-goggles.svg)
# error: svg icon (hat.svg)
page = """
<|{status}|status|use_icon[info]=https://www.svgrepo.com/show/530594/pants.svg|use_icon[success]=https://www.svgrepo.com/show/530595/hotel.svg|use_icon[warning]=https://www.svgrepo.com/show/530596/diving-goggles.svg|use_icon[error]=https://www.svgrepo.com/show/530597/hat.svg|>
"""

if __name__ == "__main__":
Gui(page).run(title="Status - With SVG icons")
10 changes: 10 additions & 0 deletions doc/gui/extension/example_library/example_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ def __init__(self) -> None:
# element, exported as GameTable in front-end/src/index.ts
# react_component="GameTable",
),
"visual_label_list": Element(
"lov",
{
"lov": ElementProperty(PropertyType.lov),
"sort": ElementProperty(PropertyType.string),
},
# The name of the React component (VisualLabelList) that implements this custom
# element, exported as LabeledItemList in front-end/src/index.ts
react_component="VisualLabelList",
)
}

# The implementation of the rendering for the "fraction" static element
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { useMemo } from "react";
import { LoV, useLovListMemo } from "taipy-gui";

interface VisualLabelListProps {
lov?: LoV;
defaultLov?: string;
sort?: "asc" | "desc";
}

const styles = {
listItem: {
display: "flex",
alignItems: "center",
},
image: {
marginRight: "8px",
width: "1em",
height: "1em",
},
};

const VisualLabelList: React.FC<VisualLabelListProps> = ({ lov, defaultLov = "", sort }) => {
const lovList = useLovListMemo(lov, defaultLov);

const sortedLovList = useMemo(() => {
if (sort) {
return lovList.slice().sort((a, b) => {
return sort === "asc" ? a.id.localeCompare(b.id) : b.id.localeCompare(a.id);
});
}
return lovList;
}, [lovList, sort]);

return (
<div>
<ul>
{sortedLovList.map((item, index) => (
<li key={index} style={styles.listItem}>
{typeof item.item === "string" ? null : (
<img src={item.item.path} alt={item.item.text} style={styles.image} />
)}
{item.id}
</li>
))}
</ul>
</div>
);
};

export default VisualLabelList;
3 changes: 2 additions & 1 deletion doc/gui/extension/example_library/front-end/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
// the name used in the element declaration in the element library.
import ColoredLabel from "./ColoredLabel";
import GameTable from "./GameTable";
import VisualLabelList from "./VisualLabelList";

export { ColoredLabel as ExampleLabel, GameTable };
export { ColoredLabel as ExampleLabel, GameTable, VisualLabelList };
Binary file added doc/gui/extension/images/cpp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/gui/extension/images/java.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/gui/extension/images/javascript.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/gui/extension/images/python.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/gui/extension/images/typescript.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions doc/gui/extension/visual_label_list.py
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.
from example_library import ExampleLibrary

from taipy.gui import Gui, Icon

languages = [
["Python", Icon("images/python.png", "Python logo")],
["JavaScript", Icon("images/javascript.png", "JavaScript logo")],
["TypeScript", Icon("images/typescript.png", "TypeScript logo")],
["Java", Icon("images/java.png", "Java logo")],
["C++", Icon("images/cpp.png", "C++ logo")],
]

page = """
<|{languages}|example.visual_label_list|sort=asc|>
"""

if __name__ == "__main__":
Gui(page, libraries=[ExampleLibrary()]).run(title="List of item")
36 changes: 18 additions & 18 deletions frontend/taipy-gui/src/components/Taipy/Status.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,59 +42,59 @@ describe("Status Component", () => {
await userEvent.click(elt);
expect(myClose).toHaveBeenCalled();
})
it("displays the icon", async () => {
const {getByTestId} = render(<Status value={status} icon={<PlusOneOutlined/>} onClose={jest.fn()} />);
it("displays the open icon", async () => {
const {getByTestId} = render(<Status value={status} openedIcon={<PlusOneOutlined/>} onClose={jest.fn()} />);
getByTestId("PlusOneOutlinedIcon");
})
// Test case for Inline SVG content
it("renders an Avatar with inline SVG", () => {
const inlineSvg = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24'><circle cx='12' cy='12' r='10' fill='red'/></svg>";
const { getByTestId } = render(<Status value={status} content={inlineSvg} />);
const { getByTestId } = render(<Status value={status} icon={inlineSvg} />);
const avatar = getByTestId("Avatar");
// Inline SVG should be rendered as inner HTML inside the Avatar
const svgElement = avatar.querySelector("svg");
expect(svgElement).toBeInTheDocument();
});

// Test case for Text content (default behavior)
it("renders Avatar with initial when content is text", () => {
const { getByTestId } = render(<Status value={status} content="Text content" />);
it("renders Avatar with initial when icon is text", () => {
const { getByTestId } = render(<Status value={status} icon="Text content" />);
const avatar = getByTestId("Avatar");
expect(avatar).toHaveTextContent("S");
});

// Test case for empty content
it("renders Avatar with initial when no content is provided", () => {
const { getByTestId } = render(<Status value={status} content="Text content" />);
it("renders Avatar with initial when no icon is provided", () => {
const { getByTestId } = render(<Status value={status} />);
const avatar = getByTestId("Avatar");
expect(avatar).toHaveTextContent("S");
});

// Test case for an invalid content type (like a non-SVG string)
it("renders Avatar with initial if content is invalid", () => {
const { getByTestId } = render(<Status value={status} content="invalid-content" />);
it("renders Avatar with initial if icon is invalid", () => {
const { getByTestId } = render(<Status value={status} icon="invalid-content" />);
const avatar = getByTestId("Avatar");
expect(avatar).toHaveTextContent("S");
});

it("renders an avatar with initial when withIcons is false", () => {
it("renders an avatar with initial when icon is false", () => {
const statusWithoutIcons: StatusType = { status: "warning", message: "Warning detected" };
const { getByTestId } = render(<Status value={statusWithoutIcons} withIcons={false} />);

const { getByTestId } = render(<Status value={statusWithoutIcons} icon={false} />);

// Check if the avatar has the initial of the status (W)
const avatar = getByTestId("Avatar");
expect(avatar).toHaveTextContent("W");
});

it("renders the correct icon when withIcons is true", () => {
it("renders the correct icon when icon is true", () => {
const statusWithIcons: StatusType = { status: "success", message: "Operation successful" };
const { getByTestId } = render(<Status value={statusWithIcons} withIcons={true} />);

const { getByTestId } = render(<Status value={statusWithIcons} icon={true} />);

// Check if the Avatar element contains the icon (CheckCircleIcon for success status)
const avatar = getByTestId("Avatar");

// Check if the avatar contains the appropriate icon, in this case CheckCircleIcon
// Since CheckCircleIcon is rendered as part of the Avatar, we can check for its presence by looking for SVGs or icon classes
const icon = avatar.querySelector("svg");
Expand Down
Loading

0 comments on commit 39660ad

Please sign in to comment.