Skip to content

Commit

Permalink
table: lov for column (#859)
Browse files Browse the repository at this point in the history
* table: lov for column
resolves #556

* Support for None as an indicator that the user can enter any value

* format

* format

---------

Co-authored-by: Fred Lefévère-Laoide <[email protected]>
  • Loading branch information
FredLL-Avaiga and Fred Lefévère-Laoide authored Feb 22, 2024
1 parent 2ed3aa5 commit 4ee6366
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 145 deletions.
296 changes: 160 additions & 136 deletions frontend/taipy-gui/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/taipy-gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"eslint-webpack-plugin": "^4.0.0",
"generate-json-webpack-plugin": "^2.0.0",
"html-webpack-plugin": "^5.5.0",
"husky": "^8.0.1",
"husky": "^9.0.11",
"jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3",
"jest-websocket-mock": "^2.2.1",
Expand Down
85 changes: 79 additions & 6 deletions frontend/taipy-gui/src/components/Taipy/tableUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,26 @@
* specific language governing permissions and limitations under the License.
*/

import React, { useState, useCallback, useEffect, useMemo, CSSProperties, MouseEvent } from "react";
import TableCell, { TableCellProps } from "@mui/material/TableCell";
import React, {
useState,
useCallback,
useEffect,
useMemo,
CSSProperties,
MouseEvent,
ChangeEvent,
SyntheticEvent,
} from "react";
import Autocomplete, { createFilterOptions } from "@mui/material/Autocomplete";
import Box from "@mui/material/Box";
import Input from "@mui/material/Input";
import TableCell, { TableCellProps } from "@mui/material/TableCell";
import Switch from "@mui/material/Switch";
import IconButton from "@mui/material/IconButton";
import CheckIcon from "@mui/icons-material/Check";
import ClearIcon from "@mui/icons-material/Clear";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
import Switch from "@mui/material/Switch";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
import { BaseDateTimePickerSlotsComponentsProps } from "@mui/x-date-pickers/DateTimePicker/shared";
Expand All @@ -29,6 +39,7 @@ import { isValid } from "date-fns";
import { FormatConfig } from "../../context/taipyReducers";
import { dateToString, getDateTime, getDateTimeString, getNumberString, getTimeZonedDate } from "../../utils/index";
import { TaipyActiveProps, TaipyMultiSelectProps, getSuffixedClassNames } from "./utils";
import { FilterOptionsState, TextField } from "@mui/material";

/**
* A column description as received by the backend.
Expand Down Expand Up @@ -65,6 +76,10 @@ export interface ColumnDesc {
/** The flag that allows the user to aggregate the column. */
groupBy?: boolean;
widthHint?: number;
/** The list of values that can be used on edit. */
lov?: string[];
/** If true the user can enter any value besides the lov values. */
freeLov?: boolean;
}

export const DEFAULT_SIZE = "small";
Expand Down Expand Up @@ -250,6 +265,10 @@ const setInputFocus = (input: HTMLInputElement) => input && input.focus();

const textFieldProps = { textField: { margin: "dense" } } as BaseDateTimePickerSlotsComponentsProps<Date>;

const filter = createFilterOptions<string>();
const getOptionKey = (option: string) => (Array.isArray(option) ? option[0] : option);
const getOptionLabel = (option: string) => (Array.isArray(option) ? option[1] : option);

export const EditableCell = (props: EditableCellProps) => {
const {
onValidation,
Expand All @@ -268,8 +287,9 @@ export const EditableCell = (props: EditableCellProps) => {
const [edit, setEdit] = useState(false);
const [deletion, setDeletion] = useState(false);

const onChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => setVal(e.target.value), []);
const onBoolChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => setVal(e.target.checked), []);
const onChange = useCallback((e: ChangeEvent<HTMLInputElement>) => setVal(e.target.value), []);
const onCompleteChange = useCallback((e: SyntheticEvent, value: string | null) => setVal(value), []);
const onBoolChange = useCallback((e: ChangeEvent<HTMLInputElement>) => setVal(e.target.checked), []);
const onDateChange = useCallback((date: Date | null) => setVal(date), []);

const withTime = useMemo(() => !!colDesc.format && colDesc.format.toLowerCase().includes("h"), [colDesc.format]);
Expand Down Expand Up @@ -327,7 +347,7 @@ export const EditableCell = (props: EditableCellProps) => {
);

const onKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
(e: React.KeyboardEvent<HTMLElement>) => {
switch (e.key) {
case "Enter":
onCheckClick();
Expand Down Expand Up @@ -375,6 +395,23 @@ export const EditableCell = (props: EditableCellProps) => {
[onSelection, rowIndex, colDesc.dfid]
);

const filterOptions = useCallback(
(options: string[], params: FilterOptionsState<string>) => {
const filtered = filter(options, params);
if (colDesc.freeLov) {
const { inputValue } = params;
if (
inputValue &&
!options.some((option) => inputValue == (Array.isArray(option) ? option[1] : option))
) {
filtered.push(inputValue);
}
}
return filtered;
},
[colDesc.freeLov]
);

useEffect(() => {
!onValidation && setEdit(false);
}, [onValidation]);
Expand Down Expand Up @@ -435,6 +472,42 @@ export const EditableCell = (props: EditableCellProps) => {
</IconButton>
</Box>
</Box>
) : colDesc.lov ? (
<Box sx={cellBoxSx}>
<Autocomplete
autoComplete={true}
fullWidth
selectOnFocus={!!colDesc.freeLov}
clearOnBlur={!!colDesc.freeLov}
handleHomeEndKeys={!!colDesc.freeLov}
options={colDesc.lov}
getOptionKey={getOptionKey}
getOptionLabel={getOptionLabel}
filterOptions={filterOptions}
freeSolo={!!colDesc.freeLov}
value={val as string}
onChange={onCompleteChange}
renderInput={(params) => (
<TextField
{...params}
fullWidth
inputRef={setInputFocus}
onChange={colDesc.freeLov ? onChange : undefined}
margin="dense"
variant="standard"
sx={tableFontSx}
/>
)}
/>
<Box sx={iconsWrapperSx}>
<IconButton onClick={onCheckClick} size="small" sx={iconInRowSx}>
<CheckIcon fontSize="inherit" />
</IconButton>
<IconButton onClick={onEditClick} size="small" sx={iconInRowSx}>
<ClearIcon fontSize="inherit" />
</IconButton>
</Box>
</Box>
) : (
<Input
value={val}
Expand Down
1 change: 1 addition & 0 deletions taipy/gui/_renderers/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class _Builder:
"apply",
"style",
"tooltip",
"lov"
]

def __init__(
Expand Down
2 changes: 1 addition & 1 deletion taipy/gui/_renderers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _get_columns_dict( # noqa: C901
if isinstance(columns, str):
col_dict = _get_columns_dict_from_list([s.strip() for s in columns.split(";")], col_types_keys, value)
elif isinstance(columns, (list, tuple)):
col_dict = _get_columns_dict_from_list(columns, col_types_keys, value)
col_dict = _get_columns_dict_from_list(columns, col_types_keys, value) # type: ignore[arg-type]
elif isinstance(columns, _MapDict):
col_dict = columns._dict.copy()
elif isinstance(columns, dict):
Expand Down
2 changes: 1 addition & 1 deletion taipy/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,7 @@ def _get_page(self, page_name: str):

def _bind_custom_page_variables(self, page: CustomPage, client_id: t.Optional[str]):
"""Handle the bindings of custom page variables"""
with self.get_flask_app().app_context() if has_app_context() else contextlib.nullcontext():
with self.get_flask_app().app_context() if has_app_context() else contextlib.nullcontext(): # type: ignore[attr-defined]
self.__set_client_id_in_context(client_id)
with self._set_locals_context(page._get_module_name()):
for k in self._get_locals_bind().keys():
Expand Down
16 changes: 16 additions & 0 deletions taipy/gui/utils/table_col_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,20 @@ def _enhance_columns( # noqa: C901
col_desc["tooltip"] = value
else:
_warn(f"{elt_name}: tooltip[{k}] is not in the list of displayed columns.")
if attributes.get("on_edit"):
lovs = _get_name_indexed_property(attributes, "lov")
for k, v in lovs.items(): # pragma: no cover
if col_desc := _get_column_desc(columns, k):
value = v.strip().split(";") if isinstance(v, str) else v # type: ignore[assignment]
if value is not None and not isinstance(value, (list, tuple)):
_warn(f"{elt_name}: lov[{k}] should be a list.")
value = None
if value is not None:
new_value = list(filter(lambda i: i is not None, value))
if len(new_value) < len(value):
col_desc["freeLov"] = True
value = new_value
col_desc["lov"] = value
else:
_warn(f"{elt_name}: lov[{k}] is not in the list of displayed columns.")
return columns
5 changes: 5 additions & 0 deletions taipy/gui/viselements.json
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,11 @@
"type": "dynamic(bool)",
"default_value": "False",
"doc": "If set to True, this allows to dynamically refresh the columns."
},
{
"name": "lov[<i>column_name</i>]",
"type": "list[str]|str",
"doc": "The list of values of the indicated column."
}
]
}
Expand Down

1 comment on commit 4ee6366

@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.py60198%68
   _init.py30100% 
   config.py145497%87, 154, 178, 233
   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.py124595%39, 141–142, 144–145
   _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.py1111190%39, 53, 55, 59, 61, 63, 99–100, 118, 149–150
   _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, 39, 41, 50
   taipy.py3904588%163, 219, 262, 267, 272, 277, 282, 287, 292, 297, 302, 340–342, 347, 352, 357, 362, 367, 372, 377, 382, 422, 461, 490–491, 498–504, 530–533, 941, 980, 996, 1045–1049
core/_backup
   __init__.py00100% 
   _backup.py33293%54–55
core/_entity
   __init__.py00100% 
   _dag.py65198%94
   _entity.py220100% 
   _entity_ids.py220100% 
   _labeled.py480100% 
   _migrate_cli.py74494%98–99, 117–118
   _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.py1891492%146, 190–191, 193–199, 201–203, 291
   _orchestrator_factory.py641182%38, 58, 73–74, 76, 79, 89, 94, 97–98, 100
core/_orchestrator/_dispatcher
   __init__.py30100% 
   _development_job_dispatcher.py19478%27, 30, 33, 36
   _job_dispatcher.py94891%69, 74–76, 99–100, 117, 135
   _standalone_job_dispatcher.py310100% 
   _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_dependencies.py5180%28
   _check_instance.py230100% 
   _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.py197597%139, 148, 157, 166, 179
   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.py170100% 
   _abstract_sql.py1833083%95, 143, 145, 149, 162–163, 166–167, 179, 185, 187, 189, 195, 202, 235, 254–261, 268, 274, 290, 299–301, 307
   _abstract_tabular.py45197%40
   _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.py40295%103, 106
   csv.py109397%91, 205, 209
   data_node.py293797%158, 226, 278, 287, 464, 467, 471
   data_node_id.py50100% 
   excel.py2022886%95, 279, 282, 284–288, 292–293, 296, 298–300, 302, 304–305, 307, 312, 314–315, 317–320, 322, 343, 365
   generic.py48197%83
   in_memory.py280100% 
   json.py115595%91, 170, 174, 179, 183
   mongo.py1131289%207–214, 222, 232, 237, 289
   operator.py110100% 
   parquet.py114397%107, 122, 230
   pickle.py630100% 
   sql.py44197%100
   sql_table.py660100% 
core/exceptions
   __init__.py10100% 
   exceptions.py118595%183, 191, 229, 267, 309
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.py187597%30, 77, 149, 295, 336
   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.py3191495%129, 132, 134–135, 177, 224, 243, 324, 366, 409, 601, 603, 659, 665
   scenario_id.py30100% 
core/sequence
   __init__.py00100% 
   _sequence_converter.py190100% 
   _sequence_manager.py2381294%227, 241, 243, 246, 251, 257, 283–286, 353, 371
   _sequence_manager_factory.py11190%23
   sequence.py144397%81, 160, 172
   sequence_id.py30100% 
core/submission
   __init__.py00100% 
   _submission_converter.py200100% 
   _submission_fs_repository.py60100% 
   _submission_manager.py600100% 
   _submission_manager_factory.py20290%28, 31
   _submission_model.py310100% 
   _submission_sql_repository.py60100% 
   submission.py171795%111, 119, 140, 186, 189, 195, 248
   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.py1101685%175, 177, 179–180, 184, 193, 201, 203, 207, 209, 211, 275–276, 281–282, 323
   gui.py125424580%41, 362, 364, 410–416, 419–426, 428–429, 431, 433–434, 436–438, 440–441, 443, 445–447, 449–452, 454–455, 457–462, 516, 527, 529, 531, 551, 574, 576, 589–590, 596–597, 618–623, 637, 641, 653, 667, 672, 679–680, 704–706, 716, 745, 754, 774, 791–792, 796–802, 804–809, 842–843, 857, 866, 954, 956, 961–962, 965, 968–969, 971, 973, 977, 979–980, 985, 987, 992, 998–1005, 1007, 1009, 1022–1026, 1028–1031, 1045–1047, 1054, 1056–1057, 1060, 1069–1078, 1083, 1087–1088, 1096, 1101, 1112–1119, 1151–1153, 1220–1221, 1286, 1288, 1293, 1302–1303, 1314, 1324, 1330, 1358, 1360–1361, 1414, 1504–1506, 1516, 1525–1533, 1557, 1563, 1719–1722, 1768, 1770, 1821, 1837, 1851–1853, 1855, 1858–1859, 1871, 1876–1878, 1880, 1938, 1952–1953, 1982, 1987, 1999–2002, 2008, 2020–2025, 2045, 2052–2054, 2069, 2082, 2094, 2106, 2108, 2112–2113, 2121–2123, 2137, 2253, 2385, 2398, 2408, 2412
   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.py92693%148, 153, 158, 165, 176, 178
   icon.py231630%58–63, 66–75
   page.py511864%21, 46, 48, 50, 55–57, 62–67, 98, 109, 112–114
   partial.py27388%21, 66, 73
   server.py1723778%42, 67, 91, 109, 152–158, 160–161, 174–175, 184, 187, 194, 205, 256, 258–259, 282, 291, 293, 298–299, 306–307, 309–311, 321, 323, 325, 328–329
   setup.py26260%14, 16–18, 20–21, 23, 25–30, 32, 51, 53, 63–67, 70–73, 76
   state.py1081883%24, 128, 140, 154, 180, 195, 210–212, 222–223, 235–238, 241–242, 245
gui/_renderers
   __init__.py731086%21–22, 40, 49, 60, 85–87, 91, 98
   builder.py66411382%45, 124, 143–144, 160–162, 164, 177, 204, 236–237, 241, 259–260, 264, 279, 297, 302–303, 307, 318, 335–338, 347, 350–352, 365, 378, 380–381, 384, 388–391, 393, 400, 442, 454, 500–503, 505–509, 511–514, 516–520, 530, 550, 567, 574, 579, 594, 601, 604–605, 607, 610, 614, 629, 636, 662, 674, 676–680, 683–684, 708, 711, 713, 799, 802, 825–826, 830, 862, 867–870, 872–875, 881–882, 892, 945, 962, 967, 974–978, 1001
   factory.py78396%20–21, 578
   json.py351265%27, 34–44
   utils.py66887%38–39, 54, 66–67, 78–79, 90
gui/_renderers/_html
   __init__.py10100% 
   factory.py9188%22
   parser.py981386%41–42, 52–53, 63, 70, 74, 82–83, 108–109, 121, 134
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.py37294%61–62
   numpy_data_accessor.py21766%30, 33–35, 40–42
   pandas_data_accessor.py2406572%81, 83–92, 94, 96–103, 109, 117, 149–151, 156–159, 182, 204, 207–212, 231, 262–263, 279–280, 283, 292–294, 300–301, 311, 317–319, 353–357, 359, 364–365, 374–376, 406, 409
   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.py1391887%27–28, 62, 71, 75, 81, 132, 141, 143, 176, 240, 270, 343, 349, 351, 364, 412, 422
gui/utils
   __init__.py220100% 
   _adapter.py1175453%39–40, 44–45, 48–55, 58–70, 82, 87, 92, 98–100, 103–108, 116, 126–133, 141–145, 149, 151, 153
   _attributes.py30776%16, 31–32, 39–40, 56–57
   _bindings.py50198%20
   _evaluator.py2284281%22, 124–126, 149, 151, 161, 169–170, 199–201, 244–248, 250–260, 270, 290–293, 295–298, 301, 313, 326–327, 338
   _locals_context.py48295%54, 60
   _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.py17382%27, 30–31
   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.py481960%21, 29, 38–40, 42, 52–54, 56, 59–61, 63, 66–68, 70, 116
   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, 100–101, 103, 113, 116–129, 133, 146–147, 149, 166–172, 196–197, 199
   _context.py57322161%21–22, 163, 172–173, 199, 203–204, 217, 232–233, 242–248, 250–251, 254–257, 264–265, 268–273, 285, 312–316, 319–325, 327–336, 351, 353–356, 358–359, 368–372, 374, 379, 381–384, 386, 389, 392, 396–407, 412, 423, 435–436, 438–443, 445, 449, 458, 464, 480–487, 492–495, 498–500, 510–514, 521–522, 529–531, 538–539, 547–550, 570–571, 577, 589–590, 601–602, 612, 622–623, 628, 640, 642–643, 650, 656, 659–662, 665–668, 677–679, 681, 685, 691, 698–704, 706–707, 716–717, 722, 725, 728, 735–742, 749–752, 758–761, 775, 795–796, 818–820, 826–827, 846–848, 864, 867–868, 885–886, 890–901
   _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
TOTAL17626209288% 

Please sign in to comment.