Skip to content

Commit

Permalink
display toggle as switch if lov is not declared (#737)
Browse files Browse the repository at this point in the history
* display toggle as switch if lov is not declared

* default value

* switch mode

* fix test

* fix test

---------

Co-authored-by: Fred Lefévère-Laoide <[email protected]>
  • Loading branch information
FredLL-Avaiga and Fred Lefévère-Laoide authored Jan 23, 2024
1 parent 53ab999 commit f8e90ad
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 45 deletions.
4 changes: 2 additions & 2 deletions frontend/taipy-gui/src/components/Taipy/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
import WbSunny from "@mui/icons-material/WbSunny";
import Brightness3 from "@mui/icons-material/Brightness3";

import { TaipyActiveProps } from "./utils";
import { TaipyActiveProps, emptyStyle } from "./utils";
import { TaipyContext } from "../../context/taipyContext";
import { createThemeAction } from "../../context/taipyReducers";
import { useClassNames } from "../../utils/hooks";
Expand All @@ -46,7 +46,7 @@ const boxSx = {
const groupSx = { verticalAlign: "middle" };

const ThemeToggle = (props: ThemeToggleProps) => {
const { id, label = "Mode", style = {}, active = true } = props;
const { id, label = "Mode", style = emptyStyle, active = true } = props;
const { state, dispatch } = useContext(TaipyContext);

const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
Expand Down
56 changes: 56 additions & 0 deletions frontend/taipy-gui/src/components/Taipy/Toggle.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,60 @@ describe("Toggle Component", () => {
await userEvent.click(elt);
expect(dispatch).not.toHaveBeenCalled();
});

describe("As Switch", () => {
it("renders", async () => {
const { getByText } = render(<Toggle isSwitch={true} label="switch" />);
const elt = getByText("switch");
expect(elt.tagName).toBe("SPAN");
});
it("uses the class", async () => {
const { getByText } = render(<Toggle isSwitch={true} label="switch" className="taipy-toggle" />);
const elt = getByText("switch");
expect(elt.parentElement).toHaveClass("taipy-toggle-switch");
});
it("shows a selection at start", async () => {
const { getByText } = render(<Toggle isSwitch={true} defaultValue={true as unknown as string} label="switch" />);
const elt = getByText("switch");
expect(elt.parentElement?.querySelector(".MuiSwitch-switchBase")).toHaveClass("Mui-checked");
});
it("shows a selection at start through value", async () => {
const { getByText } = render(<Toggle isSwitch={true} value={true as unknown as string} defaultValue={false as unknown as string} label="switch" />);
const elt = getByText("switch");
expect(elt.parentElement?.querySelector(".MuiSwitch-switchBase")).toHaveClass("Mui-checked");
});
it("is disabled", async () => {
const { getByText } = render(<Toggle isSwitch={true} defaultValue={false as unknown as string} label="switch" active={false} />);
const elt = getByText("switch");
expect(elt.parentElement?.querySelector("input")).toBeDisabled();
});
it("is enabled by default", async () => {
const { getByText } = render(<Toggle isSwitch={true} defaultValue={false as unknown as string} label="switch" />);
const elt = getByText("switch");
expect(elt.parentElement?.querySelector("input")).not.toBeDisabled();
});
it("is enabled by active", async () => {
const { getByText } = render(<Toggle isSwitch={true} defaultValue={false as unknown as string} label="switch" active={true} />);
const elt = getByText("switch");
expect(elt.parentElement?.querySelector("input")).not.toBeDisabled();
});
it("dispatch a well formed message", async () => {
const dispatch = jest.fn();
const state: TaipyState = INITIAL_STATE;
const { getByText } = render(
<TaipyContext.Provider value={{ state, dispatch }}>
<Toggle isSwitch={true} updateVarName="varname" defaultValue={false as unknown as string} label="switch" />
</TaipyContext.Provider>
);
const elt = getByText("switch");
await userEvent.click(elt);
expect(dispatch).toHaveBeenCalledWith({
name: "varname",
payload: { value: true },
propagate: true,
type: "SEND_UPDATE_ACTION",
});
});

});
});
95 changes: 65 additions & 30 deletions frontend/taipy-gui/src/components/Taipy/Toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
* specific language governing permissions and limitations under the License.
*/

import React, { CSSProperties, MouseEvent, useCallback, useEffect, useState } from "react";
import React, { CSSProperties, MouseEvent, SyntheticEvent, useCallback, useEffect, useState } from "react";
import Box from "@mui/material/Box";
import Switch from "@mui/material/Switch";
import Typography from "@mui/material/Typography";
import ToggleButton from "@mui/material/ToggleButton";
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
Expand All @@ -22,24 +23,25 @@ import { createSendUpdateAction } from "../../context/taipyReducers";
import ThemeToggle from "./ThemeToggle";
import { LovProps, useLovListMemo } from "./lovUtils";
import { useClassNames, useDispatch, useDynamicProperty, useModule } from "../../utils/hooks";
import { getUpdateVar } from "./utils";
import { emptyStyle, getSuffixedClassNames, getUpdateVar } from "./utils";
import { Icon, IconAvatar } from "../../utils/icon";
import { FormControlLabel } from "@mui/material";

const groupSx = {verticalAlign: "middle"};
const groupSx = { verticalAlign: "middle" };

interface ToggleProps extends LovProps<string> {
style?: CSSProperties;
label?: string;
kind?: string;
unselectedValue?: string;
allowUnselect?: boolean;
mode?: string;
isSwitch? : boolean;
}

const Toggle = (props: ToggleProps) => {
const {
id,
style = {},
kind,
style = emptyStyle,
label,
updateVarName = "",
propagate = true,
Expand All @@ -48,9 +50,18 @@ const Toggle = (props: ToggleProps) => {
unselectedValue = "",
updateVars = "",
valueById,
mode = "",
isSwitch = false,
} = props;
const dispatch = useDispatch();
const [value, setValue] = useState(props.defaultValue);
const [bVal, setBVal] = useState(() =>
typeof props.defaultValue === "boolean"
? props.defaultValue
: typeof props.value === "boolean"
? props.value
: false
);
const module = useModule();

const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
Expand All @@ -61,7 +72,7 @@ const Toggle = (props: ToggleProps) => {

const changeValue = useCallback(
(evt: MouseEvent, val: string) => {
if (!props.allowUnselect && val === null ) {
if (!props.allowUnselect && val === null) {
return;
}
dispatch(
Expand All @@ -73,36 +84,60 @@ const Toggle = (props: ToggleProps) => {
propagate,
valueById ? undefined : getUpdateVar(updateVars, "lov")
)
)},
[unselectedValue, updateVarName, propagate, dispatch, updateVars, valueById, props.onChange, props.allowUnselect, module]
);
},
[
unselectedValue,
updateVarName,
propagate,
dispatch,
updateVars,
valueById,
props.onChange,
props.allowUnselect,
module,
]
);

const changeSwitchValue = useCallback(
(evt: SyntheticEvent, checked: boolean) =>
dispatch(createSendUpdateAction(updateVarName, checked, module, props.onChange, propagate)),
[updateVarName, dispatch, props.onChange, propagate, module]
);

useEffect(() => {props.value !== undefined && setValue(props.value)}, [props.value]);
useEffect(() => {
typeof props.value === "boolean" ? setBVal(props.value) : props.value !== undefined && setValue(props.value);
}, [props.value]);

return kind === "theme" ? (
return mode.toLowerCase() === "theme" ? (
<ThemeToggle {...props} />
) : (
<Box id={id} sx={style} className={className}>
{label ? <Typography>{label}</Typography> : null}
{label && !isSwitch ? <Typography>{label}</Typography> : null}
<Tooltip title={hover || ""}>
<ToggleButtonGroup
value={value}
exclusive
onChange={changeValue}
disabled={!active}
sx={groupSx}
>
{lovList &&
lovList.map((v) => (
<ToggleButton value={v.id} key={v.id}>
{typeof v.item === "string" ? (
<Typography>{v.item}</Typography>
) : (
<IconAvatar id={v.id} img={v.item as Icon} />
)}
</ToggleButton>
))}
</ToggleButtonGroup>
{isSwitch ? (
<FormControlLabel
control={<Switch />}
checked={bVal}
onChange={changeSwitchValue}
disabled={!active}
label={label}
className={getSuffixedClassNames(className, "-switch")}
/>
) : (
<ToggleButtonGroup value={value} exclusive onChange={changeValue} disabled={!active} sx={groupSx}>
{lovList &&
lovList.map((v) => (
<ToggleButton value={v.id} key={v.id}>
{typeof v.item === "string" ? (
<Typography>{v.item}</Typography>
) : (
<IconAvatar id={v.id} img={v.item as Icon} />
)}
</ToggleButton>
))}
</ToggleButtonGroup>
)}
</Tooltip>
</Box>
);
Expand Down
4 changes: 3 additions & 1 deletion frontend/taipy-gui/src/components/Taipy/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* specific language governing permissions and limitations under the License.
*/

import { MouseEvent } from "react";
import { CSSProperties, MouseEvent } from "react";

export interface TaipyActiveProps extends TaipyDynamicProps, TaipyHoverProps {
defaultActive?: boolean;
Expand Down Expand Up @@ -109,3 +109,5 @@ export const getSuffixedClassNames = (names: string | undefined, suffix: string)
.split(/\s+/)
.map((n) => n + suffix)
.join(" ");

export const emptyStyle = {} as CSSProperties;
8 changes: 6 additions & 2 deletions taipy/gui/_renderers/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,14 @@ def set_value_and_default(
default_val (optional(Any)): the default value.
"""
var_name = self.__default_property_name if var_name is None else var_name
if var_type == PropertyType.slider_value:
if var_type == PropertyType.slider_value or var_type == PropertyType.toggle_value:
if self.__attributes.get("lov"):
var_type = PropertyType.lov_value
native_type = False
elif var_type == PropertyType.toggle_value:
self.__set_react_attribute(_to_camel_case("is_switch"), True)
var_type = PropertyType.dynamic_boolean
native_type = True
else:
var_type = (
PropertyType.dynamic_lo_numbers
Expand Down Expand Up @@ -832,7 +836,7 @@ def _set_input_type(self, type_name: str, allow_password=False):

def _set_kind(self):
if self.__attributes.get("theme", False):
self.set_attribute("kind", "theme")
self.set_attribute("mode", "theme")
return self

def __get_typed_hash_name(self, hash_name: str, var_type: t.Optional[PropertyType]) -> str:
Expand Down
11 changes: 4 additions & 7 deletions taipy/gui/_renderers/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ class _Factory:
]
),
"chart": lambda gui, control_type, attrs: _Builder(
gui=gui,
control_type=control_type,
element_name="Chart",
attributes=attrs,
default_value=None
gui=gui, control_type=control_type, element_name="Chart", attributes=attrs, default_value=None
)
.set_value_and_default(with_default=False, var_type=PropertyType.data)
.set_attributes(
Expand All @@ -104,7 +100,7 @@ class _Factory:
("template", PropertyType.dict),
("template[dark]", PropertyType.dict, gui._get_config("chart_dark_template", None)),
("template[light]", PropertyType.dict),
("figure", PropertyType.to_json)
("figure", PropertyType.to_json),
]
)
._get_chart_config("scatter", "lines+markers")
Expand Down Expand Up @@ -506,7 +502,7 @@ class _Factory:
"toggle": lambda gui, control_type, attrs: _Builder(
gui=gui, control_type=control_type, element_name="Toggle", attributes=attrs, default_value=None
)
.set_value_and_default(with_default=False, var_type=PropertyType.lov_value)
.set_value_and_default(with_default=False, var_type=PropertyType.toggle_value)
._get_adapter("lov", multi_selection=False) # need to be called before set_lov
._set_lov()
.set_attributes(
Expand All @@ -519,6 +515,7 @@ class _Factory:
("unselected_value", PropertyType.string, ""),
("allow_unselect", PropertyType.boolean),
("on_change", PropertyType.function),
("mode",),
]
)
._set_kind()
Expand Down
1 change: 1 addition & 0 deletions taipy/gui/gui_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class PropertyType(Enum):
"""
boolean_or_list = "boolean|list"
slider_value = "number|number[]|lovValue"
toggle_value = "boolean|lovValue"
string_list = "stringlist"
decimator = Decimator
"""
Expand Down
5 changes: 5 additions & 0 deletions taipy/gui/viselements.json
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@
"type": "bool",
"default_value": "False",
"doc": "If set, this allows de-selection and the value is set to unselected_value."
},
{
"name": "mode",
"type": "str",
"doc": "Define the way the toggle is displayed:<ul><li>&quote;theme&quote;: synonym for setting the *theme* property to True</li></ul>"
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion tests/gui/builder/control/test_toggle.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
def test_toggle_builder(gui: Gui, helpers):
with tgb.Page(frame=None) as page:
tgb.toggle(theme=True) # type: ignore[attr-defined]
expected_list = ["<Toggle", 'kind="theme"', 'unselectedValue=""']
expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""']
helpers.test_control_builder(gui, page, expected_list)


Expand Down
20 changes: 18 additions & 2 deletions tests/gui/control/test_toggle.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

def test_toggle_md(gui: Gui, helpers):
md_string = "<|toggle|theme|>"
expected_list = ["<Toggle", 'kind="theme"', 'unselectedValue=""']
expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""']
helpers.test_control_md(gui, md_string, expected_list)


Expand Down Expand Up @@ -44,7 +44,7 @@ def test_toggle_lov_md(gui: Gui, test_client, helpers):

def test_toggle_html_1(gui: Gui, helpers):
html_string = '<taipy:toggle theme="True" />'
expected_list = ["<Toggle", 'kind="theme"', 'unselectedValue=""']
expected_list = ["<Toggle", 'mode="theme"', 'unselectedValue=""']
helpers.test_control_html(gui, html_string, expected_list)


Expand All @@ -64,3 +64,19 @@ def test_toggle_html_2(gui: Gui, test_client, helpers):
"value={_TpLv_tpec_TpExPr_x_TPMDL_0}",
]
helpers.test_control_html(gui, html_string, expected_list)

def test_toggle_switch_md(gui: Gui, test_client, helpers):
gui._bind_var_val("x", True)
md_string = "<|{x}|toggle|label=Label|>"
expected_list = [
"<Toggle",
'isSwitch={true}',
'defaultValue={true}',
'libClassName="taipy-toggle"',
'updateVarName="_TpB_tpec_TpExPr_x_TPMDL_0"',
'value={_TpB_tpec_TpExPr_x_TPMDL_0}',
'label="Label"',
]
helpers.test_control_md(gui, md_string, expected_list)


1 comment on commit f8e90ad

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Taipy Overall Coverage Report
FileStmtsMissCoverMissing
__init__.py16193%31
_entrypoint.py36488%44, 46, 50–51
_run.py38294%77–78
version.py90100% 
_cli
   __init__.py00100% 
   _help_cli.py190100% 
   _run_cli.py251156%40, 42–46, 48–49, 51, 53, 59
   _scaffold_cli.py18288%41–42
_cli/_base_cli
   __init__.py10100% 
   _cli.py410100% 
config
   __init__.py38976%41–42, 44–49, 70
   _config.py61198%68
   _init.py30100% 
   config.py145497%87, 154, 178, 235
   section.py42685%35, 40, 44, 48, 53, 57
   setup.py15150%14–16, 18, 20–21, 23, 25–29, 31, 33, 35
   unique_section.py50100% 
   version.py90100% 
config/_config_comparator
   __init__.py00100% 
   _comparator_result.py95396%67, 110–111
   _config_comparator.py680100% 
config/_serializer
   __init__.py00100% 
   _base_serializer.py125596%39, 142–143, 145–146
   _json_serializer.py24387%33–35
   _toml_serializer.py230100% 
config/checker
   __init__.py00100% 
   _checker.py140100% 
   issue.py150100% 
   issue_collector.py280100% 
config/checker/_checkers
   __init__.py00100% 
   _auth_config_checker.py25250%12–14, 17–19, 21–24, 26–30, 32–34, 39–40, 47–49, 54–55
   _config_checker.py30196%28
config/common
   __init__.py00100% 
   _classproperty.py50100% 
   _config_blocker.py240100% 
   _repr_enum.py70100% 
   _template_handler.py1121190%39, 54, 56, 60, 62, 64, 100–101, 119, 150–151
   _validate_id.py100100% 
   frequency.py70100% 
   scope.py220100% 
   typing.py30100% 
config/exceptions
   __init__.py10100% 
   exceptions.py50100% 
config/global_app
   __init__.py00100% 
   global_app_config.py32196%38
core
   __init__.py70100% 
   _core.py560100% 
   _core_cli.py460100% 
   _init.py180100% 
   _init_version.py100100% 
   setup.py16160%14–16, 18, 20–21, 23–28, 30, 41, 43, 50
   taipy.py3884787%163, 219, 262, 267, 272, 277, 282, 287, 292, 297, 302, 340–342, 347, 352, 357, 362, 367, 372, 377, 382, 419–420, 422, 461, 490–491, 498–504, 530–533, 932, 971, 987, 1036–1040
core/_backup
   __init__.py00100% 
   _backup.py33293%54–55
core/_entity
   __init__.py00100% 
   _dag.py65198%94
   _entity.py220100% 
   _entity_ids.py220100% 
   _labeled.py480100% 
   _migrate_cli.py73494%97–98, 116–117
   _properties.py350100% 
   _reload.py62198%72
   submittable.py75494%47, 102, 106, 110
core/_entity/_migrate
   __init__.py30100% 
   _migrate_fs.py66592%43, 68, 104–106
   _migrate_mongo.py76593%52, 71, 87, 105, 127
   _migrate_sql.py1065350%30–31, 33–36, 38–46, 53, 57, 64–65, 69, 76–77, 81, 89–90, 94, 100–101, 105, 110–111, 115, 120–121, 125, 127–137, 139–140, 154, 198–199, 201–202
   _utils.py1993084%32, 34–36, 38, 59–61, 63–67, 69–71, 73–74, 157, 160, 169, 197–199, 202–204, 241–242, 316
core/_manager
   __init__.py00100% 
   _manager.py81198%113
   _manager_factory.py21290%28, 32
core/_orchestrator
   __init__.py00100% 
   _abstract_orchestrator.py23482%27, 40, 53, 58
   _orchestrator.py1941691%147, 191–194, 196–202, 204–206, 294
   _orchestrator_factory.py631084%38, 58, 73–74, 76, 79, 94, 97–98, 100
core/_orchestrator/_dispatcher
   __init__.py30100% 
   _development_job_dispatcher.py19478%26, 29, 32, 35
   _job_dispatcher.py88792%64–66, 88–89, 106, 124
   _standalone_job_dispatcher.py270100% 
   _task_function_wrapper.py57394%75–76, 84
core/_repository
   __init__.py00100% 
   _abstract_converter.py10280%19, 24
   _abstract_repository.py361072%29, 41, 53, 63, 73, 80, 90, 101, 113, 124
   _base_taipy_model.py31487%27–28, 50, 53
   _decoder.py21290%36, 51
   _encoder.py19384%30, 36, 41
   _filesystem_repository.py1592186%147, 173–174, 176, 178–181, 190–193, 197–200, 224, 237–238, 257–258
   _sql_repository.py1311687%79–80, 123, 137, 143–144, 147–148, 153–157, 163, 180, 216
core/_repository/db
   __init__.py00100% 
   _sql_base_model.py30100% 
   _sql_connection.py46295%82–83
core/_version
   __init__.py00100% 
   _utils.py260100% 
   _version.py140100% 
   _version_converter.py140100% 
   _version_fs_repository.py68592%44–45, 100–101, 134
   _version_manager.py149894%98, 104, 148–149, 171, 212, 220, 230
   _version_manager_factory.py19289%26, 29
   _version_mixin.py190100% 
   _version_model.py210100% 
   _version_repository_interface.py26773%22, 26, 30, 34, 38, 42, 46
   _version_sql_repository.py530100% 
core/_version/_cli
   __init__.py00100% 
   _bcolor.py241058%21, 23–25, 27–31, 33
   _version_cli.py138497%81, 85, 193, 195
core/common
   __init__.py10100% 
   _check_instance.py23195%49
   _listattributes.py29389%21–22, 32
   _mongo_connector.py17288%37, 45
   _repr_enum.py70100% 
   _utils.py390100% 
   _warnings.py210100% 
   mongo_default_document.py50100% 
   typing.py70100% 
   warn_if_inputs_not_ready.py140100% 
core/config
   __init__.py300100% 
   core_section.py182497%132, 141, 150, 163
   data_node_config.py350798%287, 291, 637, 639, 643, 645, 1044
   job_config.py73395%125–127
   migration_config.py46197%57
   scenario_config.py149497%211, 215, 223, 227
   task_config.py97792%70–71, 149, 152, 220–222
core/config/checkers
   __init__.py00100% 
   _config_id_checker.py180100% 
   _core_section_checker.py180100% 
   _data_node_config_checker.py91297%112, 147
   _job_config_checker.py190100% 
   _migration_config_checker.py300100% 
   _scenario_config_checker.py610100% 
   _task_config_checker.py340100% 
core/cycle
   __init__.py00100% 
   _cycle_converter.py110100% 
   _cycle_fs_repository.py60100% 
   _cycle_manager.py1010100% 
   _cycle_manager_factory.py20290%28, 31
   _cycle_model.py230100% 
   _cycle_sql_repository.py60100% 
   cycle.py109298%81, 147
   cycle_id.py30100% 
core/data
   __init__.py130100% 
   _abstract_file.py100100% 
   _abstract_sql.py1813083%95, 143, 145, 149, 162–163, 166–167, 179, 185, 187, 189, 195, 202, 230, 249–256, 263, 269, 285, 294–296, 302
   _abstract_tabular.py120100% 
   _data_converter.py175597%114, 183, 225, 258, 267
   _data_fs_repository.py60100% 
   _data_manager.py117298%93, 179
   _data_manager_factory.py20290%28, 31
   _data_model.py320100% 
   _data_sql_repository.py60100% 
   _filter.py1931791%41, 63, 83–91, 143, 183, 190, 205, 213, 222
   aws_s3.py36294%98, 101
   csv.py107496%92, 203, 207, 237
   data_node.py293797%158, 226, 278, 287, 464, 467, 471
   data_node_id.py50100% 
   excel.py204597%97, 278, 305, 343, 368
   generic.py48197%83
   in_memory.py280100% 
   json.py113595%91, 167, 171, 176, 180
   mongo.py1091288%201–208, 216, 226, 231, 283
   operator.py110100% 
   parquet.py110397%107, 122, 225
   pickle.py610100% 
   sql.py44197%100
   sql_table.py660100% 
core/exceptions
   __init__.py10100% 
   exceptions.py113496%183, 219, 257, 299
core/job
   __init__.py00100% 
   _job_converter.py31293%59–60
   _job_fs_repository.py60100% 
   _job_manager.py570100% 
   _job_manager_factory.py20290%28, 31
   _job_model.py260100% 
   _job_sql_repository.py60100% 
   job.py189696%30, 77, 149, 295, 312, 339
   job_id.py30100% 
   status.py110100% 
core/notification
   __init__.py70100% 
   _registration.py180100% 
   _topic.py23195%65
   core_event_consumer.py26196%84
   event.py40197%139
   notifier.py470100% 
   registration_id.py30100% 
core/scenario
   __init__.py00100% 
   _scenario_converter.py320100% 
   _scenario_fs_repository.py60100% 
   _scenario_manager.py273996%88–91, 183, 188, 384, 429, 440
   _scenario_manager_factory.py20290%28, 31
   _scenario_model.py300100% 
   _scenario_sql_repository.py60100% 
   scenario.py2971794%129, 132, 134–135, 177, 214, 246–250, 302, 345, 537, 539, 595, 601
   scenario_id.py30100% 
core/sequence
   __init__.py00100% 
   _sequence_converter.py190100% 
   _sequence_manager.py2371294%226, 240, 242, 245, 250, 256, 282–285, 352, 370
   _sequence_manager_factory.py11190%23
   sequence.py143397%80, 159, 171
   sequence_id.py30100% 
core/submission
   __init__.py00100% 
   _submission_converter.py140100% 
   _submission_fs_repository.py60100% 
   _submission_manager.py600100% 
   _submission_manager_factory.py20290%28, 31
   _submission_model.py250100% 
   _submission_sql_repository.py60100% 
   submission.py143795%112, 120, 141, 157, 160, 166, 214
   submission_id.py30100% 
   submission_status.py100100% 
core/task
   __init__.py00100% 
   _task_converter.py28196%68
   _task_fs_repository.py60100% 
   _task_manager.py121595%153–154, 159–160, 200
   _task_manager_factory.py20290%28, 31
   _task_model.py250100% 
   _task_sql_repository.py60100% 
   task.py107595%91, 96, 167–169
   task_id.py30100% 
gui
   __init__.py150100% 
   _default_config.py30100% 
   _gui_cli.py370100% 
   _gui_section.py300100% 
   _init.py10100% 
   _page.py32293%20–21
   _warnings.py110100% 
   config.py1101388%177, 180, 193, 201, 203, 207, 209, 211, 275–276, 281–282, 323
   gui.py122020183%40, 360, 362, 408–414, 417–424, 426–427, 429, 431–432, 434–436, 438–439, 441, 443–445, 447–450, 452–453, 455–460, 511, 522, 524, 526, 546, 571, 613, 615, 629, 633, 664, 671–672, 737, 746, 766, 783–784, 788–794, 796–801, 849, 858, 946, 948, 953–954, 957, 960–961, 963, 965, 969, 972, 979, 987–994, 996, 998, 1011–1015, 1017–1020, 1034–1036, 1043, 1045–1046, 1049, 1058, 1060–1062, 1070–1078, 1083, 1188–1189, 1254, 1256, 1270–1271, 1282, 1292, 1298, 1369, 1459–1461, 1471, 1480–1488, 1512, 1518, 1723, 1725, 1776, 1806–1808, 1810, 1813–1814, 1826, 1831–1833, 1835, 1893, 1939, 1950–1953, 1959, 1971–1976, 1996, 2003–2005, 2020, 2033, 2045, 2057, 2059, 2063–2064, 2073, 2189, 2198–2200, 2332, 2345, 2355, 2359
   gui_actions.py962771%61, 101, 133, 148, 174, 196–199, 220, 234, 238–239, 261–263, 289, 312–314, 318–319, 371, 380, 382, 387, 393
   gui_types.py91693%147, 152, 157, 164, 175, 177
   icon.py231630%58–63, 66–75
   page.py51688%21, 48, 50, 98, 109, 114
   partial.py27388%21, 66, 73
   server.py1753281%43, 69, 93, 111, 157–161, 164–165, 181–182, 212, 263, 265–266, 289, 298, 300, 305–306, 313–314, 316–318, 328, 330, 332, 335–336
   setup.py26260%14, 16–18, 20–21, 23, 25–30, 32, 51, 53, 63–67, 70–73, 76
   state.py1081784%24, 128, 140, 154, 180, 210–212, 222–223, 235–238, 241–242, 245
gui/_renderers
   __init__.py73987%21–22, 40, 49, 85–87, 91, 98
   builder.py66411382%45, 123, 142–143, 159–161, 163, 176, 203, 235–236, 240, 258–259, 263, 278, 296, 301–302, 306, 317, 334–337, 346, 349–351, 364, 377, 379–380, 383, 387–390, 392, 399, 441, 453, 499–502, 504–508, 510–513, 515–519, 529, 549, 566, 573, 578, 593, 600, 603–604, 606, 609, 613, 628, 635, 661, 673, 675–679, 682–683, 707, 710, 712, 798, 801, 824–825, 829, 861, 866–869, 871–874, 880–881, 891, 944, 961, 966, 973–977, 1000
   factory.py77396%20–21, 566
   json.py30873%26, 33–39
   utils.py66887%38–39, 54, 66–67, 78–79, 90
gui/_renderers/_html
   __init__.py10100% 
   factory.py9188%22
   parser.py98792%41–42, 70, 74, 108–109, 121
gui/_renderers/_markdown
   __init__.py18194%30
   blocproc.py35488%48–49, 67–68
   control.py110100% 
   factory.py140100% 
   postproc.py190100% 
   preproc.py122695%23, 103, 132, 136, 140, 199
gui/builder
   __init__.py40100% 
   _api_generator.py59689%25, 43, 45, 51, 70, 73
   _context_manager.py13192%17
   _element.py951089%24, 49–50, 65, 73, 78, 160, 171, 189, 192
   _factory.py9188%22
   page.py30970%57, 61–66, 70, 72
gui/custom
   __init__.py10100% 
   _page.py301260%28–32, 45, 48, 52, 63, 70, 79, 86
gui/data
   __init__.py30100% 
   array_dict_data_accessor.py40685%47–48, 50–51, 59, 66
   content_accessor.py961881%51, 58–60, 64, 66, 73, 85–86, 91–92, 109–110, 124–126, 128, 131
   data_accessor.py721579%27, 33, 37, 43, 48, 51, 72, 74, 77, 83, 87–88, 97–99
   data_format.py40100% 
   data_scope.py33293%55–56
   numpy_data_accessor.py21766%30, 33–35, 40–42
   pandas_data_accessor.py2366373%81, 83–92, 94, 96–103, 109, 117, 149–151, 156–159, 182, 205–210, 258–259, 275–276, 279, 288–290, 296–297, 307, 313–315, 349–353, 355, 360–361, 370–372, 402, 405
   utils.py592852%22, 53–54, 57–59, 82, 98, 118–119, 121–125, 127–133, 136, 138, 141–144
gui/data/decimator
   __init__.py40100% 
   lttb.py38294%53, 56
   minmax.py25196%45
   rdp.py64592%85, 112–114, 140
   scatter_decimator.py501374%62–63, 77–83, 87–90
gui/extension
   __init__.py20100% 
   library.py1391787%27–28, 62, 71, 75, 81, 132, 141, 143, 176, 240, 270, 349, 351, 364, 412, 422
gui/utils
   __init__.py220100% 
   _adapter.py1174462%39–40, 58–70, 82, 87, 92, 98–100, 103–108, 116, 126–133, 141–145, 149, 151, 153
   _attributes.py30583%16, 31–32, 39–40
   _bindings.py48197%20
   _evaluator.py2272887%22, 151, 170, 199–201, 243–247, 249–259, 269, 296, 312, 325–326, 337
   _locals_context.py480100% 
   _map_dict.py66592%34, 55, 70–71, 73
   _runtime_manager.py13284%17, 30
   _variable_directory.py100892%47–50, 61, 72, 84, 88
   boolean.py9188%27
   chart_config_builder.py1381291%23, 91–92, 107, 154–155, 195, 198–200, 266, 268
   clientvarname.py14285%23, 26
   datatype.py11372%20, 22, 24
   date.py17288%27, 30
   expr_var_name.py13192%23
   filename.py120100% 
   filter_locals.py50100% 
   get_imported_var.py110100% 
   get_module_name.py130100% 
   get_page_from_module.py5180%19
   getdatecolstrname.py8187%21
   html.py9188%22
   is_debugging.py3166%17
   is_port_open.py60100% 
   isnotebook.py10100% 
   proxy.py65650%12–17, 19–22, 24, 27, 29, 36–37, 40–46, 49, 52–53, 55–60, 62–63, 70–71, 73–79, 87–88, 91–95, 97–103, 106–109, 111–115
   singleton.py70100% 
   table_col_builder.py461860%21, 29, 38–40, 42, 52–54, 56, 59–61, 63, 66–68, 70
   types.py1493179%49–50, 104–110, 138–141, 144–146, 185–186, 195–199, 201–208
   varnamefromcontent.py6183%17
gui_core
   _GuiCoreLib.py340100% 
   __init__.py10100% 
   _adapters.py823853%59–64, 92–93, 95, 105, 108–121, 125, 138–139, 141, 158–164, 188–189, 191
   _context.py53920062%20–21, 159, 167–168, 196, 200–201, 214, 229–230, 239–245, 247–248, 251–254, 261–262, 265–270, 282, 309–313, 316–322, 324–333, 348, 350–353, 355–356, 365–369, 371, 376, 378–381, 383, 386, 389, 393–404, 409, 436, 455–462, 467–470, 473–475, 485–489, 496–497, 504–506, 513–514, 522–525, 545–546, 552, 564–565, 576–577, 587, 597–598, 603, 615, 617–618, 625, 631–634, 637–640, 649–651, 653, 657, 663, 670–676, 678–679, 688–689, 692, 699–706, 716–719, 733, 753–754, 776–778, 784–785, 803–804, 821–822, 839–840, 844–855
   _init.py50100% 
logger
   __init__.py00100% 
   _taipy_logger.py22290%30–31
rest
   __init__.py40100% 
   _init.py10100% 
   app.py200100% 
   extensions.py30100% 
   rest.py7185%45
   setup.py12120%11–12, 14, 16–17, 19–24, 26
   version.py90100% 
rest/api
   __init__.py20100% 
   error_handler.py49197%88
   views.py64493%165–166, 212–213
rest/api/exceptions
   __init__.py00100% 
   exceptions.py90100% 
rest/api/middlewares
   __init__.py00100% 
   _middleware.py14192%34
rest/api/resources
   __init__.py70100% 
   cycle.py490100% 
   datanode.py87396%465, 584, 603
   job.py70494%201–204
   scenario.py650100% 
   sequence.py66198%293
   task.py65198%202
rest/api/schemas
   __init__.py70100% 
   cycle.py100100% 
   datanode.py630100% 
   job.py120100% 
   scenario.py120100% 
   sequence.py100100% 
   task.py110100% 
rest/commons
   __init__.py00100% 
   apispec.py51982%35, 49, 84, 87, 91, 98–100, 103
   encoder.py13653%22–25, 27–28
   pagination.py14140%12, 14, 16–17, 20–23, 26–29, 36, 44
   to_from_model.py80100% 
templates/default/{{cookiecutter.__root_folder_name}}
   requirements.txt10100% 
   {{cookiecutter.__main_file}}.py00100% 
templates/default/{{cookiecutter.__root_folder_name}}/algorithms
   __init__.py110%12
   algorithms.py10100% 
templates/default/{{cookiecutter.__root_folder_name}}/configuration
   __init__.py110%12
   config.py3233%18, 20
templates/default/{{cookiecutter.__root_folder_name}}/pages
   __init__.py110%12
   root.py3233%19, 21
templates/default/{{cookiecutter.__root_folder_name}}/pages/page_example
   page_example.md00100% 
   page_example.py3233%19, 21
templates/default/{{cookiecutter.__root_folder_name}}/sections
   import.txt10100% 
   page_content.txt00100% 
templates/scenario-management/{{cookiecutter.__root_folder_name}}
   .taipyignore00100% 
templates/scenario-management/{{cookiecutter.__root_folder_name}}/algos
   __init__.py110%12
   algos.py3166%15
templates/scenario-management/{{cookiecutter.__root_folder_name}}/config
   __init__.py00100% 
   config.py9722%17, 22–25, 31, 34
   config.toml18950%3, 15–17, 19–22, 24
   config_with_toml.py440%12, 15–17
templates/scenario-management/{{cookiecutter.__root_folder_name}}/pages/job_page
   __init__.py110%12
   job_page.py2150%12
templates/scenario-management/{{cookiecutter.__root_folder_name}}/pages/scenario_page
   __init__.py110%12
   data_node_management.py141214%20–21, 26, 34–35, 42–43, 46–50
   scenario_page.py11109%12, 17–21, 23, 26–27, 30
TOTAL17390194388% 

Please sign in to comment.