From 763a79809edb4a590f367938717971dd9ca27109 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Thu, 14 Nov 2024 10:38:17 +0000 Subject: [PATCH 01/54] Apply mdformat and manual fixes: broken yaml blocks, empty yaml blocks, add some FIXME --- .github/pull_request_template.md | 10 +- .pre-commit-config.yaml | 9 + CODE_OF_CONDUCT.md | 55 +-- CONTRIBUTING.md | 3 +- README.md | 15 +- vizro-ai/README.md | 7 +- ...y_snigir_automatic_vizro_ai_score_tests.md | 6 + .../changelog.d/20241108_083647_runner.md | 6 + ...20241108_085722_maximilian_schulz_0_3_2.md | 6 + ...8_102707_maximilian_schulz_some_cleanup.md | 6 + ...atkusic_graca_add_risk_mitigation_links.md | 6 + vizro-ai/docs/index.md | 29 +- vizro-ai/docs/pages/explanation/disclaimer.md | 15 +- vizro-ai/docs/pages/explanation/faq.md | 15 +- vizro-ai/docs/pages/explanation/safeguard.md | 86 ++-- .../pages/explanation/safety-in-vizro-ai.md | 45 +- .../pages/tutorials/quickstart-dashboard.md | 11 +- vizro-ai/docs/pages/tutorials/quickstart.md | 45 +- .../add-generated-chart-usecase.md | 34 +- .../docs/pages/user-guides/chart-examples.md | 23 +- .../user-guides/create-advanced-charts.md | 28 +- .../user-guides/create-complex-dashboard.md | 11 +- .../pages/user-guides/customize-vizro-ai.md | 50 ++- .../user-guides/retrieve-dashboard-code.md | 15 +- .../docs/pages/user-guides/run-vizro-ai.md | 29 +- .../user-guides/use-different-languages.md | 14 +- .../user-guides/vizro-ai-langchain-guide.md | 15 +- vizro-core/CHANGELOG.md | 45 +- vizro-core/README.md | 18 +- .../20241030_104644_antony.milne_0_1_26.md | 6 + .../changelog.d/20241030_111845_runner.md | 6 + ...30_170000_antony.milne_vvv_link_targets.md | 6 + ...105_170003_antony.milne_new_interaction.md | 6 + ...06_104745_antony.milne_dynamic_filter_2.md | 4 + ...102_alexey_snigir_pytest_warning_ignore.md | 6 + ...112_120233_huong_li_nguyen_fix_404_page.md | 4 + ...sic_graca_add_banner_to_demo_dashboards.md | 6 + vizro-core/docs/index.md | 40 +- vizro-core/docs/pages/explanation/authors.md | 54 +-- .../docs/pages/explanation/contributing.md | 63 ++- .../explanation/documentation-style-guide.md | 86 ++-- vizro-core/docs/pages/explanation/faq.md | 120 ++---- .../docs/pages/explanation/your-examples.md | 44 +- .../pages/tutorials/explore-components.md | 164 +++----- .../docs/pages/tutorials/first-dashboard.md | 14 +- vizro-core/docs/pages/user-guides/actions.md | 251 ++++++----- vizro-core/docs/pages/user-guides/assets.md | 53 +-- .../docs/pages/user-guides/card-button.md | 393 +++++++++--------- .../docs/pages/user-guides/components.md | 5 +- .../docs/pages/user-guides/container.md | 51 +-- .../docs/pages/user-guides/custom-actions.md | 82 ++-- .../docs/pages/user-guides/custom-charts.md | 42 +- .../docs/pages/user-guides/custom-css.md | 230 +++++----- .../docs/pages/user-guides/custom-figures.md | 114 +++-- .../docs/pages/user-guides/custom-tables.md | 36 +- .../docs/pages/user-guides/dashboard.md | 95 +++-- vizro-core/docs/pages/user-guides/data.md | 82 ++-- .../docs/pages/user-guides/extensions.md | 43 +- vizro-core/docs/pages/user-guides/figure.md | 64 +-- vizro-core/docs/pages/user-guides/filters.md | 37 +- vizro-core/docs/pages/user-guides/graph.md | 98 ++--- vizro-core/docs/pages/user-guides/install.md | 4 +- .../pages/user-guides/kedro-data-catalog.md | 10 +- vizro-core/docs/pages/user-guides/layouts.md | 234 +++++------ .../docs/pages/user-guides/navigation.md | 58 ++- vizro-core/docs/pages/user-guides/pages.md | 134 +++--- .../docs/pages/user-guides/parameters.md | 33 +- vizro-core/docs/pages/user-guides/run.md | 22 +- .../docs/pages/user-guides/selectors.md | 39 +- vizro-core/docs/pages/user-guides/table.md | 251 +++++------ vizro-core/docs/pages/user-guides/tabs.md | 89 ++-- vizro-core/docs/pages/user-guides/themes.md | 61 ++- .../pages/user-guides/visual-formatting.md | 16 +- vizro-core/examples/README.md | 3 +- .../examples/visual-vocabulary/README.md | 27 +- 75 files changed, 1779 insertions(+), 2164 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 44e958f1c..ea40a09f2 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,8 +6,8 @@ - [ ] I acknowledge and agree that, by checking this box and clicking "Submit Pull Request": - - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. - - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. - - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. - - I have not referenced individuals, products or companies in any commits, directly or indirectly. - - I have not added data or restricted code in any commits, directly or indirectly. + - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. + - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. + - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. + - I have not referenced individuals, products or companies in any commits, directly or indirectly. + - I have not added data or restricted code in any commits, directly or indirectly. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 386ccc6a3..5fa161ada 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -83,6 +83,15 @@ repos: - stylelint-order@4.1.0 args: ["--fix"] + - repo: https://github.com/executablebooks/mdformat + rev: 0.7.18 + hooks: + - id: mdformat + args: [--ignore-missing-references, --wrap=no, --align-semantic-breaks-in-lists] + exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference + additional_dependencies: + - mdformat-mkdocs[recommended]==3.1.1 + - repo: https://github.com/errata-ai/vale rev: v3.8.0 hooks: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 421f29147..6173d9378 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,17 +2,11 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socioeconomic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences @@ -22,57 +16,34 @@ include: Examples of unacceptable behavior by participants include: -- The use of sexualised language or imagery and unwelcome sexual attention or - advances +- The use of sexualised language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. **Investigation Timeline:** The project team will make all reasonable efforts to initiate and conclude the investigation in a timely fashion. Depending on the type of investigation the steps and timeline for each investigation will vary. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html -[homepage]: https://www.contributor-covenant.org +For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 66bcc019a..31a65c178 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,3 @@ # Contributing -Contributions of all experience levels are welcome! If you're interested in making a contribution, -please refer to our [contributing guide](https://vizro.readthedocs.io/en/stable/pages/explanation/contributing/) for more information. +Contributions of all experience levels are welcome! If you're interested in making a contribution, please refer to our [contributing guide](https://vizro.readthedocs.io/en/stable/pages/explanation/contributing/) for more information. diff --git a/README.md b/README.md index be083bde8..43c26d456 100644 --- a/README.md +++ b/README.md @@ -11,19 +11,14 @@
-[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) -[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) -[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +FIXME: maybe use two new lines between each +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
-Documentation | -Get Started | -Vizro examples gallery +Documentation | Get Started | Vizro examples gallery
@@ -108,9 +103,7 @@ You can see Vizro in action by clicking on the following image or by visiting [t ## Visual vocabulary -Our visual vocabulary dashboard helps you to select and create various types of charts. It helps you decide when to use -each chart type, and offers sample Python code to create these charts with [Plotly](https://plotly.com/python/) and -embed them into a Vizro dashboard. +Our visual vocabulary dashboard helps you to select and create various types of charts. It helps you decide when to use each chart type, and offers sample Python code to create these charts with [Plotly](https://plotly.com/python/) and embed them into a Vizro dashboard. diff --git a/vizro-ai/README.md b/vizro-ai/README.md index 888b79af8..28fd2df39 100644 --- a/vizro-ai/README.md +++ b/vizro-ai/README.md @@ -2,11 +2,8 @@
-[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) -[![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) -[![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +FIXME: maybe use two new lines between each +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) Gif to demonstrate vizro-ai diff --git a/vizro-ai/changelog.d/20240917_174515_alexey_snigir_automatic_vizro_ai_score_tests.md b/vizro-ai/changelog.d/20240917_174515_alexey_snigir_automatic_vizro_ai_score_tests.md index f1f65e73c..aa45b72f1 100644 --- a/vizro-ai/changelog.d/20240917_174515_alexey_snigir_automatic_vizro_ai_score_tests.md +++ b/vizro-ai/changelog.d/20240917_174515_alexey_snigir_automatic_vizro_ai_score_tests.md @@ -10,36 +10,42 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17,14 +16,11 @@ and are responsible for obtaining their own suitable API key for the relevant mo Users acknowledge and agree that: -Any results, options, data, recommendations, analyses, code, -or other information (“Outputs”) generated by any third-party generative AI tools (“GenAI Tools”) may contain some inaccuracies, biases, illegitimate, potentially infringing, -or otherwise inappropriate content that may be mistaken, discriminatory, or misleading. +Any results, options, data, recommendations, analyses, code, or other information (“Outputs”) generated by any third-party generative AI tools (“GenAI Tools”) may contain some inaccuracies, biases, illegitimate, potentially infringing, or otherwise inappropriate content that may be mistaken, discriminatory, or misleading. McKinsey & Company: -(i) expressly disclaims the accuracy, adequacy, timeliness, reliability, merchantability, fitness for a particular purpose, non-infringement, -safety or completeness of any Outputs, +(i) expressly disclaims the accuracy, adequacy, timeliness, reliability, merchantability, fitness for a particular purpose, non-infringement, safety or completeness of any Outputs, (ii) shall not be liable for any errors, omissions, or other defects in, delays or interruptions in such Outputs, or for any actions taken in reliance thereon, and @@ -32,7 +28,6 @@ safety or completeness of any Outputs, The Outputs shall be verified and validated by the users and shall not be used without human oversight and as a sole basis for making decisions impacting individuals. -Users remain solely responsible for the use of the Output, in particular, the users will need to determine the level of human oversight needed to be given the context and use case, -as well as for informing the users’ personnel and other affected users about the nature of the GenAI Output. -Users are also fully responsible for their decisions, actions, use of Vizro and Vizro-AI and compliance with applicable laws, rules, and regulations, including but not limited to confirming that the Outputs do not infringe any third-party rights. +Users remain solely responsible for the use of the Output, in particular, the users will need to determine the level of human oversight needed to be given the context and use case, as well as for informing the users’ personnel and other affected users about the nature of the GenAI Output. Users are also fully responsible for their decisions, actions, use of Vizro and Vizro-AI and compliance with applicable laws, rules, and regulations, including but not limited to confirming that the Outputs do not infringe any third-party rights. + diff --git a/vizro-ai/docs/pages/explanation/faq.md b/vizro-ai/docs/pages/explanation/faq.md index 46dfcd2ce..9eb0fad6f 100644 --- a/vizro-ai/docs/pages/explanation/faq.md +++ b/vizro-ai/docs/pages/explanation/faq.md @@ -3,20 +3,11 @@ ## Who works on Vizro-AI? ### Current team members -[Alexey Snigir](https://github.com/l0uden), -[Anna Xiong](https://github.com/Anna-Xiong), -[Antony Milne](https://github.com/antonymilne), -[Dan Dumitriu](https://github.com/dandumitriu1), -[Huong Li Nguyen](https://github.com/huong-li-nguyen), -[Jo Stichbury](https://github.com/stichbury), -[Joseph Perkins](https://github.com/Joseph-Perkins), -[Lingyi Zhang](https://github.com/lingyielia), -[Maximilian Schulz](https://github.com/maxschulz-COL), -[Nadija Graca](https://github.com/nadijagraca), -[Petar Pejovic](https://github.com/petar-qb). -With thanks to Sam Bourton and Stephen Xu for sponsorship, inspiration and guidance, plus everyone else who helped to test, guide, support and encourage development. +[Alexey Snigir](https://github.com/l0uden), [Anna Xiong](https://github.com/Anna-Xiong), [Antony Milne](https://github.com/antonymilne), [Dan Dumitriu](https://github.com/dandumitriu1), [Huong Li Nguyen](https://github.com/huong-li-nguyen), [Jo Stichbury](https://github.com/stichbury), [Joseph Perkins](https://github.com/Joseph-Perkins), [Lingyi Zhang](https://github.com/lingyielia), [Maximilian Schulz](https://github.com/maxschulz-COL), [Nadija Graca](https://github.com/nadijagraca), [Petar Pejovic](https://github.com/petar-qb). +With thanks to Sam Bourton and Stephen Xu for sponsorship, inspiration and guidance, plus everyone else who helped to test, guide, support and encourage development. ## Which large language models are supported by vizro-ai? + Refer to [supported models](../user-guides/customize-vizro-ai.md#supported-models) in `vizro-ai` docs. diff --git a/vizro-ai/docs/pages/explanation/safeguard.md b/vizro-ai/docs/pages/explanation/safeguard.md index f4311fcd6..7b2857fb9 100644 --- a/vizro-ai/docs/pages/explanation/safeguard.md +++ b/vizro-ai/docs/pages/explanation/safeguard.md @@ -1,88 +1,70 @@ # Safeguard dynamic code execution in Vizro-AI -Vizro-AI uses the `exec()` statement in Python to run generated code from large language models (LLMs) for -self-debugging and automatic visual rendering in methods such as `.get_fig_object()` and `VizroAI.plot()`. -One of the primary concerns is the potential for malicious code to access or change critical system resources or data. +Vizro-AI uses the `exec()` statement in Python to run generated code from large language models (LLMs) for self-debugging and automatic visual rendering in methods such as `.get_fig_object()` and `VizroAI.plot()`. One of the primary concerns is the potential for malicious code to access or change critical system resources or data. ## Understand `exec()` -The `exec()` function enables the dynamic execution of Python programs which can either be a string or object code. -While it offers great flexibility, it also poses a significant security risk, especially when executing untrusted code. +The `exec()` function enables the dynamic execution of Python programs which can either be a string or object code. While it offers great flexibility, it also poses a significant security risk, especially when executing untrusted code. ## Safeguarding code execution -While we have made considerable efforts to safeguard its usage by limiting the usage to specific modules and functions and by restricting certain built-in operations, -these measures cannot guarantee absolute security. It is imperative for users to take extra precautions. +While we have made considerable efforts to safeguard its usage by limiting the usage to specific modules and functions and by restricting certain built-in operations, these measures cannot guarantee absolute security. It is imperative for users to take extra precautions. ### Our effort on safeguarding code execution in Vizro-AI -To help to mitigate these risks, we limit the execution of certain modules and functions. -One approach is to use Python's built-in `sys` module to restrict access to unsafe modules or functions. -By defining a whitelist of safe modules and packages and restricting certain built-in functions. +To help to mitigate these risks, we limit the execution of certain modules and functions. One approach is to use Python's built-in `sys` module to restrict access to unsafe modules or functions. By defining a whitelist of safe modules and packages and restricting certain built-in functions. !!! Warning - - While some measures have been put in place to help safeguard against known vulnerabilities, - it is important to run such systems in an isolated environment and avoid providing malicious inputs, - since such **safeguards can never be 100% effective**. Always ensure the security infrastructure when implementing and using such systems. + While some measures have been put in place to help safeguard against known vulnerabilities, it is important to run such systems in an isolated environment and avoid providing malicious inputs, since such **safeguards can never be 100% effective**. Always ensure the security infrastructure when implementing and using such systems. The white lists indicate allowed packages and built-in functions. - The red lists represent potentially - unsafe methods or operations that are restricted. + The red lists represent potentially unsafe methods or operations that are restricted. The lists below are a reflection of the security and functionality we have implemented with Vizro-AI: ??? success "Whitelisted Packages" - - - `pandas` - - `numpy` - - `vizro` - - `plotly` - - `datetime` - - `matplotlib` - - `dash` - - `scipy` - - `sklearn` + - `pandas` + - `numpy` + - `vizro` + - `plotly` + - `datetime` + - `matplotlib` + - `dash` + - `scipy` + - `sklearn` ??? success "Whitelisted Builtins" - - - abs - - len - - max - - min - - print - - sum - - None - - False - - True - - dict - - enumerate - - float - - int - - list - - map - - str - - tuple + - abs + - len + - max + - min + - print + - sum + - None + - False + - True + - dict + - enumerate + - float + - int + - list + - map + - str + - tuple ??? failure "Redlisted Class Methods" - - subclasses - builtins ??? failure "Redlisted Data Handling Methods and Formats" - - Various data file formats (such as .csv, .tsv, .xlsx, .json, and so on) - Specific methods related to data input/output operations (such as .to_csv, .read_excel, .loadtxt) ### Safeguard for user environment and input -- **Isolated environment**: Always run code in an isolated or contained environment, such as a virtual environment, - virtual machine or container, to minimize potential harm to the primary system. +- **Isolated environment**: Always run code in an isolated or contained environment, such as a virtual environment, virtual machine or container, to minimize potential harm to the primary system. -- **Avoid malicious input**: Never feed untrusted or malicious input. Regardless of safeguards, - there's always a risk associated with executing dynamic code. - It remains the user's responsibility to ensure the safety and appropriateness of executing any generated code, - particularly in sensitive or critical contexts. +- **Avoid malicious input**: Never feed untrusted or malicious input. Regardless of safeguards, there's always a risk associated with executing dynamic code. It remains the user's responsibility to ensure the safety and appropriateness of executing any generated code, particularly in sensitive or critical contexts. - **Accessible to trusted users**: Only trusted users should be given access to the system to run Vizro-AI. diff --git a/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md b/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md index 669f01d30..dc5a149f8 100644 --- a/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md +++ b/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md @@ -4,60 +4,63 @@ Vizro-AI uses generative AI models because large language models (LLMs) represen We recommend users research and understand the selected model before using `vizro_ai` package. -Users are encouraged to treat AI-generated content as supplementary, **always apply human judgment**, -approach with caution, review the relevant [disclaimer](disclaimer.md) page, and consider the following: +Users are encouraged to treat AI-generated content as supplementary, **always apply human judgment**, approach with caution, review the relevant [disclaimer](disclaimer.md) page, and consider the following: + + ### 1. Hallucination and misrepresentation Generative models can potentially generate information while appearing factual, being entirely fictitious or misleading. + -The vendor models might lack real-time knowledge or events beyond its last updates. -`vizro_ai` output may vary and you should always verify critical information. -It is the user's responsibility to discern the accuracy, consistent, and reliability of the generated content. + +The vendor models might lack real-time knowledge or events beyond its last updates. `vizro_ai` output may vary and you should always verify critical information. It is the user's responsibility to discern the accuracy, consistent, and reliability of the generated content. + ### 2. Unintended and sensitive output + -The outputs from these models can be unexpected, inappropriate, or even harmful. -Users as human in the loop is an essential part. Users must check and interpret the final output. -It is necessary to approach the generated content with caution, especially when shared or applied in various contexts. + +The outputs from these models can be unexpected, inappropriate, or even harmful. Users as human in the loop is an essential part. Users must check and interpret the final output. It is necessary to approach the generated content with caution, especially when shared or applied in various contexts. + ### 3. Data privacy + -Your data is sent to model vendors if you connect to LLMs via their APIs. -For example, if you connect to the model from OpenAI, your data will be sent to OpenAI via their API. -Users should be cautious about sharing or inputting any personal or sensitive information. + +Your data is sent to model vendors if you connect to LLMs via their APIs. For example, if you connect to the model from OpenAI, your data will be sent to OpenAI via their API. Users should be cautious about sharing or inputting any personal or sensitive information. + ### 4. Bias and fairness + -Generative AI can exhibit biases present in their training data. -Users need to be aware of and navigate potential biases in generated outputs and be cautious when interpreting the generated content. + +Generative AI can exhibit biases present in their training data. Users need to be aware of and navigate potential biases in generated outputs and be cautious when interpreting the generated content. + ### 5. Malicious use + + These models can be exploited for various malicious activities. Users should be cautious about how and where they deploy and access such models. It's crucial for users to remain informed, cautious, and ethical in their applications. - ## Dependencies, code scanners, and information security -It may occur that dependencies of `vizro_ai` get flagged by code scanners and other information security tools. As a consequence it may happen that -`vizro_ai` also get flagged. +It may occur that dependencies of `vizro_ai` get flagged by code scanners and other information security tools. As a consequence it may happen that `vizro_ai` also get flagged. -While we aim to resolve any flagged issues as soon as possible, there may not always be an immediate available fix, especially in a dynamic environment such as generative AI. We encourage users to investigate if any flagged information security issues are actually related -to any functionality used in our code base or if they only concern functionality outside the scope of `vizro_ai`. +While we aim to resolve any flagged issues as soon as possible, there may not always be an immediate available fix, especially in a dynamic environment such as generative AI. We encourage users to investigate if any flagged information security issues are actually related to any functionality used in our code base or if they only concern functionality outside the scope of `vizro_ai`. In case those issues are related to code execution, note that `vizro_ai` has its own process of executing dynamic code (see [Safeguard Execution of Dynamic Code](safeguard.md)), and does not rely on its dependencies to do so. - ## Execution of dynamic code in Vizro-AI -The `exec()` statement is used in `vizro_ai`. It enables dynamic execution of Python programs which can be powerful, but can also pose security risk -if used without caution. When paired with outputs from generative models, there is potential for unintended or malicious code execution. +The `exec()` statement is used in `vizro_ai`. It enables dynamic execution of Python programs which can be powerful, but can also pose security risk if used without caution. When paired with outputs from generative models, there is potential for unintended or malicious code execution. Users must exercise caution when executing code generated by or influenced by AI models. It's essential to: diff --git a/vizro-ai/docs/pages/tutorials/quickstart-dashboard.md b/vizro-ai/docs/pages/tutorials/quickstart-dashboard.md index c29607baa..2118112d7 100644 --- a/vizro-ai/docs/pages/tutorials/quickstart-dashboard.md +++ b/vizro-ai/docs/pages/tutorials/quickstart-dashboard.md @@ -8,12 +8,11 @@ You may also want to review the [Vizro dashboard tutorial](https://vizro.readthe If you haven't already installed Vizro-AI and set up the API key for OpenAI, follow the [installation guide](../user-guides/install.md). - ## 2. Open a Notebook + A good way to initially explore Vizro-AI is from inside a Jupyter Notebook. ??? "If you haven't used Jupyter before..." - You may need to install the Jupyter package if you . From the terminal window: ```bash @@ -39,6 +38,7 @@ print(vizro_ai.__version__) You should see a return output of the form `x.y.z`. ## 3. Instantiate VizroAI + ```py from vizro_ai import VizroAI @@ -46,6 +46,7 @@ vizro_ai = VizroAI() ``` ## 4. Prepare the data + Next, prepare the data to pass to Vizro-AI. In this example, we use the [gapminder data](https://plotly.com/python-api-reference/generated/plotly.express.data.html#plotly.express.data.gapminder). ```py @@ -87,6 +88,7 @@ dashboard = vizro_ai.dashboard([df], user_question) The call to `dashboard()` initiates dashboard generation. By default, it generates the Vizro `Dashboard` Object. ## 7. Build dashboard + Once dashboard generation is complete, launch the dashboard with `build()`. ```py @@ -95,7 +97,6 @@ Vizro().build(dashboard).run() ``` !!! example "Generated dashboard" - === "Code for the cell" ```py from vizro import Vizro @@ -119,6 +120,6 @@ Vizro().build(dashboard).run() ``` === "Result" - [![VizroAIDashboardPage1]][VizroAIDashboardPage1] + [![VizroAIDashboardPage1]][vizroaidashboardpage1] - [VizroAIDashboardPage1]: ../../assets/tutorials/dashboard/dashboard0_page1.png +[vizroaidashboardpage1]: ../../assets/tutorials/dashboard/dashboard0_page1.png diff --git a/vizro-ai/docs/pages/tutorials/quickstart.md b/vizro-ai/docs/pages/tutorials/quickstart.md index 17d673927..64574cd77 100644 --- a/vizro-ai/docs/pages/tutorials/quickstart.md +++ b/vizro-ai/docs/pages/tutorials/quickstart.md @@ -1,20 +1,24 @@ # Chart generation + This tutorial introduces you to chart generation using Vizro-AI. It explains the basics of creating a plotly chart that can be added to a Vizro dashboard. When you have followed it, you are set up to explore the Vizro and Vizro-AI packages further. + ### 1. Install Vizro-AI and its dependencies + If you haven't already installed Vizro-AI and set up the API key for OpenAI, follow the [installation guide](../user-guides/install.md). + ### 2. Open a Jupyter Notebook + A good way to initially explore Vizro-AI is from inside a Jupyter Notebook. ??? "If you haven't used Jupyter before..." - You may need to install the Jupyter package if you . From the terminal window: ```bash @@ -40,7 +44,9 @@ print(vizro_ai.__version__) You should see a return output of the form `x.y.z`. + ### 3. Create your first plotly chart using Vizro-AI + Let's create a chart to illustrate the GDP of various continents while including a reference line for the average. We give Vizro-AI the English language instruction "*describe the composition of GDP in continent and color by continent, and add a horizontal line for avg GDP*". @@ -54,12 +60,12 @@ import vizro.plotly.express as px df = px.data.gapminder() ``` - Next, we instantiate `VizroAI`: ```python vizro_ai = VizroAI() ``` + To learn how to customize the `VizroAI` class, check out the guide on [how to customize models](../user-guides/customize-vizro-ai.md). Finally, we call the `plot()` method with our English language instruction, to generate the visualization: @@ -74,7 +80,6 @@ vizro_ai.plot( ``` !!! warning "Help! The LLM request was unauthorized" - If you see an error similar to this, your LLM API key is not valid: `INFO:httpx:HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 401 Unauthorized"` @@ -83,12 +88,11 @@ vizro_ai.plot( `export OPENAI_API_KEY="sk-YOURKEY"`. - The call above makes the API key available from that terminal instance. If you want to access Vizro-AI from a Notebook, you should then run `jupyter notebook` (or just work within that terminal to run your Python script in `app.py`. When you restart the terminal, you'll need to call `export` again. + The call above makes the API key available from that terminal instance. If you want to access Vizro-AI from a Notebook, you should then run `jupyter notebook` (or just work within that terminal to run your Python script in `app.py`. When you restart the terminal, you'll need to call `export` again. And that's it! By passing the prepared data and written visualization request, Vizro-AI takes care of the processing. It generates the necessary code for data manipulation and chart creation, and returns the chart by executing the generated code. !!! example "Vizro-AI Syntax" - === "Code for the cell" ```py import vizro.plotly.express as px @@ -104,38 +108,40 @@ And that's it! By passing the prepared data and written visualization request, V Make sure to take average over continent.""", ) ``` - === "Result" - [![LineGraph]][LineGraph] - [LineGraph]: ../../assets/tutorials/chart/GDP_Composition_Graph.png + === "Result" + [![LineGraph]][linegraph] The chart created is interactive: you can hover over the data for more information. Passing `return_elements=True` to the `plot()` method returns an object, which includes the code along with a set of insights to explain the rendered chart in detail. You can then use the code within a Vizro dashboard as illustrated in the [Vizro documentation](https://vizro.readthedocs.io/en/stable/pages/tutorials/explore-components/#22-add-further-components). For the line graph above, the code returned may be as follows: !!! example "Returned by Vizro-AI" - ```python from vizro.models.types import capture import vizro.plotly.express as px import pandas as pd - @capture('graph') + + + @capture("graph") def custom_chart(data_frame): - df = data_frame.groupby(['year', 'continent'])['gdpPercap'].mean().unstack().reset_index() - fig = px.line(df, x='year', y=['Africa', 'Americas', 'Asia', 'Europe', 'Oceania']) + df = data_frame.groupby(["year", "continent"])["gdpPercap"].mean().unstack().reset_index() + fig = px.line(df, x="year", y=["Africa", "Americas", "Asia", "Europe", "Oceania"]) return fig + fig = custom_chart(data_frame=df) ``` + ### 4. Get an explanation with your chart + Let's create another example to illustrate the code and insights returned when passing `return_elements=True` as a parameter to `plot()`: !!! example "Specify `return_elements=True`" - === "Code for the cell" ```py res = vizro_ai.plot(df, "show me the geo distribution of life expectancy", return_elements=True) @@ -143,8 +149,10 @@ Let's create another example to illustrate the code and insights returned when p print(res.chart_insights) print(res.code_explanation) ``` + === "Result" Code + ```py import plotly.express as px @@ -164,13 +172,17 @@ Let's create another example to illustrate the code and insights returned when p ) return fig ``` + Chart insights + ``` This choropleth map visualizes the global distribution of life expectancy across different countries. It highlights variations and trends in life expectancy, providing a clear visual representation of geographical disparities. ``` + Code explanation + ``` - Import Plotly Express. - Create a choropleth map using the `px.choropleth` function. @@ -180,13 +192,14 @@ Let's create another example to illustrate the code and insights returned when p - Update layout to enhance map readability and aesthetics. ``` - [GeoDistribution]: ../../assets/tutorials/chart/GeoDistribution.png - + ### 5. Explore further - + Congratulations! You have created your first charts with Vizro-AI and you are ready to explore further. A good place to start would be to review the different how-to guides to learn [the different ways to run Vizro-AI](../user-guides/run-vizro-ai.md), [how to create advanced charts](../user-guides/create-advanced-charts.md) and [how to add your Vizro-AI charts to a Vizro dashboard](../user-guides/add-generated-chart-usecase.md). You may also want to review the tutorial on [how to generate a Vizro dashboard with Vizro-AI](quickstart-dashboard.md) + +[linegraph]: ../../assets/tutorials/chart/GDP_Composition_Graph.png diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index fa87f16e1..90564f948 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -2,16 +2,14 @@ This guide explains the different ways in which you can add a chart generated by Vizro-AI to an existing [Vizro dashboard](https://github.com/mckinsey/vizro/tree/main/vizro-core). -## Use Vizro-AI's generated code +## Use Vizro-AI's generated code 1. Create a chart with Vizro-AI that you would like to visualize in a dashboard. In this example, we aim to create a chart that illustrates the population development of each continent over time. To gain deeper insights and access the underlying code responsible for generating the chart, include `return_elements=True` in the `plot()` method. Let's execute the provided code and examine the outcome. !!! example "Vizro-AI chart" - === "Code for the cell" - ```py import vizro_ai from vizro_ai import VizroAI @@ -34,12 +32,11 @@ This guide explains the different ways in which you can add a chart generated by print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n" ) result.get_fig_object(df).show() ``` - === "Result" - [![VizroAIChart]][VizroAIChart] - [VizroAIChart]: ../../assets/user_guides/vizro-ai-chart.png + === "Result" + [![VizroAIChart]][vizroaichart] -2. Insert the resulting chart into a dashboard. +1. Insert the resulting chart into a dashboard. Once you are satisfied with the chart, you can add it to a [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard. @@ -62,11 +59,9 @@ This guide explains the different ways in which you can add a chart generated by return fig ``` -The `custom_chart` function is an example of the [custom chart](https://vizro.readthedocs.io/en/stable/pages/user-guides/custom-charts). It returns a `go.Figure()` object. -This object must then be passed to the `figure` argument of the Vizro [Graph](https://vizro.readthedocs.io/en/stable/pages/user-guides/graph) model. +The `custom_chart` function is an example of the [custom chart](https://vizro.readthedocs.io/en/stable/pages/user-guides/custom-charts). It returns a `go.Figure()` object. This object must then be passed to the `figure` argument of the Vizro [Graph](https://vizro.readthedocs.io/en/stable/pages/user-guides/graph) model. !!! example "Vizro-AI chart within vizro dashboard" - === "Code for the cell" ```py hl_lines="8-23 31" from vizro import Vizro @@ -111,24 +106,18 @@ This object must then be passed to the `figure` argument of the Vizro [Graph](ht Vizro().build(vm.Dashboard(pages=[page])).run(port=8090) ``` - === "Result" - [![VizroDashboard]][VizroDashboard] - - [VizroDashboard]: ../../assets/user_guides/chart_into_dashboard_large.png + === "Result" + [![VizroDashboard]][vizrodashboard] ## Use Vizro-AI dynamically to return a `fig` object -We can also use Vizro-AI dynamically and assign the output of `plot()` directly to the fig variable, enabling its reuse in the `vm.Graph.figure` argument. -This method offers streamlined efficiency, eliminating the need for code copying. -Note that each dashboard run triggers an API call to the LLM, possibly escalating costs. This can be avoided if the `fig` object is stored and retrieved as needed, instead of making repeated calls to `plot()`. +We can also use Vizro-AI dynamically and assign the output of `plot()` directly to the fig variable, enabling its reuse in the `vm.Graph.figure` argument. This method offers streamlined efficiency, eliminating the need for code copying. Note that each dashboard run triggers an API call to the LLM, possibly escalating costs. This can be avoided if the `fig` object is stored and retrieved as needed, instead of making repeated calls to `plot()`. Executing the code below yields the identical dashboard as the example above. - !!! example "Use Vizro-AI fig directly in vizro dashboard" === "Code for the cell" - ```py hl_lines="13-18 23" from vizro import Vizro import vizro.models as vm @@ -164,7 +153,10 @@ Executing the code below yields the identical dashboard as the example above. Vizro().build(vm.Dashboard(pages=[page])).run(port=8090) ``` + === "Result" - [![VizroDashboard2]][VizroDashboard2] + [![VizroDashboard2]][vizrodashboard2] - [VizroDashboard2]: ../../assets/user_guides/chart_into_dashboard_large.png +[vizroaichart]: ../../assets/user_guides/vizro-ai-chart.png +[vizrodashboard]: ../../assets/user_guides/chart_into_dashboard_large.png +[vizrodashboard2]: ../../assets/user_guides/chart_into_dashboard_large.png diff --git a/vizro-ai/docs/pages/user-guides/chart-examples.md b/vizro-ai/docs/pages/user-guides/chart-examples.md index 4721980c4..72384b707 100644 --- a/vizro-ai/docs/pages/user-guides/chart-examples.md +++ b/vizro-ai/docs/pages/user-guides/chart-examples.md @@ -4,14 +4,11 @@ Take a look at some more advanced charts that can be created with Vizro-AI using ### Polar bar chart -A polar bar chart is a circular graph where each axis represents a different variable, typically used for displaying cyclical or directional data. -It's suitable for comparing multiple variables across different categories or directions. Let's make one using Vizro-AI. - +A polar bar chart is a circular graph where each axis represents a different variable, typically used for displaying cyclical or directional data. It's suitable for comparing multiple variables across different categories or directions. Let's make one using Vizro-AI. !!! example "Polar Bar Chart" - === "Resulting chart" - [![VizroAIChart1]][VizroAIChart1] + [![VizroAIChart1]][vizroaichart1] === "Code for the cell" ```py @@ -32,17 +29,13 @@ It's suitable for comparing multiple variables across different categories or di fig.show() ``` - [VizroAIChart1]: ../../assets/user_guides/polar_bar_chart.png - - ### Geographical map chart The next chart we'll look at is a geographical map chart to visualize spatial patterns in data, which often reveals insights not seen in other charts. !!! example "Map chart" - === "Resulting chart" - [![VizroAIChart2]][VizroAIChart2] + [![VizroAIChart2]][vizroaichart2] === "Code for the cell" ```py @@ -64,17 +57,13 @@ The next chart we'll look at is a geographical map chart to visualize spatial pa fig.show() ``` - [VizroAIChart2]: ../../assets/user_guides/map_chart.gif - - ### 3D surface plot Let's explore how to generate a 3-dimensional surface plot with VizroAI. !!! example "Surface plot" - === "Resulting chart" - [![VizroAIChart3]][VizroAIChart3] + [![VizroAIChart3]][vizroaichart3] === "Code for the cell" ```py @@ -92,4 +81,6 @@ Let's explore how to generate a 3-dimensional surface plot with VizroAI. fig.show() ``` - [VizroAIChart3]: ../../assets/user_guides/surface_plot.gif +[vizroaichart1]: ../../assets/user_guides/polar_bar_chart.png +[vizroaichart2]: ../../assets/user_guides/map_chart.gif +[vizroaichart3]: ../../assets/user_guides/surface_plot.gif diff --git a/vizro-ai/docs/pages/user-guides/create-advanced-charts.md b/vizro-ai/docs/pages/user-guides/create-advanced-charts.md index c616f88bd..494aa08aa 100644 --- a/vizro-ai/docs/pages/user-guides/create-advanced-charts.md +++ b/vizro-ai/docs/pages/user-guides/create-advanced-charts.md @@ -1,4 +1,5 @@ # Advanced charts + This page explains how to use Vizro-AI to create charts with advanced visualizations and enhanced formatting. ## Animated bar chart @@ -6,7 +7,6 @@ This page explains how to use Vizro-AI to create charts with advanced visualizat We'll create an animated bar chart illustrating the GDP per capita of each continent over time. Run the code below and look at the result. !!! example "Vizro-AI animated chart" - === "Code" ```py from vizro_ai import VizroAI @@ -18,16 +18,13 @@ We'll create an animated bar chart illustrating the GDP per capita of each conti fig = vizro_ai.plot(df, "Visualize GDP per capita over the years for each country using map chart.") fig.show() ``` - === "Result" - [![AnimatedChart1]][AnimatedChart1] - [AnimatedChart1]: ../../assets/tutorials/chart/advanced_chart_1.png + === "Result" + [![AnimatedChart1]][animatedchart1] -Having unveiled our animated map chart showcasing GDP per capita development per country, it's clear that the map area is small, and it is difficult to differentiate countries. -Next, we will try to tweak our prompt to improve the overall layout. +Having unveiled our animated map chart showcasing GDP per capita development per country, it's clear that the map area is small, and it is difficult to differentiate countries. Next, we will try to tweak our prompt to improve the overall layout. !!! example "Vizro-AI animated chart" - === "Code" ```py from vizro_ai import VizroAI @@ -41,18 +38,15 @@ Next, we will try to tweak our prompt to improve the overall layout. Show countries on the map. Increase the width and height of the figure.""") fig.show() ``` - === "Result" - [![AnimatedChart2]][AnimatedChart2] - - [AnimatedChart2]: ../../assets/tutorials/chart/advanced_chart_2.png + === "Result" + [![AnimatedChart2]][animatedchart2] By incorporating the directive `Increase the width and height of the figure.` and `Show countries on the map.` we've successfully refined our animation. Upon closer inspection, the title is too long and the color palette used does not match our needs. We can fix those issues with better and more specific prompting. Let's run the code below to visually improve the chart. !!! example "Vizro-AI animated chart" - === "Code" ```py from vizro_ai import VizroAI @@ -67,12 +61,14 @@ Upon closer inspection, the title is too long and the color palette used does no Set title to be: `GDP per Capita over the years`. Use `Blues` as color sequence. """) fig.show() ``` - === "Result" - [![AnimatedChart3]][AnimatedChart3] - [AnimatedChart3]: ../../assets/tutorials/chart/animated_advanced_chart.gif + === "Result" + [![AnimatedChart3]][animatedchart3] Congratulations! You've now gained insights into harnessing the power of a LLM and Vizro-AI for crafting advanced charts and improving formatting. Don't forget, enabling `return_elements=True` in `.plot()` and check `chart_insights` and `code_explanation` is a good way of learning more about how a chart can be further improved and formatted. - Advanced charts are well-suited for [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard applications. You can create a chart using `vizro-ai` to plug into your `vizro` dashboard in seconds! + +[animatedchart1]: ../../assets/tutorials/chart/advanced_chart_1.png +[animatedchart2]: ../../assets/tutorials/chart/advanced_chart_2.png +[animatedchart3]: ../../assets/tutorials/chart/animated_advanced_chart.gif diff --git a/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md b/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md index 5ea3721ca..52d13e89e 100644 --- a/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md +++ b/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md @@ -9,6 +9,7 @@ The following example shows how to use Vizro-AI to generate a complex Vizro dash If you haven't already installed Vizro-AI and set up the API key for OpenAI, follow the [installation guide](../user-guides/install.md). ## 1. Prepare the data + Next, prepare the data to pass to Vizro-AI. In this example, we use the [election data](https://plotly.com/python-api-reference/generated/plotly.express.data.html#plotly.express.data.election) and the [stocks data](https://plotly.com/python-api-reference/generated/plotly.express.data.html#plotly.express.data.stocks). ```py @@ -18,7 +19,6 @@ df1 = px.data.election() df2 = px.data.stocks(datetimes=True) ``` - ## 2. Prepare the user prompt Devise a string of text to form the prompt that requests Vizro-AI to generate the Vizro dashboard. @@ -104,17 +104,16 @@ dashboard = vizro_ai.dashboard([df1, df2], user_question) The call to `dashboard()` triggers the dashboard building process. Once Vizro-AI finishes this process, you can launch the dashboard with `build()`. !!! example "Generated dashboard" - === "Code" ```py Vizro().build(dashboard).run() ``` === "Page1" - [![VizroAIDashboardPage1]][VizroAIDashboardPage1] + [![VizroAIDashboardPage1]][vizroaidashboardpage1] === "Page2" - [![VizroAIDashboardPage2]][VizroAIDashboardPage2] + [![VizroAIDashboardPage2]][vizroaidashboardpage2] - [VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard1_page1.png - [VizroAIDashboardPage2]: ../../assets/user_guides/dashboard/dashboard1_page2.png +[vizroaidashboardpage1]: ../../assets/user_guides/dashboard/dashboard1_page1.png +[vizroaidashboardpage2]: ../../assets/user_guides/dashboard/dashboard1_page2.png diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index 3087d7f1a..e20a3e56f 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -3,8 +3,8 @@ This guide shows how to set up a large language model (LLM) for use with Vizro-AI. Setting up a LLM is required for the package to generate charts and dashboards based on natural language queries. To ensure responsible use, review the vendor’s guidelines on risk mitigation before using the model to understand potential model limitations and best practices. ## Supported models -Vizro-AI supports **any** model that is available via [Langchain's `BaseChatModel` class](https://api.python.langchain.com/en/latest/language_models/langchain_core.language_models.chat_models.BaseChatModel.html#langchain_core.language_models.chat_models.BaseChatModel), and that has the [`with_structured_output` method](https://python.langchain.com/v0.2/docs/how_to/structured_output/#the-with_structured_output-method) implemented. An overview of the [most common vendor models supporting this functionality](https://python.langchain.com/v0.2/docs/integrations/chat/) can be found in Langchain's documentation. For ease of use one can also choose some models via a string parameter. +Vizro-AI supports **any** model that is available via [Langchain's `BaseChatModel` class](https://api.python.langchain.com/en/latest/language_models/langchain_core.language_models.chat_models.BaseChatModel.html#langchain_core.language_models.chat_models.BaseChatModel), and that has the [`with_structured_output` method](https://python.langchain.com/v0.2/docs/how_to/structured_output/#the-with_structured_output-method) implemented. An overview of the [most common vendor models supporting this functionality](https://python.langchain.com/v0.2/docs/integrations/chat/) can be found in Langchain's documentation. For ease of use one can also choose some models via a string parameter. ### Setting model via string for ease of use @@ -14,34 +14,30 @@ We have created shortcuts with sensible defaults (mainly setting `temperature=0` vizro_ai = VizroAI(model="") ``` -!!!note +!!! note For the string settings to work, you must supply your API key via environment variables. The relevant variable names to be set are noted in each vendor tab. === "OpenAI" + | Env variable | Name(s) | + | ------------ | ----------------- | + | API key | `OPENAI_API_KEY` | + | Base API URL | `OPENAI_API_BASE` | - | Env variable | Name(s) | - | ----------- | ------------------------------------ | - | API key | `OPENAI_API_KEY` | - | Base API URL | `OPENAI_API_BASE` | - - To use OpenAI with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the OpenAI models and pricing on their website](https://platform.openai.com/docs/models). Before using a model, please review OpenAI's guidelines on risk mitigation to understand potential model limitations and best practices. - [See the OpenAI site for more details on responsible usage](https://platform.openai.com/docs/guides/safety-best-practices). + To use OpenAI with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the OpenAI models and pricing on their website](https://platform.openai.com/docs/models). Before using a model, please review OpenAI's guidelines on risk mitigation to understand potential model limitations and best practices. [See the OpenAI site for more details on responsible usage](https://platform.openai.com/docs/guides/safety-best-practices). - `gpt-4o-mini` **default** - `gpt-4-turbo` - `gpt-4o` === "Anthropic" - _Currently works only for `VizroAI.plot` - we are working on making it available for `VizroAI.dashboard`_ - | Env variable | Name(s) | - | ----------- | ------------------------------------ | - | API key | `ANTHROPIC_API_KEY` | - | Base API URL | `ANTHROPIC_API_URL`,`ANTHROPIC_BASE_URL` | + | Env variable | Name(s) | + | ------------ | ---------------------------------------- | + | API key | `ANTHROPIC_API_KEY` | + | Base API URL | `ANTHROPIC_API_URL`,`ANTHROPIC_BASE_URL` | - To use Anthropic with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the Anthropic models and pricing on their website](https://docs.anthropic.com/en/docs/about-claude/models). Before using a model, please review Anthropic guidelines on risk mitigation to understand potential model limitations and best practices. - [See the Anthropic site for more details on responsible usage](https://support.anthropic.com/en/collections/4078535-trust-safety/). + To use Anthropic with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the Anthropic models and pricing on their website](https://docs.anthropic.com/en/docs/about-claude/models). Before using a model, please review Anthropic guidelines on risk mitigation to understand potential model limitations and best practices. [See the Anthropic site for more details on responsible usage](https://support.anthropic.com/en/collections/4078535-trust-safety/). - `claude-3-5-sonnet-latest` - `claude-3-opus-latest` @@ -55,17 +51,14 @@ vizro_ai = VizroAI(model="") ``` === "MistralAI" + _Currently works only for `VizroAI.plot` - we are working on making it available for `VizroAI.dashboard`_ - _Currently works only for `VizroAI.plot` - we are working on making it available for `VizroAI.dashboard`_ - - | Env variable | Name(s) | - | ----------- | ------------------------------------ | - | API key | `MISTRAL_API_KEY` | - | Base API URL | `MISTRAL_BASE_URL` | + | Env variable | Name(s) | + | ------------ | ------------------ | + | API key | `MISTRAL_API_KEY` | + | Base API URL | `MISTRAL_BASE_URL` | - To use Mistral with Vizro-AI, you can either use their API, which comes with [an associated cost](https://mistral.ai/technology/#pricing), or you could use their models for free under the Apache 2.0 license. In that case you need to setup the model API yourself. You can check [all available Mistral models including pricing on their website](https://docs.mistral.ai/getting-started/models/models_overview). This will also explain which version the below string acronyms currently point to. - Before usage, please review Mistral guidelines on risk mitigation to understand potential model limitations and best practices. - [See the Mistral site for more details on responsible usage](https://help.mistral.ai/en/collections/272960-le-chat/). + To use Mistral with Vizro-AI, you can either use their API, which comes with [an associated cost](https://mistral.ai/technology/#pricing), or you could use their models for free under the Apache 2.0 license. In that case you need to setup the model API yourself. You can check [all available Mistral models including pricing on their website](https://docs.mistral.ai/getting-started/models/models_overview). This will also explain which version the below string acronyms currently point to. Before usage, please review Mistral guidelines on risk mitigation to understand potential model limitations and best practices. [See the Mistral site for more details on responsible usage](https://help.mistral.ai/en/collections/272960-le-chat/). - `mistral-large-latest` - `open-mistral-nemo` @@ -79,18 +72,23 @@ vizro_ai = VizroAI(model="") At the time of writing, we found that even the best Mistral models struggled to produce more than the simplest charts, but these outcomes can change drastically overtime. -!!!note +!!! note When choosing the string representation, it sometimes can be tricky to have the correct environment variable set for the API key (and potential base URL). In case you cannot get this to work, we recommend instantiating the model directly (see below) and providing the API key via the models parameters. + ### Setting model via class for additional configuration + + Beyond passing a string, you can pass **any** model derived from [Langchain's `BaseChatModel` class](https://api.python.langchain.com/en/latest/language_models/langchain_core.language_models.chat_models.BaseChatModel.html#langchain_core.language_models.chat_models.BaseChatModel) that has the [`with_structured_output` method](https://python.langchain.com/v0.2/docs/how_to/structured_output/#the-with_structured_output-method) implemented. An overview of the [most common vendor models supporting this functionality](https://python.langchain.com/v0.2/docs/integrations/chat/) can be found in Langchain's documentation. When choosing this approach, you can customize your model beyond the chosen default from the string instantiation. The choice of available arguments depends on the specific vendor implementation, but usually the main parameter to tweak is the temperature. + To ensure a deterministic answer to our queries, we've set the temperature to 0 in the string instantiation. If you prefer more creative (but potentially more unstable) responses, you can raise the temperature to a maximum of 1. + Below you can find an example where a custom model is instantiated with various custom parameters. Note that we manually set the API key and base URL, which is the easiest way to get it set up. diff --git a/vizro-ai/docs/pages/user-guides/retrieve-dashboard-code.md b/vizro-ai/docs/pages/user-guides/retrieve-dashboard-code.md index a95d1159a..0fa10cf03 100644 --- a/vizro-ai/docs/pages/user-guides/retrieve-dashboard-code.md +++ b/vizro-ai/docs/pages/user-guides/retrieve-dashboard-code.md @@ -4,8 +4,8 @@ This guide shows how to retrieve the code of a Vizro-AI generated dashboard. The While Vizro-AI can follow complex user requirements well and generate high-quality dashboards, due to the nature of LLMs, the generated dashboards often only partly match user expectations. Besides refining the user prompt and re-running Vizro-AI, you can also extract the code and iterate manually to achieve the desired result. - ## 1. Prepare the data and user prompt + ```py import vizro.plotly.express as px @@ -27,16 +27,17 @@ Create a one-page dashboard layout with the following components: ``` ## 2. Generate and launch the dashboard + ```py from vizro_ai import VizroAI vizro_ai = VizroAI(model="gpt-4o-mini") result = vizro_ai.dashboard([df], user_question, return_elements=True) ``` + This triggers the dashboard building process. Once Vizro-AI finishes the dashboard generation process, you can now launch the dashboard. !!! example "Generated dashboard" - === "Code" ```py import vizro.plotly.express as px @@ -63,14 +64,17 @@ This triggers the dashboard building process. Once Vizro-AI finishes the dashboa ``` === "Result" - [![VizroAIDashboardPage1]][VizroAIDashboardPage1] + \[!\[VizroAIDashboardPage1\]\]\[VizroAIDashboardPage1\] +``` +[VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard2_page1.png +``` - [VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard2_page1.png +FIXME ## 3. Retrieve the Python code of the dashboard -!!! example "View dashboard code" +!!! example "View dashboard code" === "Code" ```py import vizro.plotly.express as px @@ -96,6 +100,7 @@ This triggers the dashboard building process. Once Vizro-AI finishes the dashboa print(result.code) ``` + === "Result" ```py ######## Module Imports ########## diff --git a/vizro-ai/docs/pages/user-guides/run-vizro-ai.md b/vizro-ai/docs/pages/user-guides/run-vizro-ai.md index 192df9ea5..9d375a504 100644 --- a/vizro-ai/docs/pages/user-guides/run-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/run-vizro-ai.md @@ -2,19 +2,18 @@ This guide offers insights into different ways of running `VizroAI.plot` to generate Plotly charts. We cover how to use: -* [a Jupyter Notebook](#jupyter-notebook) -* [a Python script](#python-script) -* [integration into an application](#application-integration) +- [a Jupyter Notebook](#jupyter-notebook) +- [a Python script](#python-script) +- [integration into an application](#application-integration) ## Jupyter Notebook + To run Vizro-AI code in a Jupyter Notebook, create a new cell and execute the code below to render the described visualization as output. ??? note "Note: API key" - Make sure you have followed the [LLM setup guide](../user-guides/install.md#set-up-access-to-a-large-language-model) and thatyour api key is set up in a `.env` file in the same folder as your Notebook file (`.ipynb`). !!! example "Ask Vizro-AI to generate a bar chart" - === "Code for the cell" ```py import vizro.plotly.express as px @@ -25,18 +24,17 @@ To run Vizro-AI code in a Jupyter Notebook, create a new cell and execute the co df = px.data.gapminder() vizro_ai.plot(df, "visualize the life expectancy per continent and color each continent") ``` - === "Result" - [![BarChart]][BarChart] - [BarChart]: ../../assets/user_guides/bar_chart_gdp_per_continent.png + === "Result" + [![BarChart]][barchart] Note that if you run this code, its appearance may not precisely resemble the one displayed, as it is generated by a generative AI and can vary. ## Python script + You can use Vizro-AI in any standard development environment by creating a `.py` file and executing the code, which displays the output in a browser window. As Vizro-AI returns the `fig` object, you need to append `fig.show()` to the response object. ??? note "Note: API key" - Make sure you have followed [LLM setup guide](../user-guides/install.md#set-up-access-to-a-large-language-model) and that your API key is set up in the environment where your `.py` script is running with command as below: ```bash @@ -44,7 +42,6 @@ You can use Vizro-AI in any standard development environment by creating a `.py` ``` !!! example "Ask Vizro-AI to generate a line chart" - === "example.py" ```py import vizro.plotly.express as px @@ -56,13 +53,13 @@ You can use Vizro-AI in any standard development environment by creating a `.py` fig = vizro_ai.plot(df, "describe life expectancy per continent over time") fig.show() ``` - === "Result" - [![LineChart]][LineChart] - [LineChart]: ../../assets/user_guides/line_chart_life_expect.png + === "Result" + [![LineChart]][linechart] ## Application integration -You may prefer to integrate Vizro-AI into an application that offers a UI for users to input prompts. For that you can take the `fig` object from the `.plot` call, and use it elsewhere -in any application (you might also want to process it further, for example, by serializing it or similar). It is also possible to obtain the code that would produce the object. For any advanced usage options, refer to -[our advanced options guide](advanced-options.md). +You may prefer to integrate Vizro-AI into an application that offers a UI for users to input prompts. For that you can take the `fig` object from the `.plot` call, and use it elsewhere in any application (you might also want to process it further, for example, by serializing it or similar). It is also possible to obtain the code that would produce the object. For any advanced usage options, refer to [our advanced options guide](advanced-options.md). + +[barchart]: ../../assets/user_guides/bar_chart_gdp_per_continent.png +[linechart]: ../../assets/user_guides/line_chart_life_expect.png diff --git a/vizro-ai/docs/pages/user-guides/use-different-languages.md b/vizro-ai/docs/pages/user-guides/use-different-languages.md index ff797f1fc..7c222fa37 100644 --- a/vizro-ai/docs/pages/user-guides/use-different-languages.md +++ b/vizro-ai/docs/pages/user-guides/use-different-languages.md @@ -1,8 +1,8 @@ # Generate visualizations using different languages + Vizro-AI is versatile, supporting prompts and chart visualizations in languages other than English. In this guide you will explore this capability with two examples, starting with Chinese where we inquire about visualizing the GDP per capita over time. !!! example "Vizro-AI Chinese" - === "Code for the cell" ```py from vizro_ai import VizroAI @@ -14,15 +14,13 @@ Vizro-AI is versatile, supporting prompts and chart visualizations in languages fig = vizro_ai.plot(df, "请画一个世界年均GDP的趋势图") fig.show() ``` - === "Result" - [![ChineseChart]][ChineseChart] - [ChineseChart]: ../../assets/tutorials/chart/ChineseExample.png + === "Result" + [![ChineseChart]][chinesechart] Subsequently, we'll switch to German and prompt the visualization of life expectancy in the United States over time, comparing it to the global life expectancy trend. For this example, we'll include `return_elements=True` to obtain comprehensive insights into both the data and the generated code. !!! example "Vizro-AI German" - === "Code for the cell" ```py from vizro_ai import VizroAI @@ -36,7 +34,9 @@ Subsequently, we'll switch to German and prompt the visualization of life expect print(f"Code:\n{result.code_explanation}\n{result.code_vizro}\n" ) result.get_fig_object(df).show() ``` + === "Result" - [![GermanChart]][GermanChart] + [![GermanChart]][germanchart] - [GermanChart]: ../../assets/tutorials/chart/GermanExample.png +[chinesechart]: ../../assets/tutorials/chart/ChineseExample.png +[germanchart]: ../../assets/tutorials/chart/GermanExample.png diff --git a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md index 210f36410..97aecc97a 100644 --- a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md +++ b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md @@ -3,9 +3,9 @@ You can use Vizro-AI's functionality within a larger LangChain application. This guide shows how to integrate Vizro-AI's chart and dashboard generation capabilities as LangChain tools. Here are the steps you need to take: 1. [Set up the environment](#1-set-up-the-environment) -2. [Define LangChain tools](#2-define-langchain-tools) -3. [Set up the tool chain](#3-set-up-the-tool-chain) -4. [Use the chain](#4-use-the-chain) +1. [Define LangChain tools](#2-define-langchain-tools) +1. [Set up the tool chain](#3-set-up-the-tool-chain) +1. [Use the chain](#4-use-the-chain) ## 1. Set up the environment @@ -51,6 +51,7 @@ def get_plot_code(df: Annotated[Any, InjectedToolArg], question: str) -> str: ) return plot_elements.code_vizro + @tool(parse_docstring=True) def get_dashboard_code(dfs: Annotated[Any, InjectedToolArg], question: str) -> str: """Generate the dashboard code. @@ -80,6 +81,7 @@ Create a chain that handles tool execution and data injection: tools = [get_plot_code, get_dashboard_code] llm_with_tools = llm.bind_tools(tools) + # Create data injection chain @chain def inject_df(ai_msg): @@ -95,13 +97,16 @@ def inject_df(ai_msg): tool_calls.append(tool_call_copy) return tool_calls + # Create tool router tool_map = {tool.name: tool for tool in tools} + @chain def tool_router(tool_call): return tool_map[tool_call["name"]] + # Combine chains chain = llm_with_tools | inject_df | tool_router.map() ``` @@ -111,7 +116,6 @@ chain = llm_with_tools | inject_df | tool_router.map() Now you can use the chain to generate charts or dashboards based on natural language queries. The chain will generate code that you can use to create visualizations. !!! example "Generate chart code" - === "Code" ```py # Load sample data @@ -120,6 +124,7 @@ Now you can use the chain to generate charts or dashboards based on natural lang plot_response = chain.invoke("Plot GDP per capita for each continent") print(plot_response[0].content) ``` + === "Vizro-AI Generated Code" ```py import plotly.graph_objects as go @@ -140,7 +145,6 @@ Now you can use the chain to generate charts or dashboards based on natural lang ``` !!! example "Generate dashboard code" - === "Code" ```py dfs = [px.data.gapminder()] @@ -148,6 +152,7 @@ Now you can use the chain to generate charts or dashboards based on natural lang dashboard_response = chain.invoke("Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp.") print(dashboard_response[0].content) ``` + === "Vizro-AI Generated Code" ```py ############ Imports ############## diff --git a/vizro-core/CHANGELOG.md b/vizro-core/CHANGELOG.md index d001e8da5..47e0c2659 100644 --- a/vizro-core/CHANGELOG.md +++ b/vizro-core/CHANGELOG.md @@ -273,10 +273,7 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse ### Highlights ✨ -- Introduce `AgGrid` as a new `Page` component, allowing the usage of - [AG Grid](https://www.ag-grid.com/) in - `Vizro`. See the [user guide on tables](https://vizro.readthedocs.io/en/stable/pages/user_guides/table/) - for more information. ([#289](https://github.com/mckinsey/vizro/pull/289),[#268](https://github.com/mckinsey/vizro/pull/268),[#324](https://github.com/mckinsey/vizro/pull/324)) +- Introduce `AgGrid` as a new `Page` component, allowing the usage of [AG Grid](https://www.ag-grid.com/) in `Vizro`. See the [user guide on tables](https://vizro.readthedocs.io/en/stable/pages/user_guides/table/) for more information. ([#289](https://github.com/mckinsey/vizro/pull/289),[#268](https://github.com/mckinsey/vizro/pull/268),[#324](https://github.com/mckinsey/vizro/pull/324)) ## Changed @@ -521,10 +518,10 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse - Optimize the client-server communication ([#34](https://github.com/mckinsey/vizro/pull/34)) - - Eliminate most server side callbacks in favor of client-side callbacks - - Add tests for client-side callbacks written in Node.js framework called `jest`. - - Add hatch command `hatch run test-js` that runs unit tests written in `jest`. - - Logging information now only displayed for action function carried out (no trigger or finished information) + - Eliminate most server side callbacks in favor of client-side callbacks + - Add tests for client-side callbacks written in Node.js framework called `jest`. + - Add hatch command `hatch run test-js` that runs unit tests written in `jest`. + - Logging information now only displayed for action function carried out (no trigger or finished information) - Replaced all screenshots in the docs to reflect new navigation designs ([#48](https://github.com/mckinsey/vizro/pull/48)) @@ -568,21 +565,21 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse - Add the following pydantic models: - - Action - - Button - - Card - - Checklist - - Dashboard - - Dropdown - - Filter - - Graph - - Layout - - Navigation - - Page - - Parameter - - RadioItems - - RangeSlider - - Slider - - VizroBaseModel + - Action + - Button + - Card + - Checklist + - Dashboard + - Dropdown + - Filter + - Graph + - Layout + - Navigation + - Page + - Parameter + - RadioItems + - RangeSlider + - Slider + - VizroBaseModel - Enable the addition and usage of custom components and custom charts diff --git a/vizro-core/README.md b/vizro-core/README.md index 3a0cb5bc6..729f13298 100644 --- a/vizro-core/README.md +++ b/vizro-core/README.md @@ -11,19 +11,14 @@
-[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) -[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) -[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +FIXME: maybe use two new lines between each +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
-Documentation | -Get Started | -Vizro examples gallery +Documentation | Get Started | Vizro examples gallery
@@ -100,9 +95,7 @@ You can see Vizro in action by clicking on the following image or by visiting [t ## Visual vocabulary -Our visual vocabulary dashboard helps you to select and create various types of charts. It helps you decide when to use -each chart type, and offers sample Python code to create these charts with [Plotly](https://plotly.com/python/) and -embed them into a Vizro dashboard. +Our visual vocabulary dashboard helps you to select and create various types of charts. It helps you decide when to use each chart type, and offers sample Python code to create these charts with [Plotly](https://plotly.com/python/) and embed them into a Vizro dashboard. @@ -138,8 +131,7 @@ We encourage you to ask and answer technical questions via the [GitHub Issues](h ## Contributing -To learn more about making a contribution, -please see the [contributing guide](https://vizro.readthedocs.io/en/stable/pages/development/contributing/) for more information +To learn more about making a contribution, please see the [contributing guide](https://vizro.readthedocs.io/en/stable/pages/development/contributing/) for more information You can also view current and former [contributors](https://vizro.readthedocs.io/en/stable/pages/development/authors/) diff --git a/vizro-core/changelog.d/20241030_104644_antony.milne_0_1_26.md b/vizro-core/changelog.d/20241030_104644_antony.milne_0_1_26.md index 7c0d58d4f..4abc0f11e 100644 --- a/vizro-core/changelog.d/20241030_104644_antony.milne_0_1_26.md +++ b/vizro-core/changelog.d/20241030_104644_antony.milne_0_1_26.md @@ -10,36 +10,42 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -[Alexey Snigir](https://github.com/l0uden), -[Antony Milne](https://github.com/antonymilne), -[Dan Dumitriu](https://github.com/dandumitriu1), -[Huong Li Nguyen](https://github.com/huong-li-nguyen), -[Jo Stichbury](https://github.com/stichbury), -[Joseph Perkins](https://github.com/Joseph-Perkins), -[Lingyi Zhang](https://github.com/lingyielia), -[Maximilian Schulz](https://github.com/maxschulz-COL), -[Nadija Graca](https://github.com/nadijagraca), -[Petar Pejovic](https://github.com/petar-qb) - +[Alexey Snigir](https://github.com/l0uden), [Antony Milne](https://github.com/antonymilne), [Dan Dumitriu](https://github.com/dandumitriu1), [Huong Li Nguyen](https://github.com/huong-li-nguyen), [Jo Stichbury](https://github.com/stichbury), [Joseph Perkins](https://github.com/Joseph-Perkins), [Lingyi Zhang](https://github.com/lingyielia), [Maximilian Schulz](https://github.com/maxschulz-COL), [Nadija Graca](https://github.com/nadijagraca), [Petar Pejovic](https://github.com/petar-qb) + + ## Previous team members and code contributors + -[Ann Marie Ward](https://github.com/AnnMarieW), -[Ned Letcher](https://github.com/ned2), -Natalia Kurakina, -[Leon Nallamuthu](https://github.com/leonnallamuthu), -[axa99](https://github.com/axa99), -[Juan Luis Cano Rodríguez](https://github.com/astrojuanlu), -[Denis Lebedev](https://github.com/DenisLebedevMcK), -[Qiuyi Chen](https://github.com/Qiuyi-Chen), -[Elena Fridman](https://github.com/EllenWie), -[Bo Xu](https://github.com/boxuboxu), -[Jingjing Guo](https://github.com/jjguo-mck), -[Oleksandr Serdiuk](https://github.com/oserdiuk-lohika), -[Prateek Bajaj](https://github.com/prateekdev552), -[Nikolaos Tsaousis](https://github.com/tsanikgr), -[Annie Wachsmuth](https://github.com/anniecwa), -[Hamza Oza](https://github.com/hamzaoza), -[Kee Wen Ng](https://github.com/KeeWenNgQB), -[Rashida Kanchwala](https://github.com/rashidakanchwala), -[Juan Luis Cano Rodríguez](https://github.com/astrojuanlu), -[Anna Xiong](https://github.com/Anna-Xiong), -[Chiara Pullem](https://github.com/chiara-sophie), -[Sylvie Zhang](https://github.com/sylviezhang37), -[Bhavana Sundar](https://github.com/bhavanaeh), -[Ferida Mohammed](https://github.com/feridaaa), -[Lydia Pitts](https://github.com/LydiaPitts), -[Riley Dou](https://github.com/rilieo), -[Upekesha Ngugi](https://github.com/upekesha), -[Hansaem Park](https://github.com/sammitako), -[Rosheen C.](https://github.com/rc678), -[Hilary Ivy](https://github.com/hxe00570), -[Jasmine Wu](https://github.com/jazwu), -[njmcgrat](https://github.com/njmcgrat) + +[Ann Marie Ward](https://github.com/AnnMarieW), [Ned Letcher](https://github.com/ned2), Natalia Kurakina, [Leon Nallamuthu](https://github.com/leonnallamuthu), [axa99](https://github.com/axa99), [Juan Luis Cano Rodríguez](https://github.com/astrojuanlu), [Denis Lebedev](https://github.com/DenisLebedevMcK), [Qiuyi Chen](https://github.com/Qiuyi-Chen), [Elena Fridman](https://github.com/EllenWie), [Bo Xu](https://github.com/boxuboxu), [Jingjing Guo](https://github.com/jjguo-mck), [Oleksandr Serdiuk](https://github.com/oserdiuk-lohika), [Prateek Bajaj](https://github.com/prateekdev552), [Nikolaos Tsaousis](https://github.com/tsanikgr), [Annie Wachsmuth](https://github.com/anniecwa), [Hamza Oza](https://github.com/hamzaoza), [Kee Wen Ng](https://github.com/KeeWenNgQB), [Rashida Kanchwala](https://github.com/rashidakanchwala), [Juan Luis Cano Rodríguez](https://github.com/astrojuanlu), [Anna Xiong](https://github.com/Anna-Xiong), [Chiara Pullem](https://github.com/chiara-sophie), [Sylvie Zhang](https://github.com/sylviezhang37), [Bhavana Sundar](https://github.com/bhavanaeh), [Ferida Mohammed](https://github.com/feridaaa), [Lydia Pitts](https://github.com/LydiaPitts), [Riley Dou](https://github.com/rilieo), [Upekesha Ngugi](https://github.com/upekesha), [Hansaem Park](https://github.com/sammitako), [Rosheen C.](https://github.com/rc678), [Hilary Ivy](https://github.com/hxe00570), [Jasmine Wu](https://github.com/jazwu), [njmcgrat](https://github.com/njmcgrat) with thanks to Sam Bourton and Kevin Staight for sponsorship, inspiration and guidance, -and special thanks to -[Wesley Leong](https://github.com/wesleyleong), [Jonas Kemper](https://github.com/jonasrk) and team for origination and support +and special thanks to [Wesley Leong](https://github.com/wesleyleong), [Jonas Kemper](https://github.com/jonasrk) and team for origination and support (plus everyone else who helped to test, guide, support and encourage development) + diff --git a/vizro-core/docs/pages/explanation/contributing.md b/vizro-core/docs/pages/explanation/contributing.md index 7e532ae3b..44e39ecf0 100644 --- a/vizro-core/docs/pages/explanation/contributing.md +++ b/vizro-core/docs/pages/explanation/contributing.md @@ -4,22 +4,20 @@ Contributions of all experience levels are welcome! There are many ways to contr Our development follows a standard [GitHub flow](https://docs.github.com/en/get-started/using-github/github-flow). To be merged, your PR must meet all the following requirements: -* two approving reviews (including a code owner) -* Continuous Integration (CI) checks pass -* code is up-to-date with `main` +- two approving reviews (including a code owner) +- Continuous Integration (CI) checks pass +- code is up-to-date with `main` If you are a first-time contributor with a new GitHub account then you may also need to [wait for CI workflows to be approved](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/approving-workflow-runs-from-public-forks). We aim to make the contribution process as easy as possible by having only one direct development dependency: [Hatch](https://hatch.pypa.io/). There are two ways to develop on Vizro: -* [GitHub Codespaces](https://docs.github.com/en/codespaces). This is the recommended method if you are a new contributor. It is the quickest and easiest way to get started. All development can be done in your browser in a temporary environment; you do not need to set up anything on your computer. The [Develop on GitHub Codespaces](#develop-on-github-codespaces) section has full instructions on how to do this. -* Local machine. If you are more experienced then you might prefer to develop on your own computer. The [Develop locally](#develop-locally) section has full instructions on how to do this. +- [GitHub Codespaces](https://docs.github.com/en/codespaces). This is the recommended method if you are a new contributor. It is the quickest and easiest way to get started. All development can be done in your browser in a temporary environment; you do not need to set up anything on your computer. The [Develop on GitHub Codespaces](#develop-on-github-codespaces) section has full instructions on how to do this. +- Local machine. If you are more experienced then you might prefer to develop on your own computer. The [Develop locally](#develop-locally) section has full instructions on how to do this. !!! note - For either method, Hatch is the _only development dependency_. You do not need to manually install Python or create any virtual environments to develop Vizro; all this will be handled for you behind the scenes by Hatch. We have also configured our codespace to pre-install Hatch. If you develop on GitHub Codespaces you don't need to install anything at all! - ## Develop on GitHub Codespaces There is no need to manually create a fork of the Vizro code if you use GitHub Codespaces. A fork is [automatically created for you](https://docs.github.com/en/codespaces/developing-in-a-codespace/using-source-control-in-your-codespace#about-automatic-forking). @@ -27,17 +25,17 @@ There is no need to manually create a fork of the Vizro code if you use GitHub C To develop on [GitHub Codespaces](https://docs.github.com/en/codespaces), follow the below steps: 1. [Create a codespace for our repository](https://codespaces.new/mckinsey/vizro). Leave the settings on their defaults and click "Create codespace" to start your codespace. It should take 1-2 minutes to fully launch and automatically start an example dashboard on port 8050. In the rare event that the codespace fails to start correctly and enters recovery mode, you should [rebuild the container](https://docs.github.com/en/codespaces/developing-in-a-codespace/rebuilding-the-container-in-a-codespace#rebuilding-a-container) or start a whole new codespace. -2. Make changes to Vizro code in your codespace. See the [GitHub Codespaces documentation on developing in a codespace](https://docs.github.com/en/codespaces/developing-in-a-codespace/developing-in-a-codespace) for more information. -3. Add your name to the [list of contributors](authors.md) (source file `vizro-core/docs/pages/explanation/authors.md`). -4. [Create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). +1. Make changes to Vizro code in your codespace. See the [GitHub Codespaces documentation on developing in a codespace](https://docs.github.com/en/codespaces/developing-in-a-codespace/developing-in-a-codespace) for more information. +1. Add your name to the [list of contributors](authors.md) (source file `vizro-core/docs/pages/explanation/authors.md`). +1. [Create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). ## Develop locally 1. Install Hatch. There are [several ways to do this](https://hatch.pypa.io/latest/install/). -2. [Fork the Vizro repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) and clone it to your local machine. -3. Make changes to Vizro code in your fork. -4. Add your name to the [list of contributors](authors.md) (source file `vizro-core/docs/pages/explanation/authors.md`). -5. [Create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). +1. [Fork the Vizro repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) and clone it to your local machine. +1. Make changes to Vizro code in your fork. +1. Add your name to the [list of contributors](authors.md) (source file `vizro-core/docs/pages/explanation/authors.md`). +1. [Create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). ## How to use Hatch @@ -45,16 +43,18 @@ Regardless of whether you are developing locally or in a codespace, everything y The Hatch commands you need most commonly are as follows. These must be executed with `vizro-core` as your current working directory: -* [`hatch run pypath`](#hatch-run-pypath) shows the path to the Python interpreter. -* [`hatch run example`](#hatch-run-example) runs an example dashboard on port 8050 that hot-reloads while you edit it. On GitHub Codespaces, this runs automatically on startup. -* [`hatch run lint`](#hatch-run-lint) checks and fixes code quality and formatting. This is included in CI checks. -* [`hatch run changelog:add`](#hatch-run-changelogadd) generates a new changelog fragment. Changelog inclusion is checked by CI and required for all changes to source code. -* [`hatch run test-unit`](#hatch-run-test-unit) runs the test suite. This is included in CI checks. -* [`hatch run docs:serve`](#hatch-run-docsserve) builds and displays documentation that hot-reloads while you edit it. Documentation is also built automatically in your PR and can be previewed on Read The Docs. -* [`hatch run pip`](#hatch-run-pip) provides a [pip-compatible interface using uv](https://docs.astral.sh/uv/pip/). You should not need to use this much. +- [`hatch run pypath`](#hatch-run-pypath) shows the path to the Python interpreter. +- [`hatch run example`](#hatch-run-example) runs an example dashboard on port 8050 that hot-reloads while you edit it. On GitHub Codespaces, this runs automatically on startup. +- [`hatch run lint`](#hatch-run-lint) checks and fixes code quality and formatting. This is included in CI checks. +- [`hatch run changelog:add`](#hatch-run-changelogadd) generates a new changelog fragment. Changelog inclusion is checked by CI and required for all changes to source code. +- [`hatch run test-unit`](#hatch-run-test-unit) runs the test suite. This is included in CI checks. +- [`hatch run docs:serve`](#hatch-run-docsserve) builds and displays documentation that hot-reloads while you edit it. Documentation is also built automatically in your PR and can be previewed on Read The Docs. +- [`hatch run pip`](#hatch-run-pip) provides a [pip-compatible interface using uv](https://docs.astral.sh/uv/pip/). You should not need to use this much. + To save yourself from repeatedly typing `hatch run` you might like to [set up an alias](https://www.tecmint.com/create-alias-in-linux/): + ```console @@ -67,10 +67,10 @@ This enables you to run, for example, `hr lint` instead of `hatch run lint`. On `hatch run pypath` shows the path to the Python interpreter. This is useful for setting a Python interpreter in your IDE to navigate the codebase. For example, in GitHub Codespaces and VS Code: -* Run `hatch run pypath` and copy the output to your clipboard. -* Open the Command Palette (++ctrl+shift+p++). -* Run the "Python: Select Interpreter" command and select the "Enter interpreter path..." option. -* Paste the path. +- Run `hatch run pypath` and copy the output to your clipboard. +- Open the Command Palette (++ctrl+shift+p++). +- Run the "Python: Select Interpreter" command and select the "Enter interpreter path..." option. +- Paste the path. ### `hatch run example` @@ -82,15 +82,14 @@ You can run any example in `vizro-core/examples` or its subdirectories by runnin Examples are run with the following settings: -* [Dash dev tools](https://dash.plotly.com/devtools) enabled. This includes hot reloading, so that any changes to the example app or Vizro source code should automatically show in your dashboard without needing refresh or restart anything. -* The environment variable `VIZRO_LOG_LEVEL = "DEBUG"` to show log messages of level `DEBUG` and above. +- [Dash dev tools](https://dash.plotly.com/devtools) enabled. This includes hot reloading, so that any changes to the example app or Vizro source code should automatically show in your dashboard without needing refresh or restart anything. +- The environment variable `VIZRO_LOG_LEVEL = "DEBUG"` to show log messages of level `DEBUG` and above. ### `hatch run lint` `hatch run lint` checks and fixes code quality and formatting. This is included in CI checks. All linting and associated dependencies are controlled by [pre-commit](https://pre-commit.com/) hooks. We use the [pre-commit.ci](https://pre-commit.ci/) to automatically fix all the linting checks that we can when a PR is pushed. Other linting failures (such as `mypy`) need manual intervention from the developer. !!! note - The first time you run `hatch run lint` it may take a couple of minutes, since pre-commit needs to setup linting environments. Subsequent runs reuse these environments and are much faster. `hatch run lint` runs the pre-commit hooks on all (not only staged) files. You can run an individual hook, for example `mypy`, on all files by running `hatch run lint mypy`. @@ -106,7 +105,6 @@ The format of our changelog is based on [Keep a Changelog](https://keepachangelo Run `hatch run changelog:add` to create a changelog fragment and then uncomment the relevant section(s). If you are uncertain about what to add or whether to add anything at all, refer to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The rule of thumb is that if Vizro users would be affected in any way then the changes should be described in the changelog. !!! note - Changes that do not affect source code do not need a changelog fragment. This facilitates simple modifications to documentation [made directly on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files) or with the [github.dev](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor), where no terminal is available to run `hatch changelog:add`. Any changes to source code require a changelog fragment to be generated. If your changes do not require a changelog entry then you still need to generate the fragment but can leave it all commented out. ### `hatch run test-unit` @@ -127,9 +125,9 @@ hatch run all.py3.10:test-unit-coverage In addition to running unit tests with code coverage, CI also performs the following checks: -* `hatch run test-integration` runs integration tests that include checking that the example apps in `vizro-core/examples` run. -* `hatch run test-js` runs Javascript tests using [jest](https://jestjs.io/). Arguments are passed through to the underlying `npx jest` command, for example `hatch run test-js --help`. -* QA tests. These are run on a separate private `vizro-qa` repository and not triggered by PRs coming from forks. +- `hatch run test-integration` runs integration tests that include checking that the example apps in `vizro-core/examples` run. +- `hatch run test-js` runs Javascript tests using [jest](https://jestjs.io/). Arguments are passed through to the underlying `npx jest` command, for example `hatch run test-js --help`. +- QA tests. These are run on a separate private `vizro-qa` repository and not triggered by PRs coming from forks. ### `hatch run docs:serve` @@ -146,7 +144,6 @@ Vizro's dependencies are described by the `dependencies` section in `vizro-core/ We have [configured Hatch to use uv](https://hatch.pypa.io/1.12/how-to/environment/select-installer/) for rapid virtual environment creation, dependency resolution and installation. !!! note - If you have installed unwanted dependencies in your Hatch environment then the simplest solution is to delete the environment (`hatch env remove` to remove one environment or `hatch env prune` to remove all environments). Your next `hatch run` command will recreate the environment and install all the dependencies it needs. If for some reason you do need to use `pip` then the correct way to do so is through `hatch run pip`. For example, you could run `hatch run pip show plotly`. This will use the version of uv that Hatch itself uses under the hood. If you already have uv installed globally then `uv pip show plotly` would also work. diff --git a/vizro-core/docs/pages/explanation/documentation-style-guide.md b/vizro-core/docs/pages/explanation/documentation-style-guide.md index 9c397754e..40f989ac0 100644 --- a/vizro-core/docs/pages/explanation/documentation-style-guide.md +++ b/vizro-core/docs/pages/explanation/documentation-style-guide.md @@ -14,8 +14,8 @@ The names of our products are **Vizro** and **Vizro-AI**. We refer to other products using their preferred capitalization. For example: -* Dash and Pydantic are always capitalized, except where given as Python package names `dash` and `pydantic`. -* pandas DataFrame has a lowercase "p" and camelcase "DataFrame". +- Dash and Pydantic are always capitalized, except where given as Python package names `dash` and `pydantic`. +- pandas DataFrame has a lowercase "p" and camelcase "DataFrame". Vizro components are named using lower case: @@ -28,46 +28,42 @@ Use code font when referring to the component as a class or object: Avoid referring to data using terms like "dataset" or "connector". Prefer to use just "data" or, where that does not feel natural, "data source". ## Bullets -* Capitalize the first word, and end the bullet with a period. -* Don't use numbered bullets except for a sequence of instructions, or where you have to refer back to one of them in the text (or a diagram). + +- Capitalize the first word, and end the bullet with a period. +- Don't use numbered bullets except for a sequence of instructions, or where you have to refer back to one of them in the text (or a diagram). ## Call out boxes Keep the amount of text, and the number and variety of callouts used, to a minimum. There is a [broad set available](https://squidfunk.github.io/mkdocs-material/reference/admonitions/#supported-types) for use in the Vizro docs, but we limit usage to notes, warnings, details and examples: !!! note "note" - - For notable information. + For notable information. !!! warning "warning" - - To indicate a potential gotcha. + To indicate a potential gotcha. ??? details "See more details" - A side note (used sparingly) !!! example "example" - - For example code. - + For example code. Callout boxes can be made collapsible: if you use them, add them to the page so they are initially collapsed. ???+ note "Limit the use of collapsible callouts to secondary information only" - Don't use expanded-on-load collapsibles like this one. If the callout contains important information and needs to be shown as expanded on page load, it should simply be non-collapsible. ## Capitalization -* Only capitalize proper nouns such as the names of technology products, other tools and services. -* Don't capitalize cloud, internet, machine learning, or advanced analytics. Take a look at the [Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/accessibility-terms) if you're unsure. -* Follow sentence case, which capitalizes only the first word of a title/subtitle. We prefer "An introduction to data visualization" to "An Introduction to Data Visualization". +- Only capitalize proper nouns such as the names of technology products, other tools and services. +- Don't capitalize cloud, internet, machine learning, or advanced analytics. Take a look at the [Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/accessibility-terms) if you're unsure. +- Follow sentence case, which capitalizes only the first word of a title/subtitle. We prefer "An introduction to data visualization" to "An Introduction to Data Visualization". ## Code formatting -* Mark code blocks with the appropriate language to enable syntax highlighting. -* We use a `bash` lexer for all codeblocks that represent the terminal, and we don't include the prompt. -* Use the code format for Python package names such as `pandas` or `pydantic`. + +- Mark code blocks with the appropriate language to enable syntax highlighting. +- We use a `bash` lexer for all codeblocks that represent the terminal, and we don't include the prompt. +- Use the code format for Python package names such as `pandas` or `pydantic`. ## Headings and subheadings @@ -77,43 +73,45 @@ Aim to avoid use of gerunds (verb+ing) where you can. So your page should be "Ge In Vizro, when you are working on a how-to guide, there are a few additional guidelines to follow for consistency: -* Don't use "how to" in the file name: keep that as short as possible. -* The title (H1 header) should start with "How to". -* Don't use "how to" in the subsections that follow (H2 - H5) unless you consider the alternative to be confusing. -* Don't use gerund form in the subsections either. +- Don't use "how to" in the file name: keep that as short as possible. +- The title (H1 header) should start with "How to". +- Don't use "how to" in the subsections that follow (H2 - H5) unless you consider the alternative to be confusing. +- Don't use gerund form in the subsections either. Example: In a page called "Filters" you would have the following: -* H1: "How to use filters" -* H2 subsection: "Use a custom filter" and not "How to use a custom filter" nor "Using a custom filter". - +- H1: "How to use filters" +- H2 subsection: "Use a custom filter" and not "How to use a custom filter" nor "Using a custom filter". ## Instructions Prefer to use imperatives to make instructions. For example: + > Complete the configuration steps You don't need to use the word "please" -- readers want less to read and don't think it's rude if you omit it. You can also use second person: + > You should complete the configuration steps. Don't use the passive tense: -> The configuration steps should be completed. -!!!note "What is passive tense?" +> The configuration steps should be completed. +!!! note "What is passive tense?" If you can add "by zombies" to the end of any sentence, it is passive. - * For example: "The configuration steps should be completed." can also be read as: "The configuration should be completed BY ZOMBIES". - * Instead, you'd write this: "You should complete the configuration steps" or better still, "Complete the configuration steps". - + - For example: "The configuration steps should be completed." can also be read as: "The configuration should be completed BY ZOMBIES". + - Instead, you'd write this: "You should complete the configuration steps" or better still, "Complete the configuration steps". ## Language -* Use US English. + +- Use US English. ## Links -* Make hyperlink descriptions as descriptive as you can. This is a good description: + +- Make hyperlink descriptions as descriptive as you can. This is a good description: > Learn how to [contribute to Vizro](https://vizro.readthedocs.io/en/stable/pages/development/contributing/). @@ -125,16 +123,16 @@ Don't write this: > To learn how to contribute to Vizro, see [here](https://vizro.readthedocs.io/en/stable/pages/development/contributing/). - ### Internal cross-referencing -We use internal cross-references as follows: -* For each documentation page, if it helps the reader, we link to narrative documentation (non-API documentation) about each Vizro topic where it is first introduced. -* On any single page, we limit the repetition of links: do not re-link to the same page again unless there is good reason to do so (for example, linking to a specific sub-section to illustrate a point). -* Add links to relevant API documentation where it is useful for the reader, and consider how they will navigate from where they land in the API documentation back to the narrative content. Consider adding a link in the relevant docstring back to your page. +We use internal cross-references as follows: +- For each documentation page, if it helps the reader, we link to narrative documentation (non-API documentation) about each Vizro topic where it is first introduced. +- On any single page, we limit the repetition of links: do not re-link to the same page again unless there is good reason to do so (for example, linking to a specific sub-section to illustrate a point). +- Add links to relevant API documentation where it is useful for the reader, and consider how they will navigate from where they land in the API documentation back to the narrative content. Consider adding a link in the relevant docstring back to your page. ## Oxford commas + Use these in lists to avoid confusion. This is confusing: > The ice cream comes in a range of flavors including banana and strawberry, mango and raspberry and blueberry. @@ -158,6 +156,7 @@ Simple is not vague, verbose or full of jargon: > We leverage your existing organizational resources to synthesize novel competencies. ### Friendly + Friendly is approachable and open, and it makes discussions flow: > Vizro: Let’s make cool visualizations happen. Together. @@ -178,9 +177,10 @@ Functional is not try-hard, cliched or hyperbolic: ## Things to avoid -* **Gerunds in headings**. What are these? They are the "-ing" forms of verbs. If you find yourself writing "Getting started" in a heading, then consider "Get started" or "How to get started" instead. In fact, in general, it's better to avoid gerund-forms of verbs where you can. -* **Plagiarism**. Link to their text and credit them. -* **Colloquialisms**. Avoid them "like the plague" because they may not translate to other regions/languages. -* **Technical terminology**. This applies particularly to acronyms that do not pass the "Google test". If it is not possible to find their meaning from a simple Google search, don't use them, or explain them with a link or some text. -* **Business speak**. You can explain simply without using words like "leverage", "utilize" or "facilitate" and still sound clever. +- **Gerunds in headings**. What are these? They are the "-ing" forms of verbs. If you find yourself writing "Getting started" in a heading, then consider "Get started" or "How to get started" instead. In fact, in general, it's better to avoid gerund-forms of verbs where you can. +- **Plagiarism**. Link to their text and credit them. +- **Colloquialisms**. Avoid them "like the plague" because they may not translate to other regions/languages. +- **Technical terminology**. This applies particularly to acronyms that do not pass the "Google test". If it is not possible to find their meaning from a simple Google search, don't use them, or explain them with a link or some text. +- **Business speak**. You can explain simply without using words like "leverage", "utilize" or "facilitate" and still sound clever. + diff --git a/vizro-core/docs/pages/explanation/faq.md b/vizro-core/docs/pages/explanation/faq.md index 98dd6f051..084687701 100644 --- a/vizro-core/docs/pages/explanation/faq.md +++ b/vizro-core/docs/pages/explanation/faq.md @@ -9,72 +9,60 @@ Here are some answers to frequently asked questions: -* [Which browsers does Vizro support?](#which-browsers-does-vizro-support) -* [What is the Vizro versioning policy?](#what-is-the-vizro-versioning-policy) -* [Where can I find example dashboards?](#where-can-i-find-example-dashboards) -* [Why should I use Vizro?](#why-should-i-use-vizro) -* [How does Vizro differ from Dash or Streamlit?](#how-does-vizro-differ-from-dash-or-streamlit) -* [How does Vizro compare with Python packages and business intelligence (BI) tools?](#how-does-vizro-compare-with-python-packages-and-business-intelligence-bi-tools) -* [When would an alternative to Vizro be more suitable?](#when-would-an-alternative-to-vizro-be-more-suitable) -* [How can I report a bug?](#how-can-i-report-a-bug) -* [How can I request a feature?](#how-can-i-request-a-feature) -* [I still have a question. Where can I ask it?](#i-still-have-a-question-where-can-i-ask-it) +- [Which browsers does Vizro support?](#which-browsers-does-vizro-support) +- [What is the Vizro versioning policy?](#what-is-the-vizro-versioning-policy) +- [Where can I find example dashboards?](#where-can-i-find-example-dashboards) +- [Why should I use Vizro?](#why-should-i-use-vizro) +- [How does Vizro differ from Dash or Streamlit?](#how-does-vizro-differ-from-dash-or-streamlit) +- [How does Vizro compare with Python packages and business intelligence (BI) tools?](#how-does-vizro-compare-with-python-packages-and-business-intelligence-bi-tools) +- [When would an alternative to Vizro be more suitable?](#when-would-an-alternative-to-vizro-be-more-suitable) +- [How can I report a bug?](#how-can-i-report-a-bug) +- [How can I request a feature?](#how-can-i-request-a-feature) +- [I still have a question. Where can I ask it?](#i-still-have-a-question-where-can-i-ask-it) ## Which browsers does Vizro support? -Vizro supports the [Chrome browser](https://www.google.com/intl/en_us/chrome/). -Other browsers may work, but are not officially supported. + +Vizro supports the [Chrome browser](https://www.google.com/intl/en_us/chrome/). Other browsers may work, but are not officially supported. ## What is the Vizro versioning policy? -This project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html). -We do not consider frontend changes (such as changing the appearance of a component) to be breaking changes. -!!! note +This project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html). We do not consider frontend changes (such as changing the appearance of a component) to be breaking changes. +!!! note While being in version `0.x.x`, we may introduce breaking changes in minor versions. - ## Where can I find example dashboards? For a gallery of examples showing Vizro in action, take a look at [vizro.mckinsey.com](https://vizro.mckinsey.com). The gallery links to the [Vizro HuggingFace collection](https://huggingface.co/vizro), which includes complete code accessed for each example by selecting "Files" in the top right menu. We also maintain a separate, curated page of [videos, blog posts, and examples of Vizro usage from our community](your-examples.md). - ## Why should I use Vizro? -Vizro is a high-level framework built on top of Dash and Pydantic, -which makes it easier to build advanced dashboards -since it automates many of the otherwise complex and time-consuming tasks -traditionally associated with designing, building and deploying front-end applications, -from prototypes to production. +Vizro is a high-level framework built on top of Dash and Pydantic, which makes it easier to build advanced dashboards since it automates many of the otherwise complex and time-consuming tasks traditionally associated with designing, building and deploying front-end applications, from prototypes to production. ### You can build beautiful & powerful dashboards, quickly & easily Users can configure Vizro dashboards without needing to know advanced software development principles, nor how to build front-end applications. -??? details "See more details" +??? details "See more details"
Image title
less than 30 lines of configuration can create dashboards with multiple charts and filters
- - **Beautiful** - inbuilt visual design best practices are applied automatically, - so users can create beautiful dashboards without needing to know any HTML, CSS or design principles. + - **Beautiful** - inbuilt visual design best practices are applied automatically, so users can create beautiful dashboards without needing to know any HTML, CSS or design principles. - **Powerful** - advanced functionality and interactions come out-of-the-box, by using just a few lines of simple configuration. - - **Quick and easy** - the simple configuration follows an intuitive "grammar of dashboards" which is quick to learn and easy to use. - This removes most of the "glue code" that would otherwise need to be written. Thousands of lines of code are reduced to tens of lines of configuration. - Users can configure Vizro dashboards without needing to know any advanced software development principles of how to build front-end applications. + - **Quick and easy** - the simple configuration follows an intuitive "grammar of dashboards" which is quick to learn and easy to use. This removes most of the "glue code" that would otherwise need to be written. Thousands of lines of code are reduced to tens of lines of configuration. Users can configure Vizro dashboards without needing to know any advanced software development principles of how to build front-end applications. ### You can extend and customize infinitely Users benefit from the power of the Dash framework and the flexibility of React. ??? details "See more details" - - - **Dash** - since Vizro is built on top of Dash, then users benefit from all the underlying power and customizations offered by the Dash framework, - including the ability to use extension libraries related to Dash. + - **Dash** - since Vizro is built on top of Dash, then users benefit from all the underlying power and customizations offered by the Dash framework, including the ability to use extension libraries related to Dash. - **React** - since Dash enables JavaScript React components to be incorporated into Dash applications, Vizro users can create custom charts and UI components which offer the infinite flexibility of React. - **Vizro extensions** - adding extensions such as user defined custom charts, components, actions and data connectors is intuitively incorporated into the configuration language of Vizro. @@ -83,74 +71,54 @@ Users benefit from the power of the Dash framework and the flexibility of React. Consistency and re-usability designed for scale. ??? details "See more details" - - - **Prototype rapidly** - even complex dashboards can be created within minutes using Vizro, - which enables prototype dashboards to be created and iterated on quickly and easily, with very low barrier to entry. + - **Prototype rapidly** - even complex dashboards can be created within minutes using Vizro, which enables prototype dashboards to be created and iterated on quickly and easily, with very low barrier to entry. - **Deploy easily** - since Vizro is built on Dash which uses Flask, it is simple to deploy Vizro like any other Dash application, and use application servers such as Gunicorn to scale to multiple users. - - **Scale** - since Vizro offers standardization of visual design, application architecture and configuration language, - it is easier to scale across multiple developers, projects and implementations in a consistent and reusable way. + - **Scale** - since Vizro offers standardization of visual design, application architecture and configuration language, it is easier to scale across multiple developers, projects and implementations in a consistent and reusable way. ## How does Vizro differ from Dash or Streamlit? -Potential users sometimes request comparisons between Vizro and similar tools such as Dash and Streamlit. -In many ways a direct comparison is not possible as these products tackle somewhat different use cases and their relative pros and cons change depending on the particular requirements of each different user. +Potential users sometimes request comparisons between Vizro and similar tools such as Dash and Streamlit. In many ways a direct comparison is not possible as these products tackle somewhat different use cases and their relative pros and cons change depending on the particular requirements of each different user. Any attempt at a high-level explanation must rely on an oversimplification that misses many important nuances. With the caveat that it's not possible to "compare apples with pears", and that any comparison will have a different conclusion for different users, an oversimplified view could be: ??? details "Streamlit is great for rapid prototyping" - - - **rapid prototyping** - Streamlit's architecture allows you to write apps the same way you write plain Python scripts. - To unlock this, Streamlit apps have a unique data flow: any time something must be updated on the screen, Streamlit reruns your entire Python script from top to bottom. [[1]](https://docs.streamlit.io/library/get-started/main-concepts) - This turns data scripts into sharable web apps in minutes. [[2]](https://streamlit.io/) - Adding a widget is the same as declaring a variable. - (No need to write a backend, define routes, handle HTTP requests, connect a frontend, write HTML, CSS, JavaScript, etc. [[3]](https://streamlit.io/)) + - **rapid prototyping** - Streamlit's architecture allows you to write apps the same way you write plain Python scripts. To unlock this, Streamlit apps have a unique data flow: any time something must be updated on the screen, Streamlit reruns your entire Python script from top to bottom. [\[1\]](https://docs.streamlit.io/library/get-started/main-concepts) This turns data scripts into sharable web apps in minutes. [\[2\]](https://streamlit.io/) Adding a widget is the same as declaring a variable. (No need to write a backend, define routes, handle HTTP requests, connect a frontend, write HTML, CSS, JavaScript, etc. [\[3\]](https://streamlit.io/)) ??? details "Dash is great for customization and scalability" - - - **customization** - one of the great things about Dash is that it is built on top of React.js, a JavaScript library for building web components. - Thousands of components have been built and released with open source licenses by the React community, any of which could be adapted into a Dash component. [[4]](https://dash.plotly.com/plugins) - Dash supports adding custom CSS [[5]](https://dash.plotly.com/external-resources) and HTML, callbacks for custom behavior, - and many component libraries such as Dash Bootstrap components [[6]](https://dash-bootstrap-components.opensource.faculty.ai/) - - **scalability** - based on Flask which is widely adopted by the Python community and deployed in production environments - everywhere [[7]](https://medium.com/plotly/introducing-dash-5ecf7191b503) Dash was designed to be a stateless framework. Stateless frameworks are more scalable and robust [[8]](https://dash.plotly.com/sharing-data-between-callbacks#why-share-state?) + - **customization** - one of the great things about Dash is that it is built on top of React.js, a JavaScript library for building web components. Thousands of components have been built and released with open source licenses by the React community, any of which could be adapted into a Dash component. [\[4\]](https://dash.plotly.com/plugins) Dash supports adding custom CSS [\[5\]](https://dash.plotly.com/external-resources) and HTML, callbacks for custom behavior, and many component libraries such as Dash Bootstrap components [\[6\]](https://dash-bootstrap-components.opensource.faculty.ai/) + - **scalability** - based on Flask which is widely adopted by the Python community and deployed in production environments everywhere [\[7\]](https://medium.com/plotly/introducing-dash-5ecf7191b503) Dash was designed to be a stateless framework. Stateless frameworks are more scalable and robust [\[8\]](https://dash.plotly.com/sharing-data-between-callbacks#why-share-state?) ??? details "Vizro is great for combining rapid prototyping with customization and scalability" - - **rapid prototyping** - since Vizro is a high-level framework providing declarative configuration, it is quick and easy to create powerful interactive apps in minutes, without needing to write callbacks, HTML, CSS, or JavaScript. Key topics such as applying state management, application architecture, and testing are done automatically by Vizro. - **customization and scalability** - since Vizro is built on top of Dash, then users benefit from all the underlying power of the Dash framework for customization and scalability - **beauty and robustness** - since Vizro uses inbuilt visual design and software development best practices, it automatically generates dashboards which look beautiful and can go from prototype to production quickly and easily -All are great entry points to the world of data apps. -If you prefer a top-down scripting style, then Streamlit is a powerful approach. -If you prefer full control and customization over callbacks and layouts, then Dash is a powerful approach. -If you prefer a configuration approach with in-built best practices, and the potential for customization and scalability through Dash, then Vizro is a powerful approach. +All are great entry points to the world of data apps. If you prefer a top-down scripting style, then Streamlit is a powerful approach. If you prefer full control and customization over callbacks and layouts, then Dash is a powerful approach. If you prefer a configuration approach with in-built best practices, and the potential for customization and scalability through Dash, then Vizro is a powerful approach. -For a more detailed comparison, it may help to visit the introductory articles of [Dash](https://medium.com/plotly/introducing-dash-5ecf7191b503), [Streamlit](https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace) and [Vizro](https://quantumblack.medium.com/introducing-vizro-a-toolkit-for-creating-modular-data-visualization-applications-3a42f2bec4db), -to see how each tool serves a distinct purpose, and could be the best tool of choice. +For a more detailed comparison, it may help to visit the introductory articles of [Dash](https://medium.com/plotly/introducing-dash-5ecf7191b503), [Streamlit](https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace) and [Vizro](https://quantumblack.medium.com/introducing-vizro-a-toolkit-for-creating-modular-data-visualization-applications-3a42f2bec4db), to see how each tool serves a distinct purpose, and could be the best tool of choice. ## How does Vizro compare with Python packages and business intelligence (BI) tools? + There are a number of Python packages and BI tools which offer support for visualization applications (such as Streamlit, Plotly/Dash, Tableau and PowerBI). Vizro is intended to support several niches between the benefits from those tools, rather than being in direct comparison with any single tool. Therefore, direct comparisons are often only partially suitable, given the many features offered across this landscape. -However, in general, there are several areas of functionality where Vizro can be particularly useful, such as in providing a simple configuration to speed up the assembly of components, leveraging inbuilt visual design, application architecture, and coding standards, -along with the ability to scale easily across multiple developers and implementations. +However, in general, there are several areas of functionality where Vizro can be particularly useful, such as in providing a simple configuration to speed up the assembly of components, leveraging inbuilt visual design, application architecture, and coding standards, along with the ability to scale easily across multiple developers and implementations. ??? details "See more details" - - | Functionality | Benefits | In context of Python packages | In context of BI tools | - | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | **Assembly system**
  • Configuration-driven assembly system of Vizro automatically builds user-friendly, higher-level dashboard concepts (such as a filter) from low-level individual components (for example, a dropdown component plus a filtering function).
|
  • Removes the need for users to learn how to write the “glue code” which combines lower-level components.
  • Removes the time taken to write, test and optimize the “glue code” which combines lower-level components.
  • Reduces what can be 1000s of lines of code down to dozens of lines of configuration.
| Many Python packages still require a moderate understanding of the coding required to assemble higher-level dashboard concepts, which necessitates the creation of “glue code” to combine lower-level components.

Vizro primarily offers configuration to simplify that assembly of components offered by existing packages (currently leveraging Plotly/Dash), and so occupies a slightly different niche from libraries offering primarily the lower-level components themselves. It also removes the requirement from users to implement certain code standards for the assembled code themselves, and therefore saves time on often time consuming things such as writing unit tests and ensuring linting coverage. | Many BI tools incorporate the assembly of higher-level concepts automatically from GUI (drop-and-drag) interfaces, and occupy a slightly different niche to the configuration driven assembly offered by Vizro. | - | **Inbuilt visual design decisions**
  • UX decisions such as placement of filters and orientation of charts in relation to other components on the screen.
  • Visual design decisions such as chart formatting and spacing between components.
  • Colors including text, backgrounds and chart contents.
|
  • Ensures visual consistency within applications, and across applications built by the same user.
  • Speeds up development by removing the need to spend time on visual design decisions.
  • Removes the need for advanced expertise in visual design.
  • Ensures basic color accessibility for most likely color combinations.
| Many Python packages offer inbuilt color choices, and visual design choices for certain components.

Vizro applies that to a wide range of component combinations and complex user flows, offering a holistic and comprehensive approach to automatically enable beautiful visual design best practices, whilst allowing customization and flexibility. | Many BI tools supply inbuilt color choices and visual design choices for certain components.

Vizro offers inbuilt visual design for components in addition to the ability to customize them in a flexible way where needed (for example through CSS), and automatic arrangement of components on the screen. | - | **Inbuilt application architecture decisions**
  • The architectural decisions required to connect components in advanced ways - such as combining connecting filters to charts with multi-screen navigation to allow drill-throughs between screens.
|
  • Ensures structural consistency within applications, and across applications built by the same user.
  • Speeds up development by removing the need to spend time on architectural decisions or development.
  • Removes need for advanced expertise in application architecture.
| Many Python packages supply inbuilt application architecture choices for certain functionalities.

Vizro applies that to a wide range of component combinations and complex user flows, offering a holistic and comprehensive approach to the entire application architecture, whilst allowing customization and flexibility where relevant. | Many BI tools apply proprietary application architecture by default.

Vizro enables the user to view and understand the application architecture by directly viewing the code. | - | **Declarative configuration, in multiple formats**
  • Configuration is declarative and can be written in Python or a configuration language such as YAML, JSON and TOML.
|
  • The range of formats enables flexibility in implementations (and can be extended in future).
  • Formats such as YAML support programmatic construction of dashboards (for example being dynamically generated from a Kedro pipeline).
  • The focus on editing configuration directly, rather than via GUI or drop-and-drag interfaces, allows for ease of collaboration.
| Many Python packages give a mostly declarative configuration, with limited ability to leverage multiple formats such as Pydantic models and JSON.

Vizro simplifies this approach, and facilitates the extension of the assembly system to enable integration with other tools such as Kedro to programmatically and dynamically generate the relevant dashboard configurations in a streamlined way. | Many BI tools solely use a GUI and/or drag-and-drop interface for defining dashboards, and leverage proprietary configuration formats.

Vizro enables the user to view and understand the configuration by viewing it directly, in addition to being able to edit it directly. | - | **Mostly tech agnostic “grammar of dashboards”**
  • The configuration follows a “grammar of dashboards” which is mostly generic and tech agnostic (rather than being specific to any Python package or coding language).
|
  • Enables a more intuitive understanding of how to write the configuration.
  • Enables the configuration to apply to other Python packages or other coding languages in future. (NB: this would require an adjustment to the underlying assembly core code).
| Many Python packages supply an effective “grammar of charts” and Python specific declaration.

Vizro offers a “grammar of dashboards” with declaration which is largely tech agnostic and can be extended to non-Python languages. | Many BI tools utilize an implicit internal “grammar of dashboards” which is specific to the proprietary language(s) on with which they are built.

Vizro offers an explicit configuration grammar and allows users to leverage a mostly tech agnostic approach (which can be extended in future). | - | **Inbuilt validation**
  • The ability to leverage Pydantic models automatically give meaningful feedback to users about configuration choices.
|
  • Increases ease of use by guiding users, providing early validation and clear feedback throughout the configuration process.
  • This validation feedback can also be utilized by processes which construct the configuration programmatically, such as via a Kedro pipeline.
| Many Python packages supply individual components or non-Pydantic based models.

Vizro offers the advantages of Pydantic based models for many elements of the configuration process, which leverages the validation and guidance inherent in that process to facilitate implementation by users. | Many BI tools have inbuilt guideline systems to ensure components are combined in a valid way, and give feedback to the manual user to help guide through that process.

Vizro utilizes a flexible system which can be extended to give feedback to programmatic generation of configuration. | - | **Modularity**
  • The standardization applied by Vizro (in terms of visual design, application architecture and coding standards) makes it possible to reuse configuration, charts, components and extensions such as custom actions, between implementations.
|
  • Speeds up development by allowing reuse of existing implementations.
  • Facilitates collaboration between users by allowing knowledge to be encoded in modular ways.
| Many Python packages support modularity of components such as charts and controls.

Vizro supports modularity of groups of components (such as their implementation together as a dashboard screen), which can be easily transferred between implementations as configuration. | Many BI tools supply extensions and plugins which support modularity of visualizations.

Vizro supports modularity of groups of components (such as their implementation together as a dashboard screen), which can be easily transferred between implementations as configuration. | - | **Flexibility**
  • The ability to utilize the low-code approach of configuration with the high-code approach of custom functions offers flexibility in implementation for both less technical and more technical users.
|
  • The low-code configuration driven approach enables all users to create fairly flexible dashboards easily.
  • The high-code approach of using custom functions in a structured way gives more technical users with flexibility to extend functionality almost infinitely.
| Many Python packages offer some low-code and/or high-code approaches, which offer varying degrees of flexibility.

Vizro supports a holistic combination of low-code and high-code approaches which support less technical and more technical users individually while allowing them much flexibility in implementation according to their technical level. | Many BI tools offer a no-code (or at least low-code) approach to creating charts and dashboards, along with varying forms of plugins to increase flexibility.

Vizro unlocks Python custom functions to be able to power this user driven flexibility in a technically advanced way, with a high degree of control and visibility over the code, whilst also supporting less technical users through low-code configuration. | - | **Scaling**
  • The consistency in visual design, application architecture and code standards, combined with the ease of collaboration between Python developers, allows scaling within and between projects by facilitating reuse, extension and programmatic updates of configurations.
|
  • Sections of configuration can be reused and tailored easily, allowing implementations to scale across or between projects.
  • New joiners to a team can get up to speed quickly, allowing teams to scale in size.
  • Other teams can inherit configurations easily, allowing implementations to scale between teams.
  • Updates can be propagated to configurations from a central location, allowing adjustments and updates to scale easily across large implementations.
  • Inbuilt visual design decisions offer visual consistency.
  • Leveraging collaborative coding mechanisms such as Git enables almost any number of developers to collaborate effectively.
| Many Python packages benefit from the ability to propagate updates programmatically, while applying that to “glue code”.

Vizro makes it easy to scale by replicating the relatively small amount of configuration in 1 file between usages, rather than replicating a large amount of code across many files between usages.

Updating configuration programmatically from a central location is often easier than updating code. When sharing between users, it can be easier to inherit and understand configuration than the underlying code. The visual consistency makes it easier to scale within or between projects while maintaining visual coherence. | Many BI tools allow scaling through GUI drag-and-drop interfaces (having some functionality for duplication or propagating changes) for single users.

Vizro makes it easy to leverage tools such as Git to enable almost any number of users to collaborate effectively, therefore allowing the number of developers on a single project to scale easily.

Since updates can be propagated programmatically easily from a central location, it allows scaling across almost any number of related implementations which can be kept up to date and aligned without the need to manually adjust each implementation when updates are required. | - | **Python first**
  • Leveraging Pydantic and Plotly/Dash give a Python first approach (whilst making use of a mostly tech agnostic configuration system).
  • (Since Plotly/Dash leverage React components, and allow them to be used as components, then JavaScript can also be used in a form that is effectively wrapped in Python).
|
  • This empowers a wider group of practitioners that are already close to data analytics, since they are more likely to have existing skills in Python than JavaScript.
  • This offers the advantage of leveraging existing Python work spaces such as notebooks and IDEs.
  • Facilitates multi-developer collaboration via tools such as Git.
| Python packages are already Python focused.

Vizro is no different in this respect. By leveraging Plotly/Dash, Vizro is also able to benefit from the power and flexibility offered by JavaScript via React, whilst still presenting a format that is Python first to the user (by making use of the ability offered by Dash to effectively wrap those components into Python). | Many BI tools do not offer direct or full integration with Python.

Vizro supports a Python first approach which leverages the power and flexibility of Python, and the open source community supporting that wide ranging functionality. | - | **Open source**
  • The use of an open source license, and the reliance on open source packages.
  • The provision of ongoing development and maintenance.
|
  • There is no license fee required to utilize Vizro.
  • Ongoing development and maintenance increases the long term usability of the Vizro package, and viability of implementations.
| Many Python packages also use an open source license, and offer ongoing development and maintenance.

Vizro is no different in this respect. | Many BI tools follow a license fee model and/or charge for ongoing development and maintenance.

Vizro requires no license fee, and offers ongoing development and support, which helps to remove some barriers to usage. | + | Functionality | Benefits | In context of Python packages | In context of BI tools | + | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | **Assembly system**
  • Configuration-driven assembly system of Vizro automatically builds user-friendly, higher-level dashboard concepts (such as a filter) from low-level individual components (for example, a dropdown component plus a filtering function).
|
  • Removes the need for users to learn how to write the “glue code” which combines lower-level components.
  • Removes the time taken to write, test and optimize the “glue code” which combines lower-level components.
  • Reduces what can be 1000s of lines of code down to dozens of lines of configuration.
| Many Python packages still require a moderate understanding of the coding required to assemble higher-level dashboard concepts, which necessitates the creation of “glue code” to combine lower-level components.

Vizro primarily offers configuration to simplify that assembly of components offered by existing packages (currently leveraging Plotly/Dash), and so occupies a slightly different niche from libraries offering primarily the lower-level components themselves. It also removes the requirement from users to implement certain code standards for the assembled code themselves, and therefore saves time on often time consuming things such as writing unit tests and ensuring linting coverage. | Many BI tools incorporate the assembly of higher-level concepts automatically from GUI (drop-and-drag) interfaces, and occupy a slightly different niche to the configuration driven assembly offered by Vizro. | + | **Inbuilt visual design decisions**
  • UX decisions such as placement of filters and orientation of charts in relation to other components on the screen.
  • Visual design decisions such as chart formatting and spacing between components.
  • Colors including text, backgrounds and chart contents.
|
  • Ensures visual consistency within applications, and across applications built by the same user.
  • Speeds up development by removing the need to spend time on visual design decisions.
  • Removes the need for advanced expertise in visual design.
  • Ensures basic color accessibility for most likely color combinations.
| Many Python packages offer inbuilt color choices, and visual design choices for certain components.

Vizro applies that to a wide range of component combinations and complex user flows, offering a holistic and comprehensive approach to automatically enable beautiful visual design best practices, whilst allowing customization and flexibility. | Many BI tools supply inbuilt color choices and visual design choices for certain components.

Vizro offers inbuilt visual design for components in addition to the ability to customize them in a flexible way where needed (for example through CSS), and automatic arrangement of components on the screen. | + | **Inbuilt application architecture decisions**
  • The architectural decisions required to connect components in advanced ways - such as combining connecting filters to charts with multi-screen navigation to allow drill-throughs between screens.
|
  • Ensures structural consistency within applications, and across applications built by the same user.
  • Speeds up development by removing the need to spend time on architectural decisions or development.
  • Removes need for advanced expertise in application architecture.
| Many Python packages supply inbuilt application architecture choices for certain functionalities.

Vizro applies that to a wide range of component combinations and complex user flows, offering a holistic and comprehensive approach to the entire application architecture, whilst allowing customization and flexibility where relevant. | Many BI tools apply proprietary application architecture by default.

Vizro enables the user to view and understand the application architecture by directly viewing the code. | + | **Declarative configuration, in multiple formats**
  • Configuration is declarative and can be written in Python or a configuration language such as YAML, JSON and TOML.
|
  • The range of formats enables flexibility in implementations (and can be extended in future).
  • Formats such as YAML support programmatic construction of dashboards (for example being dynamically generated from a Kedro pipeline).
  • The focus on editing configuration directly, rather than via GUI or drop-and-drag interfaces, allows for ease of collaboration.
| Many Python packages give a mostly declarative configuration, with limited ability to leverage multiple formats such as Pydantic models and JSON.

Vizro simplifies this approach, and facilitates the extension of the assembly system to enable integration with other tools such as Kedro to programmatically and dynamically generate the relevant dashboard configurations in a streamlined way. | Many BI tools solely use a GUI and/or drag-and-drop interface for defining dashboards, and leverage proprietary configuration formats.

Vizro enables the user to view and understand the configuration by viewing it directly, in addition to being able to edit it directly. | + | **Mostly tech agnostic “grammar of dashboards”**
  • The configuration follows a “grammar of dashboards” which is mostly generic and tech agnostic (rather than being specific to any Python package or coding language).
|
  • Enables a more intuitive understanding of how to write the configuration.
  • Enables the configuration to apply to other Python packages or other coding languages in future. (NB: this would require an adjustment to the underlying assembly core code).
| Many Python packages supply an effective “grammar of charts” and Python specific declaration.

Vizro offers a “grammar of dashboards” with declaration which is largely tech agnostic and can be extended to non-Python languages. | Many BI tools utilize an implicit internal “grammar of dashboards” which is specific to the proprietary language(s) on with which they are built.

Vizro offers an explicit configuration grammar and allows users to leverage a mostly tech agnostic approach (which can be extended in future). | + | **Inbuilt validation**
  • The ability to leverage Pydantic models automatically give meaningful feedback to users about configuration choices.
|
  • Increases ease of use by guiding users, providing early validation and clear feedback throughout the configuration process.
  • This validation feedback can also be utilized by processes which construct the configuration programmatically, such as via a Kedro pipeline.
| Many Python packages supply individual components or non-Pydantic based models.

Vizro offers the advantages of Pydantic based models for many elements of the configuration process, which leverages the validation and guidance inherent in that process to facilitate implementation by users. | Many BI tools have inbuilt guideline systems to ensure components are combined in a valid way, and give feedback to the manual user to help guide through that process.

Vizro utilizes a flexible system which can be extended to give feedback to programmatic generation of configuration. | + | **Modularity**
  • The standardization applied by Vizro (in terms of visual design, application architecture and coding standards) makes it possible to reuse configuration, charts, components and extensions such as custom actions, between implementations.
|
  • Speeds up development by allowing reuse of existing implementations.
  • Facilitates collaboration between users by allowing knowledge to be encoded in modular ways.
| Many Python packages support modularity of components such as charts and controls.

Vizro supports modularity of groups of components (such as their implementation together as a dashboard screen), which can be easily transferred between implementations as configuration. | Many BI tools supply extensions and plugins which support modularity of visualizations.

Vizro supports modularity of groups of components (such as their implementation together as a dashboard screen), which can be easily transferred between implementations as configuration. | + | **Flexibility**
  • The ability to utilize the low-code approach of configuration with the high-code approach of custom functions offers flexibility in implementation for both less technical and more technical users.
|
  • The low-code configuration driven approach enables all users to create fairly flexible dashboards easily.
  • The high-code approach of using custom functions in a structured way gives more technical users with flexibility to extend functionality almost infinitely.
| Many Python packages offer some low-code and/or high-code approaches, which offer varying degrees of flexibility.

Vizro supports a holistic combination of low-code and high-code approaches which support less technical and more technical users individually while allowing them much flexibility in implementation according to their technical level. | Many BI tools offer a no-code (or at least low-code) approach to creating charts and dashboards, along with varying forms of plugins to increase flexibility.

Vizro unlocks Python custom functions to be able to power this user driven flexibility in a technically advanced way, with a high degree of control and visibility over the code, whilst also supporting less technical users through low-code configuration. | + | **Scaling**
  • The consistency in visual design, application architecture and code standards, combined with the ease of collaboration between Python developers, allows scaling within and between projects by facilitating reuse, extension and programmatic updates of configurations.
|
  • Sections of configuration can be reused and tailored easily, allowing implementations to scale across or between projects.
  • New joiners to a team can get up to speed quickly, allowing teams to scale in size.
  • Other teams can inherit configurations easily, allowing implementations to scale between teams.
  • Updates can be propagated to configurations from a central location, allowing adjustments and updates to scale easily across large implementations.
  • Inbuilt visual design decisions offer visual consistency.
  • Leveraging collaborative coding mechanisms such as Git enables almost any number of developers to collaborate effectively.
| Many Python packages benefit from the ability to propagate updates programmatically, while applying that to “glue code”.

Vizro makes it easy to scale by replicating the relatively small amount of configuration in 1 file between usages, rather than replicating a large amount of code across many files between usages.

Updating configuration programmatically from a central location is often easier than updating code. When sharing between users, it can be easier to inherit and understand configuration than the underlying code. The visual consistency makes it easier to scale within or between projects while maintaining visual coherence. | Many BI tools allow scaling through GUI drag-and-drop interfaces (having some functionality for duplication or propagating changes) for single users.

Vizro makes it easy to leverage tools such as Git to enable almost any number of users to collaborate effectively, therefore allowing the number of developers on a single project to scale easily.

Since updates can be propagated programmatically easily from a central location, it allows scaling across almost any number of related implementations which can be kept up to date and aligned without the need to manually adjust each implementation when updates are required. | + | **Python first**
  • Leveraging Pydantic and Plotly/Dash give a Python first approach (whilst making use of a mostly tech agnostic configuration system).
  • (Since Plotly/Dash leverage React components, and allow them to be used as components, then JavaScript can also be used in a form that is effectively wrapped in Python).
|
  • This empowers a wider group of practitioners that are already close to data analytics, since they are more likely to have existing skills in Python than JavaScript.
  • This offers the advantage of leveraging existing Python work spaces such as notebooks and IDEs.
  • Facilitates multi-developer collaboration via tools such as Git.
| Python packages are already Python focused.

Vizro is no different in this respect. By leveraging Plotly/Dash, Vizro is also able to benefit from the power and flexibility offered by JavaScript via React, whilst still presenting a format that is Python first to the user (by making use of the ability offered by Dash to effectively wrap those components into Python). | Many BI tools do not offer direct or full integration with Python.

Vizro supports a Python first approach which leverages the power and flexibility of Python, and the open source community supporting that wide ranging functionality. | + | **Open source**
  • The use of an open source license, and the reliance on open source packages.
  • The provision of ongoing development and maintenance.
|
  • There is no license fee required to utilize Vizro.
  • Ongoing development and maintenance increases the long term usability of the Vizro package, and viability of implementations.
| Many Python packages also use an open source license, and offer ongoing development and maintenance.

Vizro is no different in this respect. | Many BI tools follow a license fee model and/or charge for ongoing development and maintenance.

Vizro requires no license fee, and offers ongoing development and support, which helps to remove some barriers to usage. | ## When would an alternative to Vizro be more suitable? @@ -162,18 +130,14 @@ There are a number of cases where alternatives to Vizro may be more suitable, in - where Python developers are already very comfortable leveraging other Python packages - - ## How can I report a bug? Head over to our [GitHub issues](https://github.com/mckinsey/vizro/issues) and [create a new bug report](https://github.com/mckinsey/vizro/issues/new/choose). We will try to reproduce the bug you've reported and follow up with the next steps. - ## How can I request a feature? To raise a feature request, head to our [GitHub issues](https://github.com/mckinsey/vizro/issues) and [create a new feature request](https://github.com/mckinsey/vizro/issues/new/choose). The team will then try to understand the request in more detail, explore the feasibility and prioritize it in relation to the current roadmap. We will get back to you as soon as possible with an estimate of whether and when this feature could be released. - ## I still have a question. Where can I ask it? We are happy to receive general questions around Vizro. Take a look at our [GitHub issues](https://github.com/mckinsey/vizro/issues) and [create a new issue](https://github.com/mckinsey/vizro/issues/new/choose) by clicking "General question". diff --git a/vizro-core/docs/pages/explanation/your-examples.md b/vizro-core/docs/pages/explanation/your-examples.md index 6f1da044a..91a0baa2b 100644 --- a/vizro-core/docs/pages/explanation/your-examples.md +++ b/vizro-core/docs/pages/explanation/your-examples.md @@ -4,37 +4,43 @@ This page lists videos, blog posts, and examples of Vizro usage in repositories If you have something you'd like us to include on the list, or spot something that we should include, let us know: -* you can [raise an issue](https://github.com/mckinsey/vizro/issues) on the Vizro repository, -* better still, you can [make a PR to contribute](../explanation/contributing.md) to this page. - +- you can [raise an issue](https://github.com/mckinsey/vizro/issues) on the Vizro repository, +- better still, you can [make a PR to contribute](../explanation/contributing.md) to this page. !!! note - The Vizro team and QuantumBlack, AI by McKinsey, do not take responsibility for third party content. In curating the list below, we may inspect or test an example at time of inclusion, but cannot guarantee the content thereafter. ## Videos -* From [Charming Data on YouTube](https://www.youtube.com/@CharmingData): - * [Build Python Data Apps with Vizro Dash](https://www.youtube.com/watch?v=wmQ6_GZ0zSk). - * [Introduction to Vizro Actions - Plotly Dash](https://www.youtube.com/watch?v=bom-9275Cic&t=8s). - * [Use Dash AG Grid within a Vizro app](https://www.youtube.com/watch?v=YvtVcXwQw0E). - * [Visual Vocabulary Dashboard showcasing charting options in Vizro and Plotly](https://www.youtube.com/watch?v=OZNAokBKT-M). +- From [Charming Data on YouTube](https://www.youtube.com/@CharmingData): + - [Build Python Data Apps with Vizro Dash](https://www.youtube.com/watch?v=wmQ6_GZ0zSk). + - [Introduction to Vizro Actions - Plotly Dash](https://www.youtube.com/watch?v=bom-9275Cic&t=8s). + - [Use Dash AG Grid within a Vizro app](https://www.youtube.com/watch?v=YvtVcXwQw0E). + - [Visual Vocabulary Dashboard showcasing charting options in Vizro and Plotly](https://www.youtube.com/watch?v=OZNAokBKT-M). ## Blog posts -* [Introducing Vizro](https://quantumblack.medium.com/introducing-vizro-a-toolkit-for-creating-modular-data-visualization-applications-3a42f2bec4db). -* [Creating Custom Dashboards with Vizro: A Comprehensive Guide](https://medium.com/@saffand03/creating-custom-dashboards-with-vizro-a-comprehensive-guide-73c69c6f851e). + +- [Introducing Vizro](https://quantumblack.medium.com/introducing-vizro-a-toolkit-for-creating-modular-data-visualization-applications-3a42f2bec4db). +- [Creating Custom Dashboards with Vizro: A Comprehensive Guide](https://medium.com/@saffand03/creating-custom-dashboards-with-vizro-a-comprehensive-guide-73c69c6f851e). + -* [I built a reusable dashboard read-the-docs traffic analytics using vizro](https://medium.com/towards-data-science/i-built-a-reusable-dashboard-for-read-the-docs-traffic-analytics-using-vizro-47dc15dc04f8). + +- [I built a reusable dashboard read-the-docs traffic analytics using vizro](https://medium.com/towards-data-science/i-built-a-reusable-dashboard-for-read-the-docs-traffic-analytics-using-vizro-47dc15dc04f8). + -* [Visualizing data science insights](https://medium.com/quantumblack/visualizing-data-science-insights-dfc8ad0646b6). + +- [Visualizing data science insights](https://medium.com/quantumblack/visualizing-data-science-insights-dfc8ad0646b6). + -* [A low-code, attractive, sharable data dashboard: Illustrating my LinkedIn connections in 100 lines of Python](https://medium.com/design-bootcamp/a-low-code-attractive-sharable-data-dashboard-a60badba2a03). + +- [A low-code, attractive, sharable data dashboard: Illustrating my LinkedIn connections in 100 lines of Python](https://medium.com/design-bootcamp/a-low-code-attractive-sharable-data-dashboard-a60badba2a03). ## Examples on GitHub or PyCafe -* [Personal Vizro app demos by Vizro team member `huong-li-nguyen`](https://github.com/huong-li-nguyen/vizro-app-demos). -* [Proof of concept example by `viiviandias`](https://github.com/viiviandias/poc-vizro/blob/main/brasil_stocks.ipynb). -* [Amazon sales analysis by `Bottleneck44`](https://github.com/Bottleneck44/Amazon-Sales-Analysis/blob/main/Amazon-analysis.ipynb). -* [Insight-AI: Chart and business insight generation by `micky091` using vizro-ai](https://github.com/micky0919/insight-ai) -* [Music trend analysis using Vizro](https://py.cafe/app/KhushaliP/vizro-music-trend-analysis) by [`KhushaliP`](https://github.com/KhushaliP) +- [Personal Vizro app demos by Vizro team member `huong-li-nguyen`](https://github.com/huong-li-nguyen/vizro-app-demos). +- [Proof of concept example by `viiviandias`](https://github.com/viiviandias/poc-vizro/blob/main/brasil_stocks.ipynb). +- [Amazon sales analysis by `Bottleneck44`](https://github.com/Bottleneck44/Amazon-Sales-Analysis/blob/main/Amazon-analysis.ipynb). +- [Insight-AI: Chart and business insight generation by `micky091` using vizro-ai](https://github.com/micky0919/insight-ai) +- [Music trend analysis using Vizro](https://py.cafe/app/KhushaliP/vizro-music-trend-analysis) by [`KhushaliP`](https://github.com/KhushaliP) + diff --git a/vizro-core/docs/pages/tutorials/explore-components.md b/vizro-core/docs/pages/tutorials/explore-components.md index 52a0ef3e3..1ed53d464 100644 --- a/vizro-core/docs/pages/tutorials/explore-components.md +++ b/vizro-core/docs/pages/tutorials/explore-components.md @@ -23,12 +23,10 @@ Vizro uses [`Graph`][vizro.models.Graph] objects and [Plotly Express functions]( The code below shows the steps necessary to add a box plot to the page: 1. Add a Vizro [`Graph`][vizro.models.Graph] to the `components` list. -2. Add a [`plotly.express.box`](https://plotly.com/python-api-reference/generated/plotly.express.box.html#plotly.express.box) figure to the list of components. - +1. Add a [`plotly.express.box`](https://plotly.com/python-api-reference/generated/plotly.express.box.html#plotly.express.box) figure to the list of components. !!! example "First component" === "app.py" - ```{.python pycafe-link} from vizro import Vizro import vizro.models as vm @@ -55,23 +53,19 @@ The code below shows the steps necessary to add a box plot to the page: ``` === "Result" - - [![FirstPage1]][FirstPage1] - - [FirstPage1]: ../../assets/tutorials/dashboard/dashboard21.png - + [![FirstPage1]][firstpage1] ??? note "To run the dashboard in a Notebook or script" - Paste the above code into a Notebook cell, run the Notebook, and evaluate it. --- + If you prefer to use Python scripts to Notebooks, here's how to try out the dashboard: 1. Create a new script called `app.py`. - 2. Copy the code above into the script. - 3. Navigate to the directory where `app.py` file is located using your terminal. - 4. Run the script by executing the command `python app.py`. + 1. Copy the code above into the script. + 1. Navigate to the directory where `app.py` file is located using your terminal. + 1. Run the script by executing the command `python app.py`. Once the script is running, open your web browser and go to `localhost:8050`. You should see the dashboard page with the gapminder data displayed, as shown in the `Result` tab above. @@ -83,11 +77,10 @@ You can combine and arrange various types of `components` on a dashboard page. T The code below adds two components to the page: -* A [`Card`][vizro.models.Card] to insert markdown text into the dashboard. -* A [`Graph`][vizro.models.Graph] to illustrate GDP development per continent since 1952 as a line graph. +- A [`Card`][vizro.models.Card] to insert markdown text into the dashboard. +- A [`Graph`][vizro.models.Graph] to illustrate GDP development per continent since 1952 as a line graph. !!! warning "Before you run this code in a Jupyter Notebook" - If you are following this tutorial in a Jupyter Notebook, you need to restart the kernel each time you evaluate the code. If you do not, you will see error messages such as "Components must uniquely map..." because those components already exist from the previous evaluation. !!! example "Add components" @@ -103,6 +96,7 @@ The code below adds two components to the page: ) ``` + === "Code second component" ```py @@ -113,8 +107,8 @@ The code below adds two components to the page: "gdpPercap":"GDP Per Cap"}, title=''), ) ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro import vizro.models as vm @@ -152,15 +146,13 @@ The code below adds two components to the page: dashboard = vm.Dashboard(pages=[first_page]) Vizro().build(dashboard).run() ``` - === "Result" - [![FirstPage2]][FirstPage2] - [FirstPage2]: ../../assets/tutorials/dashboard/dashboard22.png + === "Result" + [![FirstPage2]][firstpage2] As you explore the dashboard, you may notice that the current layout could be further enhanced. The charts appear cramped, while the text component has ample unused space. The next section explains how to configure the layout and arrange the components. !!! note "An introduction to Vizro-AI" - In the example above, the code to create the line graph was generated using [Vizro-AI](https://vizro.readthedocs.io/en/latest/pages/tutorials/first-dashboard/). Vizro-AI enables you to use English, or other languages, to create interactive charts with [Plotly](https://plotly.com/python/) by simplifying the process through use of a large language model. In essence, Vizro-AI generates code from natural language instructions so that you can add it into a Vizro dashboard, such as in the example above. Find out more in the [Vizro-AI documentation](https://vizro.readthedocs.io/projects/vizro-ai/)! @@ -169,32 +161,23 @@ As you explore the dashboard, you may notice that the current layout could be fu By default, Vizro places each element in the order it was added to `components` list, and spaces them equally. -You can use the [`Layout`][vizro.models.Layout] object to specify the placement and size of components on the page. To learn more about how to -configure layouts, check out [How to use layouts](../user-guides/layouts.md). +You can use the [`Layout`][vizro.models.Layout] object to specify the placement and size of components on the page. To learn more about how to configure layouts, check out [How to use layouts](../user-guides/layouts.md). -The following layout configuration positions the text at the top and the two charts side -by side, giving them more space relative to the text component: +The following layout configuration positions the text at the top and the two charts side by side, giving them more space relative to the text component: ```python -grid=[ [0, 0], - [1, 2], - [1, 2], - [1, 2] ] +grid = [[0, 0], [1, 2], [1, 2], [1, 2]] ``` -Vizro interprets these values as follows. First, the configuration divides the available space into two columns and -four rows. Each element in the list (such as `[0,0]`) represents one row of the grid layout: +Vizro interprets these values as follows. First, the configuration divides the available space into two columns and four rows. Each element in the list (such as `[0,0]`) represents one row of the grid layout: ![image1](../../assets/tutorials/dashboard/dashboard231.png) -Each element in the `components` list is referenced with a unique number, and placed on the grid as visualized with the white frames. The `Card`, is referenced by 0 as it is the first element in the `components` list. It is placed in the first row and spans across both -columns (`[0, 0]`). The two `Graph` objects, referenced by 1 and 2, are positioned next to each other and occupy a column each. +Each element in the `components` list is referenced with a unique number, and placed on the grid as visualized with the white frames. The `Card`, is referenced by 0 as it is the first element in the `components` list. It is placed in the first row and spans across both columns (`[0, 0]`). The two `Graph` objects, referenced by 1 and 2, are positioned next to each other and occupy a column each. ![image2](../../assets/tutorials/dashboard/dashboard233.png) -The `Graph` objects occupy three rows, denoted by `[1, 2], [1, 2], [1, 2]`, while the -`Card` only occupies one row `[0, 0]`. As a result, the `Graph` objects occupy three-quarters of the vertical space, while the -`Card` occupies one-quarter of it. +The `Graph` objects occupy three rows, denoted by `[1, 2], [1, 2], [1, 2]`, while the `Card` only occupies one row `[0, 0]`. As a result, the `Graph` objects occupy three-quarters of the vertical space, while the `Card` occupies one-quarter of it. ![image3](../../assets/tutorials/dashboard/dashboard232.png) @@ -205,8 +188,8 @@ Run the code below to apply the layout to the dashboard page: ```py layout=vm.Layout(grid=[[0, 0], [1, 2], [1, 2], [1, 2]]) ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro import vizro.models as vm @@ -244,32 +227,24 @@ Run the code below to apply the layout to the dashboard page: dashboard = vm.Dashboard(pages=[first_page]) Vizro().build(dashboard).run() ``` - === "Result" - [![FirstPage3]][FirstPage3] - - [FirstPage3]: ../../assets/tutorials/dashboard/dashboard23.png + === "Result" + [![FirstPage3]][firstpage3] ### 2.4. Add a control for dashboard interactivity -Controls add interactivity to the dashboard page and make it more dynamic, enabling users -to have greater control and customization over the displayed data and components. +Controls add interactivity to the dashboard page and make it more dynamic, enabling users to have greater control and customization over the displayed data and components. There are two types of control: -* [`Filters`][vizro.models.Filter] enable users to filter a column of the underlying data. -* [`Parameters`][vizro.models.Parameter] enable users to change arguments or properties of the components, such as adjusting colors. - +- [`Filters`][vizro.models.Filter] enable users to filter a column of the underlying data. +- [`Parameters`][vizro.models.Parameter] enable users to change arguments or properties of the components, such as adjusting colors. The guides on [`How to use Filters`](../user-guides/filters.md) and [`How to use Parameters`](../user-guides/parameters.md) offer instructions on their application. For further customization, refer to the guide on [`How to use selectors`](../user-guides/selectors.md). To link a control to a component, use an `id` assigned to the component, which is unique across all dashboard pages and serves as a reference to target it. -To illustrate, let's add a [`Filter`][vizro.models.Filter] on specific -continents of the underlying gapminder data. The [`Filter`][vizro.models.Filter] requires the `column` argument, that denotes -the target column to be filtered. Each `control` also has a `targets` parameter, to specify the -data and components targeted by the `control`. For this dashboard, both charts -are listed in the `targets` parameter, meaning that the filter is be applied to both charts. However, you can apply the [`Filter`][vizro.models.Filter] to only one specific chart if required. +To illustrate, let's add a [`Filter`][vizro.models.Filter] on specific continents of the underlying gapminder data. The [`Filter`][vizro.models.Filter] requires the `column` argument, that denotes the target column to be filtered. Each `control` also has a `targets` parameter, to specify the data and components targeted by the `control`. For this dashboard, both charts are listed in the `targets` parameter, meaning that the filter is be applied to both charts. However, you can apply the [`Filter`][vizro.models.Filter] to only one specific chart if required. !!! example "Configure filter" === "Code" @@ -278,8 +253,8 @@ are listed in the `targets` parameter, meaning that the filter is be applied to vm.Filter(column="continent", targets=["box_cont", "line_gdp"]), ] ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro import vizro.models as vm @@ -324,16 +299,14 @@ are listed in the `targets` parameter, meaning that the filter is be applied to ``` === "Result" - [![FirstPage4]][FirstPage4] - - [FirstPage4]: ../../assets/tutorials/dashboard/dashboard24.png + [![FirstPage4]][firstpage4] Fantastic job! You have completed first dashboard page and gained valuable skills to: 1. [Create an initial figure on a dashboard page](#2-create-a-first-dashboard-page) -2. [Add extra components](#22-add-further-components) -3. [Arrange them in a layout configuration](#23-configure-the-layout) -4. [Set up an interactive dashboard control](#24-add-a-control-for-dashboard-interactivity). +1. [Add extra components](#22-add-further-components) +1. [Arrange them in a layout configuration](#23-configure-the-layout) +1. [Set up an interactive dashboard control](#24-add-a-control-for-dashboard-interactivity). ## 3. Create a second dashboard page @@ -343,16 +316,10 @@ Every [`Page`][vizro.models.Page] that you want to display needs to be added to In creating a [`Parameter`][vizro.models.Parameter] object, you define the `target` it applies to. In the code below: -* The first parameter enables the user to change the color mapping for the `virginica` category of the iris data, targeting both charts. -* The second parameter adjusts the opacity of the first chart alone, through `scatter_iris.opacity`. - +- The first parameter enables the user to change the color mapping for the `virginica` category of the iris data, targeting both charts. +- The second parameter adjusts the opacity of the first chart alone, through `scatter_iris.opacity`. -In general, `targets` for [`Parameters`][vizro.models.Parameter] are set following the structure of -`component_id.argument`. In certain cases, you may see a nested structure for the `targets`. An example of this is -`scatter_iris.color_discrete_map.virginica`. A nested structure targets a specific attribute within a -component. In this particular example, it specifies that only the color of the virginica flower type should be changed. -More information on how to set `targets` for [`Parameters`][vizro.models.Parameter] can be found in the [how-to guide -for parameters](../user-guides/parameters.md). +In general, `targets` for [`Parameters`][vizro.models.Parameter] are set following the structure of `component_id.argument`. In certain cases, you may see a nested structure for the `targets`. An example of this is `scatter_iris.color_discrete_map.virginica`. A nested structure targets a specific attribute within a component. In this particular example, it specifies that only the color of the virginica flower type should be changed. More information on how to set `targets` for [`Parameters`][vizro.models.Parameter] can be found in the [how-to guide for parameters](../user-guides/parameters.md). !!! example "Second page" === "Code" @@ -392,8 +359,8 @@ for parameters](../user-guides/parameters.md). ], ) ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro import vizro.models as vm @@ -470,25 +437,19 @@ for parameters](../user-guides/parameters.md). dashboard = vm.Dashboard(pages=[first_page,second_page]) Vizro().build(dashboard).run() ``` - === "Result" - [![SecondPage]][SecondPage] - [SecondPage]: ../../assets/tutorials/dashboard/dashboard3.png + === "Result" + [![SecondPage]][secondpage] ### 3.1. Customize with selectors -The code in the example above uses two different types of [`selector`](../user-guides/selectors.md) objects, namely -[`Dropdown`][vizro.models.Dropdown] and [`Slider`][vizro.models.Slider] upon the -[`Parameters`][vizro.models.Parameter]. The `selectors` enable configuration of the controls to customize their behavior and appearance. +The code in the example above uses two different types of [`selector`](../user-guides/selectors.md) objects, namely [`Dropdown`][vizro.models.Dropdown] and [`Slider`][vizro.models.Slider] upon the [`Parameters`][vizro.models.Parameter]. The `selectors` enable configuration of the controls to customize their behavior and appearance. -The first parameter is a [`Dropdown`][vizro.models.Dropdown]. It is configured with two available -options, disables multi-selection, and has a default `value` set to blue. Users can choose a single option -from the dropdown. +The first parameter is a [`Dropdown`][vizro.models.Dropdown]. It is configured with two available options, disables multi-selection, and has a default `value` set to blue. Users can choose a single option from the dropdown. The second parameter is a [`Slider`][vizro.models.Slider] with a default value of 0.8. Users can adjust a value within the specified range of `min=0` and `max=1`. -You can apply selectors to configure [`Filters`][vizro.models.Filter] and -[`Parameters`][vizro.models.Parameter] to fine-tune the behavior and appearance of the controls. The selectors currently available are as follows: +You can apply selectors to configure [`Filters`][vizro.models.Filter] and [`Parameters`][vizro.models.Parameter] to fine-tune the behavior and appearance of the controls. The selectors currently available are as follows: - [`Parameter`][vizro.models.Parameter]: - [`Checklist`][vizro.models.Checklist] @@ -499,22 +460,15 @@ You can apply selectors to configure [`Filters`][vizro.models.Filter] and ## 4. The final touches -This section puts everything together by adding a -homepage to the example for navigation between the two separate pages. +This section puts everything together by adding a homepage to the example for navigation between the two separate pages. -For easy navigation within your dashboard, we'll create a page that serves as the entry point for the user. -On this homepage are two [`Cards`][vizro.models.Card] which serve as tiles that can be customized with a title, some text, and an -image. These cards link to the subpages within your dashboard using their `href` attributes as `href="/first-page"` and `href="/second-page"`. This -establishes the navigation links from the homepage to each of the subpages. +For easy navigation within your dashboard, we'll create a page that serves as the entry point for the user. On this homepage are two [`Cards`][vizro.models.Card] which serve as tiles that can be customized with a title, some text, and an image. These cards link to the subpages within your dashboard using their `href` attributes as `href="/first-page"` and `href="/second-page"`. This establishes the navigation links from the homepage to each of the subpages. -Each page is added to the dashboard using the following line of code: -`vm.Dashboard(pages=[home_page, first_page, second_page])`. This ensures that all the pages are accessible. +Each page is added to the dashboard using the following line of code: `vm.Dashboard(pages=[home_page, first_page, second_page])`. This ensures that all the pages are accessible. -The code below illustrates a functional dashboard where you can navigate from the homepage to each -of the subpages. Additionally, you can use the navigation panel on the left side to switch between the three pages. +The code below illustrates a functional dashboard where you can navigate from the homepage to each of the subpages. Additionally, you can use the navigation panel on the left side to switch between the three pages. !!! example "Final dashboard" - === "Code" ```py home_page = vm.Page( @@ -543,11 +497,12 @@ of the subpages. Additionally, you can use the navigation panel on the left side ], ) ``` + ```py dashboard = vm.Dashboard(pages=[home_page, first_page, second_page]) ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro @@ -651,31 +606,23 @@ of the subpages. Additionally, you can use the navigation panel on the left side dashboard = vm.Dashboard(pages=[home_page, first_page, second_page]) Vizro().build(dashboard).run() ``` - === "Homepage" - [![FinalPage]][FinalPage] - [FinalPage]: ../../assets/tutorials/dashboard/dashboard4.png + === "Homepage" + [![FinalPage]][finalpage] === "Subpage1" - [![FinalPage1]][FinalPage1] - - [FinalPage1]: ../../assets/tutorials/dashboard/dashboard2.png + [![FinalPage1]][finalpage1] === "Subpage2" - [![FinalPage2]][FinalPage2] + [![FinalPage2]][finalpage2] - [FinalPage2]: ../../assets/tutorials/dashboard/dashboard3.png - -Congratulations on completing this tutorial! You have acquired the knowledge to configure layouts, add components, and -implement interactivity in Vizro dashboards, working across two navigable pages. +Congratulations on completing this tutorial! You have acquired the knowledge to configure layouts, add components, and implement interactivity in Vizro dashboards, working across two navigable pages. ## Find out more After completing the tutorial you now have a solid understanding of the main elements of Vizro and how to bring them together to create dynamic and interactive data visualizations. -You can find out more about the Vizro by reading the [components overview page](../user-guides/components.md). To gain more in-depth knowledge about the usage and configuration details of individual controls, check out the guides dedicated to [Filters](../user-guides/filters.md), [Parameters](../user-guides/parameters.md) -and [Selectors](../user-guides/selectors.md). If you'd like to understand more about different ways to configure the navigation of your dashboard, head -to [Navigation](../user-guides/navigation.md). +You can find out more about the Vizro by reading the [components overview page](../user-guides/components.md). To gain more in-depth knowledge about the usage and configuration details of individual controls, check out the guides dedicated to [Filters](../user-guides/filters.md), [Parameters](../user-guides/parameters.md) and [Selectors](../user-guides/selectors.md). If you'd like to understand more about different ways to configure the navigation of your dashboard, head to [Navigation](../user-guides/navigation.md). Vizro doesn't end here, and we only covered the key features, but there is still much more to explore! You can learn: @@ -683,3 +630,12 @@ Vizro doesn't end here, and we only covered the key features, but there is still - How to add custom styling using [static assets](../user-guides/assets.md) such as custom css or JavaScript files. - How to use [Actions](../user-guides/actions.md) for example, for chart interaction or custom controls. - How to create dashboards from `yaml`, `dict` or `json` following the [dashboard guide](../user-guides/dashboard.md). + +[finalpage]: ../../assets/tutorials/dashboard/dashboard4.png +[finalpage1]: ../../assets/tutorials/dashboard/dashboard2.png +[finalpage2]: ../../assets/tutorials/dashboard/dashboard3.png +[firstpage1]: ../../assets/tutorials/dashboard/dashboard21.png +[firstpage2]: ../../assets/tutorials/dashboard/dashboard22.png +[firstpage3]: ../../assets/tutorials/dashboard/dashboard23.png +[firstpage4]: ../../assets/tutorials/dashboard/dashboard24.png +[secondpage]: ../../assets/tutorials/dashboard/dashboard3.png diff --git a/vizro-core/docs/pages/tutorials/first-dashboard.md b/vizro-core/docs/pages/tutorials/first-dashboard.md index 0f69ee34d..8c435f2b8 100644 --- a/vizro-core/docs/pages/tutorials/first-dashboard.md +++ b/vizro-core/docs/pages/tutorials/first-dashboard.md @@ -29,22 +29,28 @@ Click on the **Run and edit this code in PyCafe** link below to live-edit the da ``` === "Result" - - [![FirstDash]][FirstDash] - - [FirstDash]: ../../assets/tutorials/dashboard/first-dashboard.png + [![FirstDash]][firstdash] + ## Can I break this code? + + When you click the link to "Edit live on PyCafe" the dashboard is running inside your browser. Any changes you make are local and you don't need to worry about breaking the code for others. Nobody else sees the changes you make unless you save a copy of the project as your own Vizro PyCafe project. + ## How can I make my own dashboards? + + You can use PyCafe to experiment with your own Vizro dashboards by dropping code onto a new project. Check out the [PyCafe documentation](https://py.cafe/docs/apps/vizro) for more information. If you need inspiration or a starting point, we make all our examples available for you to try out on PyCafe. Throughout our documentation, follow the "**Run and edit this code in PyCafe**" link below the code snippets to open them in PyCafe. ## Where next? + You are now ready to explore Vizro further, by working through the ["Explore Vizro" tutorial](explore-components.md) or by consulting the [how-to guides](../user-guides/dashboard.md). + +[firstdash]: ../../assets/tutorials/dashboard/first-dashboard.png diff --git a/vizro-core/docs/pages/user-guides/actions.md b/vizro-core/docs/pages/user-guides/actions.md index 3c811eb48..6a41ee25d 100644 --- a/vizro-core/docs/pages/user-guides/actions.md +++ b/vizro-core/docs/pages/user-guides/actions.md @@ -1,7 +1,6 @@ # How to use actions -This guide shows you how to use actions, an idea that is similar to [callbacks](https://dash.plotly.com/basic-callbacks) in `Dash`. -Many components of a dashboard (for example, [`Graph`][vizro.models.Graph] or [`Button`][vizro.models.Button]) have an optional `actions` argument, where you can enter the [`Action`][vizro.models.Action] model. +This guide shows you how to use actions, an idea that is similar to [callbacks](https://dash.plotly.com/basic-callbacks) in `Dash`. Many components of a dashboard (for example, [`Graph`][vizro.models.Graph] or [`Button`][vizro.models.Button]) have an optional `actions` argument, where you can enter the [`Action`][vizro.models.Action] model. By combining the [`Action`][vizro.models.Action] model with an action function, you can create complex dashboard interactions triggered by various events. @@ -12,22 +11,18 @@ There are already a few action functions you can reuse: ## Pre-defined actions -To attach an action to a component, you must enter the [`Action`][vizro.models.Action] model into the component's `action` argument. You can then -add a desired pre-defined action function into the `function` argument of the [`Action`][vizro.models.Action]. +To attach an action to a component, you must enter the [`Action`][vizro.models.Action] model into the component's `action` argument. You can then add a desired pre-defined action function into the `function` argument of the [`Action`][vizro.models.Action]. ??? note "Note on `Trigger`" - Currently each component has one pre-defined trigger property. A trigger property is an attribute of the component that triggers a configured action (for example, for the `Button` it is `n_click`). The below sections are guides on how to use pre-defined action functions. ### Export data -To enable downloading data, you can add the [`export_data`][vizro.actions.export_data] action function to the [`Button`][vizro.models.Button] component. -Hence, as a result, when a dashboard user now clicks the button, all data on the page will be downloaded. +To enable downloading data, you can add the [`export_data`][vizro.actions.export_data] action function to the [`Button`][vizro.models.Button] component. Hence, as a result, when a dashboard user now clicks the button, all data on the page will be downloaded. !!! example "`export_data`" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -61,60 +56,55 @@ Hence, as a result, when a dashboard user now clicks the button, all data on the Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - components: - - type: graph - figure: - _target_: scatter - data_frame: iris - color: sepal_width - x: petal_length - y: sepal_length - - type: graph - figure: - _target_: histogram - data_frame: iris - color: species - x: petal_length - - type: button - text: Export data - id: export_data_button - actions: - - function: - _target_: export_data + - type: graph + figure: + _target_: scatter + data_frame: iris + color: sepal_width + x: petal_length + y: sepal_length + - type: graph + figure: + _target_: histogram + data_frame: iris + color: species + x: petal_length + - type: button + text: Export data + id: export_data_button + actions: + - function: + _target_: export_data title: Exporting ``` - === "Result" - [![Graph]][Graph] - - [Graph]: ../../assets/user_guides/actions/actions_export.png + === "Result" + [![Graph]][graph] !!! note - - Note that exported data only reflects the original dataset and any native data modifications defined with [`vm.Filter`](filters.md), [`vm.Parameter`](data.md/#parametrize-data-loading) or [`filter_interaction`](actions.md/#filter-data-by-clicking-on-chart) action. - Filters from the chart itself, such as ag-grid filters, are not included, and neither are other chart modifications, nor any data transformations in custom charts. + Note that exported data only reflects the original dataset and any native data modifications defined with [`vm.Filter`](filters.md), [`vm.Parameter`](data.md/#parametrize-data-loading) or [`filter_interaction`](actions.md/#filter-data-by-clicking-on-chart) action. Filters from the chart itself, such as ag-grid filters, are not included, and neither are other chart modifications, nor any data transformations in custom charts. ### Filter data by clicking on chart -To enable filtering when clicking on data in a source chart, you can add the -[`filter_interaction`][vizro.actions.filter_interaction] action function to the [`Graph`][vizro.models.Graph], -[`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid] components. -The [`filter_interaction`][vizro.actions.filter_interaction] is currently configured -to be triggered on click only. +To enable filtering when clicking on data in a source chart, you can add the [`filter_interaction`][vizro.actions.filter_interaction] action function to the [`Graph`][vizro.models.Graph], [`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid] components. The [`filter_interaction`][vizro.actions.filter_interaction] is currently configured to be triggered on click only. To configure this chart interaction follow the steps below: -1. Add the action function to the source [`Graph`][vizro.models.Graph], [`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid] -component and a list of IDs of the target charts into `targets`. +1. Add the action function to the source [`Graph`][vizro.models.Graph], [`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid] component and a list of IDs of the target charts into `targets`. + ```py actions=[vm.Action(function=filter_interaction(targets=["scatter_relation_2007"]))] ``` -2. If the source chart is [`Graph`][vizro.models.Graph], enter the filter columns in the `custom_data` argument of the underlying source chart `function`. + +1. If the source chart is [`Graph`][vizro.models.Graph], enter the filter columns in the `custom_data` argument of the underlying source chart `function`. + ```py Graph(figure=px.scatter(..., custom_data=["continent"])) ``` @@ -128,7 +118,6 @@ Selecting a data point with a corresponding value of "Africa" in the continent c Here is an example of how to configure a chart interaction when the source is a [`Graph`][vizro.models.Graph] component. !!! example "Graph `filter_interaction`" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -171,50 +160,47 @@ Here is an example of how to configure a chart interaction when the source is a Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - components: - - type: graph - figure: - _target_: box - data_frame: gapminder - color: continent - x: continent - y: lifeExp - custom_data: - - continent - actions: - - function: - _target_: filter_interaction - targets: - - scatter_relation_2007 - - type: graph - id: scatter_relation_2007 - figure: - _target_: scatter - data_frame: gapminder - color: continent - x: gdpPercap - y: lifeExp - size: pop + - type: graph + figure: + _target_: box + data_frame: gapminder + color: continent + x: continent + y: lifeExp + custom_data: + - continent + actions: + - function: + _target_: filter_interaction + targets: + - scatter_relation_2007 + - type: graph + id: scatter_relation_2007 + figure: + _target_: scatter + data_frame: gapminder + color: continent + x: gdpPercap + y: lifeExp + size: pop controls: - column: continent type: filter title: Filter interaction ``` - === "Result" - [![Graph2]][Graph2] - - [Graph2]: ../../assets/user_guides/actions/actions_filter_interaction.png + === "Result" + [![Graph2]][graph2] !!! note "`filter_interaction` with custom charts" - - If `filter_interaction` is assigned to a [custom chart](custom-charts.md), ensure that `custom_data` is an argument of the custom chart function, and that this argument is then passed to the underlying plotly function. - When then adding the custom chart in `vm.Graph`, ensure that `custom_data` is passed. + If `filter_interaction` is assigned to a [custom chart](custom-charts.md), ensure that `custom_data` is an argument of the custom chart function, and that this argument is then passed to the underlying plotly function. When then adding the custom chart in `vm.Graph`, ensure that `custom_data` is passed. ```py @capture("graph") @@ -227,11 +213,9 @@ Here is an example of how to configure a chart interaction when the source is a ``` - Here is an example of how to configure a chart interaction when the source is an [`AgGrid`][vizro.models.AgGrid] component. !!! example "AgGrid `filter_interaction`" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -271,57 +255,53 @@ Here is an example of how to configure a chart interaction when the source is an Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - components: - - type: ag_grid - figure: - _target_: dash_ag_grid - data_frame: gapminder_2007 - actions: - - function: - _target_: filter_interaction - targets: - - scatter_relation_2007 - - type: graph - id: scatter_relation_2007 - figure: - _target_: scatter - data_frame: gapminder_2007 - color: continent - x: gdpPercap - y: lifeExp - size: pop + - type: ag_grid + figure: + _target_: dash_ag_grid + data_frame: gapminder_2007 + actions: + - function: + _target_: filter_interaction + targets: + - scatter_relation_2007 + - type: graph + id: scatter_relation_2007 + figure: + _target_: scatter + data_frame: gapminder_2007 + color: continent + x: gdpPercap + y: lifeExp + size: pop controls: - column: continent type: filter title: Filter interaction ``` - === "Result" - [![Table]][Table] - - [Table]: ../../assets/user_guides/actions/actions_table_filter_interaction.png + === "Result" + [![Table]][table] ### Customize pre-defined actions + Many pre-defined actions are customizable which helps to achieve a more specific goal. Refer to the [API reference][vizro.actions] for the options available. ## Custom actions -If you require an action that isn't available as a pre-defined option, you can create a custom action function. -Refer to our [user guide on custom actions](custom-actions.md) for more information. +If you require an action that isn't available as a pre-defined option, you can create a custom action function. Refer to our [user guide on custom actions](custom-actions.md) for more information. ## Chain actions -The `actions` parameter for the different screen components accepts a `list` of [`Action`][vizro.models.Action] models. -This means that it's possible to chain together a list of actions that are executed by triggering only one component. -The order of action execution is guaranteed, and the next action in the list will start executing only when the previous one is completed. +The `actions` parameter for the different screen components accepts a `list` of [`Action`][vizro.models.Action] models. This means that it's possible to chain together a list of actions that are executed by triggering only one component. The order of action execution is guaranteed, and the next action in the list will start executing only when the previous one is completed. !!! example "Actions chaining" - === "app.py" ```{.python pycafe-link extra-requirements="openpyxl"} import vizro.models as vm @@ -368,44 +348,49 @@ The order of action execution is guaranteed, and the next action in the list wil Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml pages: - components: - - type: graph - id: scatter - figure: - _target_: scatter - data_frame: iris - color: sepal_width - x: petal_length - y: sepal_length - - type: graph - id: hist - figure: - _target_: histogram - data_frame: iris - color: species - x: petal_length - - type: button - text: Export data - id: export_data_button - actions: - - function: - _target_: export_data - targets: - - scatter - - function: - _target_: export_data - targets: - - hist - file_format: xlsx + - type: graph + id: scatter + figure: + _target_: scatter + data_frame: iris + color: sepal_width + x: petal_length + y: sepal_length + - type: graph + id: hist + figure: + _target_: histogram + data_frame: iris + color: species + x: petal_length + - type: button + text: Export data + id: export_data_button + actions: + - function: + _target_: export_data + targets: + - scatter + - function: + _target_: export_data + targets: + - hist + file_format: xlsx controls: - type: filter column: species title: Exporting ``` + === "Result" - [![Graph3]][Graph3] + [![Graph3]][graph3] - [Graph3]: ../../assets/user_guides/actions/actions_chaining.png +[graph]: ../../assets/user_guides/actions/actions_export.png +[graph2]: ../../assets/user_guides/actions/actions_filter_interaction.png +[graph3]: ../../assets/user_guides/actions/actions_chaining.png +[table]: ../../assets/user_guides/actions/actions_table_filter_interaction.png diff --git a/vizro-core/docs/pages/user-guides/assets.md b/vizro-core/docs/pages/user-guides/assets.md index ae87f5527..e4f8538ff 100644 --- a/vizro-core/docs/pages/user-guides/assets.md +++ b/vizro-core/docs/pages/user-guides/assets.md @@ -1,11 +1,8 @@ # How to add static assets -This guide shows you how to add static assets to your dashboard. Static assets are images that you would like to show in your dashboard, or custom CSS and JS files -with which you would like to enhance/change the appearance of your dashboard. + This guide shows you how to add static assets to your dashboard. Static assets are images that you would like to show in your dashboard, or custom CSS and JS files with which you would like to enhance/change the appearance of your dashboard. -To add images, custom CSS or JS files, create a folder named `assets` in the root of your app directory and insert your files. -Assets included in that folder are automatically served after serving Vizro's static files via the `external_stylesheets` and `external_scripts` arguments of [Dash](https://dash.plotly.com/external-resources#adding-external-css/javascript). -The user's `assets` folder thus always takes precedence. +To add images, custom CSS or JS files, create a folder named `assets` in the root of your app directory and insert your files. Assets included in that folder are automatically served after serving Vizro's static files via the `external_stylesheets` and `external_scripts` arguments of [Dash](https://dash.plotly.com/external-resources#adding-external-css/javascript). The user's `assets` folder thus always takes precedence. ```text title="Example folder structure" ├── app.py @@ -21,15 +18,11 @@ The user's `assets` folder thus always takes precedence. ``` !!! warning "Dash Bootstrap Themes" - - Note that Vizro is currently not compatible with [Dash Bootstrap Themes](https://dash-bootstrap-components.opensource.faculty.ai/docs/themes/). - Adding a Bootstrap stylesheet will have no visual effect on the [components](https://vizro.readthedocs.io/en/stable/pages/user_guides/components/) included in Vizro. - + Note that Vizro is currently not compatible with [Dash Bootstrap Themes](https://dash-bootstrap-components.opensource.faculty.ai/docs/themes/). Adding a Bootstrap stylesheet will have no visual effect on the [components](https://vizro.readthedocs.io/en/stable/pages/user_guides/components/) included in Vizro. ## Change the favicon -To change the default favicon (website icon appearing in the browser tab), add a file named `favicon.ico` to your `assets` folder. -For more information, see the [Dash documentation](https://dash.plotly.com/external-resources#changing-the-favicon). +To change the default favicon (website icon appearing in the browser tab), add a file named `favicon.ico` to your `assets` folder. For more information, see the [Dash documentation](https://dash.plotly.com/external-resources#changing-the-favicon). ## Add a logo image @@ -41,52 +34,36 @@ If an image named `logo.` is present in the assets folder, Vizro auto ### Theme-specific logos -You can also supply two images named `logo_dark.` and `logo_light.` to switch logos -based on the theme (dark or light). +You can also supply two images named `logo_dark.` and `logo_light.` to switch logos based on the theme (dark or light). Note that both `logo_light.` and `logo_dark.` must be supplied together, unless a single `logo.` is supplied for both light and dark themes. That is, the valid configurations are as follows: -* Single logo: Supply only `logo.`, which is used for dark and light themes. **Do not include light and dark theme logos**. -* Theme logos: Supply both `logo_light.` and `logo_dark.` for light/dark themes. **Do not include `logo.`**. -* No logo: No logo images supplied. +- Single logo: Supply only `logo.`, which is used for dark and light themes. **Do not include light and dark theme logos**. +- Theme logos: Supply both `logo_light.` and `logo_dark.` for light/dark themes. **Do not include `logo.`**. +- No logo: No logo images supplied. -![Logo dark](../../assets/user_guides/assets/logo-dark.png) -![Logo light](../../assets/user_guides/assets/logo-light.png) +![Logo dark](../../assets/user_guides/assets/logo-dark.png) ![Logo light](../../assets/user_guides/assets/logo-light.png) ## Change the `assets` folder path -If you do not want to place your `assets` folder in the root directory of your app, you can -specify an alternative path through the `assets_folder` argument of the [`Vizro`][vizro.Vizro] class. - -```python -from vizro import Vizro -import vizro.models as vm - -page = -dashboard = vm.Dashboard(pages=[page]) -app = Vizro(assets_folder="path/to/assets/folder").build(dashboard).run() +If you do not want to place your `assets` folder in the root directory of your app, you can specify an alternative path through the `assets_folder` argument of the [`Vizro`][vizro.Vizro] class. +```python +Vizro(assets_folder="path/to/assets/folder").build(dashboard).run() ``` -Note that in the example above, you still need to configure your [`Page`][vizro.models.Page]. -See more information in the [Pages User Guide](pages.md). - - ## Include a meta tags image -Vizro automatically adds [meta tags](https://metatags.io/) to display a preview card when your app is shared on social media and chat -clients. To include an image in the preview, place an image file in the assets folder named `app.` or -`logo.`. Vizro searches the assets folder and uses the first one it finds. +Vizro automatically adds [meta tags](https://metatags.io/) to display a preview card when your app is shared on social media and chat clients. To include an image in the preview, place an image file in the assets folder named `app.` or `logo.`. Vizro searches the assets folder and uses the first one it finds. Image types of `apng`, `avif`, `gif`, `jpeg`, `jpg`, `png`, `svg`, and `webp` are supported. - ## Order of serving CSS files CSS properties will be applied with the last served file taking precedence. The order of serving is: 1. Dash built-in stylesheets -2. Vizro built-in stylesheets -3. User assets folder stylesheets +1. Vizro built-in stylesheets +1. User assets folder stylesheets Within each of these categories, individual files are served in alphanumeric order. diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index c4f0218d2..541449527 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -4,12 +4,10 @@ This guide shows you how to use cards and buttons to visualize and interact with ## Cards -The [`Card`][vizro.models.Card] is a flexible and extensible component that enables customization via markdown text. -Refer to any online guide for [basic markdown usage](https://markdown-guide.readthedocs.io/en/latest/). +The [`Card`][vizro.models.Card] is a flexible and extensible component that enables customization via markdown text. Refer to any online guide for [basic markdown usage](https://markdown-guide.readthedocs.io/en/latest/). You can add a [`Card`][vizro.models.Card] to your dashboard by inserting the [`Card`][vizro.models.Card] into the `components` argument of the [`Page`][vizro.models.Page]. - !!! example "Card" === "app.py" ```{.python pycafe-link} @@ -32,28 +30,26 @@ You can add a [`Card`][vizro.models.Card] to your dashboard by inserting the [`C Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - Commodi repudiandae consequuntur voluptatum. - title: Card Title - type: card - title: Card + - components: + - text: | + Commodi repudiandae consequuntur voluptatum. + title: Card Title + type: card + title: Card ``` - === "Result" - [![Card]][Card] - [Card]: ../../assets/user_guides/components/card.png + === "Result" + [![Card]][card] ### Customize card text -The [`Card`][vizro.models.Card] uses the `dcc.Markdown` component from Dash as its underlying text component. -For more details on customizing the markdown text, refer to the [`dcc.Markdown` component documentation](https://dash.plotly.com/dash-core-components/markdown). -Based on examples from Dash, the [`Card`][vizro.models.Card] model supports the following: +The [`Card`][vizro.models.Card] uses the `dcc.Markdown` component from Dash as its underlying text component. For more details on customizing the markdown text, refer to the [`dcc.Markdown` component documentation](https://dash.plotly.com/dash-core-components/markdown). Based on examples from Dash, the [`Card`][vizro.models.Card] model supports the following: - Headers - Emphasis @@ -130,58 +126,58 @@ Based on examples from Dash, the [`Card`][vizro.models.Card] model supports the Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - # Header level 1

- - ## Header level 2

- - ### Header level 3

- - #### Header level 4

- type: card - - text: | - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - - Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. - title: Paragraphs - type: card - - text: | - > - > A block quote is a long quotation, indented to create a separate block of text. - > - title: Block Quotes - type: card - - text: | - * Item A - * Sub Item 1 - * Sub Item 2 - * Item B - title: Lists - type: card - - text: | - This word will be *italic* - - This word will be **bold** - - This word will be _**bold and italic**_ - title: Emphasis - type: card - title: Customizing Text + - components: + - text: | + # Header level 1

+ + ## Header level 2

+ + ### Header level 3

+ + #### Header level 4

+ type: card + - text: | + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + + Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. + title: Paragraphs + type: card + - text: | + > + > A block quote is a long quotation, indented to create a separate block of text. + > + title: Block Quotes + type: card + - text: | + * Item A + * Sub Item 1 + * Sub Item 2 + * Item B + title: Lists + type: card + - text: | + This word will be *italic* + + This word will be **bold** + + This word will be _**bold and italic**_ + title: Emphasis + type: card + title: Customizing Text ``` - === "Result" - [![CardText]][CardText] - [CardText]: ../../assets/user_guides/components/card_text.png + === "Result" + [![CardText]][cardtext] ### Place an image on a card @@ -189,11 +185,10 @@ Images can be added to the `text` parameter by using the standard markdown synta `![Image ALT text](Image URL)` -An image ALT text offers a description to your image and serves as a text placeholder or to improve the -accessibility of your app. Providing an image ALT text is optional. +An image ALT text offers a description to your image and serves as a text placeholder or to improve the accessibility of your app. Providing an image ALT text is optional. 1. To use a relative Image URL, place an image of your choice into your `assets` folder first -2. Use markdown to render your image by using one of the following syntax: +1. Use markdown to render your image by using one of the following syntax: - Relative Image URL: `![Image ALT text](/path/to/image.png)` - Absolute Image URL: `![Image ALT text](https://XXXXXX)` @@ -228,55 +223,54 @@ accessibility of your app. Providing an image ALT text is optional. PyCafe logoRun and edit this code in PyCafe +```` +=== "app.yaml" + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See from_yaml example + pages: + - components: + - text: | + ![continent](assets/images/continents/africa.svg) - === "app.yaml" - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See from_yaml example - pages: - - components: - - text: | - ![continent](assets/images/continents/africa.svg) - - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - title: My card with image! - type: card - title: Placing Images - ``` - === "Result" - [![CardImageDefault]][CardImageDefault] + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + title: My card with image! + type: card + title: Placing Images + ``` +=== "Result" + [![CardImageDefault]][CardImageDefault] - [CardImageDefault]: ../../assets/user_guides/components/card_image_default.png +[CardImageDefault]: ../../assets/user_guides/components/card_image_default.png +```` !!! note - - Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed - to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. + Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. You might notice that the image is quite large. You'll find out how to style images in terms of their position and size in the next section. - ### Style a card image To change the size or position of the image, add a URL hash to your image like this: `![Image ALT text](Image URL#my-image)` -Note the added URL hash `#my-image`. Now create a CSS file placed in your `assets` folder -and give an attribute selector to select images with that matching URL hash. +Note the added URL hash `#my-image`. Now create a CSS file placed in your `assets` folder and give an attribute selector to select images with that matching URL hash. !!! example "Card with styled image" === "images.css" + ```css img[src*="#my-image"] { - width: 120px; - height: 120px; + width: 120px; + height: 120px; } ``` + === "app.py" ```py import vizro.models as vm @@ -313,23 +307,22 @@ and give an attribute selector to select images with that matching URL hash. # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![](assets/images/continents/europe.svg#my-image) + - components: + - text: | + ![](assets/images/continents/europe.svg#my-image) - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - title: My card with image! - type: card - title: Styling Images + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + title: My card with image! + type: card + title: Styling Images ``` - === "Result" - [![CardImageStyled]][CardImageStyled] - [CardImageStyled]: ../../assets/user_guides/components/card_image_styled.png + === "Result" + [![CardImageStyled]][cardimagestyled] Use the following pre-defined URL hashes in your image path to apply Vizro's default styling. @@ -341,12 +334,14 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def !!! example "Card with floating image" === "images.css" + ```css img[src*="#my-image"] { - width: 120px; - height: 120px; + width: 120px; + height: 120px; } ``` + === "app.py" ```py import vizro.models as vm @@ -389,29 +384,28 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![](assets/images/continents/europe.svg#my-image#floating-right) + - components: + - text: | + ![](assets/images/continents/europe.svg#my-image#floating-right) - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. + Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. - title: My card with floating image! - type: card - title: Floating Images + Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. + title: My card with floating image! + type: card + title: Floating Images ``` - === "Result" - [![CardImageFloating]][CardImageFloating] - [CardImageFloating]: ../../assets/user_guides/components/card_image_floating.png + === "Result" + [![CardImageFloating]][cardimagefloating] #### Card with icon @@ -442,38 +436,34 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![](assets/images/icons/hypotheses.svg#icon-top) + - components: + - text: | + ![](assets/images/icons/hypotheses.svg#icon-top) - ### Card Title + ### Card Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut fringilla dictum lacus eget fringilla. - Maecenas in various nibh, quis venenatis nulla. Integer et libero ultrices, scelerisque velit sed. - type: card - title: Card with icon + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut fringilla dictum lacus eget fringilla. + Maecenas in various nibh, quis venenatis nulla. Integer et libero ultrices, scelerisque velit sed. + type: card + title: Card with icon ``` - === "Result" - [![CardIcon]][CardIcon] - - [CardIcon]: ../../assets/user_guides/components/card_icon.png + === "Result" + [![CardIcon]][cardicon] ### Make an icon responsive to theme switch -To make an icon responsive to the theme switch, override the value of the [`filter` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/filter). -The `filter` CSS property lets you add visual effects to elements using different functions. In our example, we're using the `--inverse-color` CSS variable from the Vizro theme. -It uses the CSS `invert()` function to flip the color of the icon when you switch themes. Note that this only works if your initial icon has a white fill color. If your icon is not white, you can change its color by adding `fill="white"` to the SVG code. -Assign the predefined CSS variable `--inverse-color` to the `filter` property of your selected icon. +To make an icon responsive to the theme switch, override the value of the [`filter` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/filter). The `filter` CSS property lets you add visual effects to elements using different functions. In our example, we're using the `--inverse-color` CSS variable from the Vizro theme. It uses the CSS `invert()` function to flip the color of the icon when you switch themes. Note that this only works if your initial icon has a white fill color. If your icon is not white, you can change its color by adding `fill="white"` to the SVG code. Assign the predefined CSS variable `--inverse-color` to the `filter` property of your selected icon. ```css img[src*="#my-image"] { - filter: var(--inverse-color); + filter: var(--inverse-color); } ``` @@ -489,8 +479,8 @@ A navigation card enables you to navigate to a different page via a click on the To create a navigation card: 1. Insert the [`Card`][vizro.models.Card] into the `components` argument of the [`Page`][vizro.models.Page]. -2. Pass your markdown text to the `Card.text`. -3. Pass a relative or absolute URL to the `Card.href`. +1. Pass your markdown text to the `Card.text`. +1. Pass a relative or absolute URL to the `Card.href`. !!! example "Navigation Card" === "app.py" @@ -534,76 +524,66 @@ To create a navigation card: Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ### Filters and parameters - - Leads to the first page on click - href: /filters-and-parameters - type: card - - text: | - ### Google - External Link - - Leads to an external link on click. - href: https://google.com - type: card - title: Homepage - - components: - - figure: - _target_: scatter - color: sepal_width - data_frame: iris - x: sepal_length - y: petal_width - id: scatter - type: graph - title: Filters and parameters + - components: + - text: | + ### Filters and parameters + + Leads to the first page on click + href: /filters-and-parameters + type: card + - text: | + ### Google - External Link + + Leads to an external link on click. + href: https://google.com + type: card + title: Homepage + - components: + - figure: + _target_: scatter + color: sepal_width + data_frame: iris + x: sepal_length + y: petal_width + id: scatter + type: graph + title: Filters and parameters ``` - === "Result" - [![NavCard]][NavCard] - [NavCard]: ../../assets/user_guides/components/nav_card.png + === "Result" + [![NavCard]][navcard] If you now click on the card area, you should automatically be redirected to the relevant `href`. !!! note - When using the [`Card`][vizro.models.Card], keep the following in mind: - If the href given is a relative URL, it should match the `path` of the [`Page`][vizro.models.Page] that the [`Card`][vizro.models.Card] should navigate to. - If the href given is an absolute link, it should start with `https://` or an equivalent protocol. - ### Create a KPI card -To create a KPI card, you can use the existing KPI card functions from [`vizro.figures`](../API-reference/figure-callables.md). -Unlike the static text card `vm.Card`, a KPI card must be created using a figure function, -which enables the text content of the KPI to change based on input from controls or actions. + +To create a KPI card, you can use the existing KPI card functions from [`vizro.figures`](../API-reference/figure-callables.md). Unlike the static text card `vm.Card`, a KPI card must be created using a figure function, which enables the text content of the KPI to change based on input from controls or actions. For detailed examples on how to create a KPI card, refer to the [figure user guide on KPI cards](figure.md#key-performance-indicator-kpi-cards). ## Buttons -To enhance dashboard interactions, you can use the [`Button`][vizro.models.Button] component to trigger any pre-defined -action functions such as exporting chart data. To use the currently available options for the [`Actions`][vizro.models.Action] -component, check out the [API reference][vizro.actions]. +To enhance dashboard interactions, you can use the [`Button`][vizro.models.Button] component to trigger any pre-defined action functions such as exporting chart data. To use the currently available options for the [`Actions`][vizro.models.Action] component, check out the [API reference][vizro.actions]. -To add a [`Button`][vizro.models.Button], insert it into the `components` argument of the -[`Page`][vizro.models.Page]. +To add a [`Button`][vizro.models.Button], insert it into the `components` argument of the [`Page`][vizro.models.Page]. -You can configure the `text` argument to alter the display text of the [`Button`][vizro.models.Button] and the -`actions` argument to define which action function should be executed on button click. - -In the below example we show how to configure a button to export the filtered data of a target chart using -[export_data][vizro.actions.export_data], a pre-defined action function. +You can configure the `text` argument to alter the display text of the [`Button`][vizro.models.Button] and the `actions` argument to define which action function should be executed on button click. +In the below example we show how to configure a button to export the filtered data of a target chart using [export_data][vizro.actions.export_data], a pre-defined action function. !!! example "Button" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -639,29 +619,30 @@ In the below example we show how to configure a button to export the filtered da Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - components: - - figure: - _target_: scatter - x: sepal_width - y: sepal_length - color: species - size: petal_length - data_frame: iris - id: scatter_chart - type: graph - - type: button - text: Export data - id: export_data - actions: - - function: - _target_: export_data - targets: - - scatter_chart + - figure: + _target_: scatter + x: sepal_width + y: sepal_length + color: species + size: petal_length + data_frame: iris + id: scatter_chart + type: graph + - type: button + text: Export data + id: export_data + actions: + - function: + _target_: export_data + targets: + - scatter_chart controls: - column: species selector: @@ -677,13 +658,11 @@ In the below example we show how to configure a button to export the filtered da - [1] title: My first page ``` - === "Result" - [![Button]][Button] - [Button]: ../../assets/user_guides/components/button.png + === "Result" + [![Button]][button] -The [`Button`][vizro.models.Button] component is currently reserved to be used inside the main panel (right-side) of the dashboard. -However, there might be use cases where one would like to place the `Button` inside the control panel (left-side) with the other controls. +The [`Button`][vizro.models.Button] component is currently reserved to be used inside the main panel (right-side) of the dashboard. However, there might be use cases where one would like to place the `Button` inside the control panel (left-side) with the other controls. In this case, follow the user-guide outlined for [creating custom components](custom-components.md) and manually add the `Button` as a valid type to the `controls` argument by running the following lines before your dashboard configurations: @@ -696,3 +675,11 @@ vm.Page.add_type("controls", vm.Button) # Add dashboard configurations below ... ``` + +[button]: ../../assets/user_guides/components/button.png +[card]: ../../assets/user_guides/components/card.png +[cardicon]: ../../assets/user_guides/components/card_icon.png +[cardimagefloating]: ../../assets/user_guides/components/card_image_floating.png +[cardimagestyled]: ../../assets/user_guides/components/card_image_styled.png +[cardtext]: ../../assets/user_guides/components/card_text.png +[navcard]: ../../assets/user_guides/components/nav_card.png diff --git a/vizro-core/docs/pages/user-guides/components.md b/vizro-core/docs/pages/user-guides/components.md index 106bf6a0b..45ea5a123 100755 --- a/vizro-core/docs/pages/user-guides/components.md +++ b/vizro-core/docs/pages/user-guides/components.md @@ -1,8 +1,6 @@ # Components -The [`Page`][vizro.models.Page] model accepts the `components` argument, where you can enter any of the components -listed below to fill your dashboard with visuals. - +The [`Page`][vizro.models.Page] model accepts the `components` argument, where you can enter any of the components listed below to fill your dashboard with visuals.
@@ -38,7 +36,6 @@ listed below to fill your dashboard with visuals. [:octicons-arrow-right-24: View user guide](card-button.md) - - :octicons-table-16:{ .lg .middle } __Containers__ --- diff --git a/vizro-core/docs/pages/user-guides/container.md b/vizro-core/docs/pages/user-guides/container.md index c7e327c5f..2f379709e 100755 --- a/vizro-core/docs/pages/user-guides/container.md +++ b/vizro-core/docs/pages/user-guides/container.md @@ -2,30 +2,22 @@ This guide shows you how to use containers to group your components into sections and subsections within the page. -A [`Container`][vizro.models.Container] complements the idea of a [`Page`][vizro.models.Page], and the two models have almost identical arguments. - [`Page.layout`](layouts.md) offers a way to structure the overall layout of the page, and a `Container` enables more granular control within a specific section of that page. +A [`Container`][vizro.models.Container] complements the idea of a [`Page`][vizro.models.Page], and the two models have almost identical arguments. [`Page.layout`](layouts.md) offers a way to structure the overall layout of the page, and a `Container` enables more granular control within a specific section of that page. -While there is currently no clear difference in rendering, extra functionality will be added to the `Container` soon (including controls specific to that container), -enhancing the ability to manage related components. +While there is currently no clear difference in rendering, extra functionality will be added to the `Container` soon (including controls specific to that container), enhancing the ability to manage related components. !!! note "Displaying multiple containers inside Tabs" - An alternative way to display multiple containers on one page is to place them inside [Tabs](tabs.md). - [`Tabs`][vizro.models.Tabs] organize and separate groups of related content in a dashboard, letting users switch between different sections or views. - They are a way of putting multiple containers into the same screen space, and letting the user switch between them. + [`Tabs`][vizro.models.Tabs] organize and separate groups of related content in a dashboard, letting users switch between different sections or views. They are a way of putting multiple containers into the same screen space, and letting the user switch between them. ![tabs](../../assets/user_guides/components/tabs-info.png){ width="500" } - - ## When to use containers -In general, any arbitrarily granular layout can already be achieved by [using `Page.layout`](layouts.md) alone and is our -recommended approach if you want to arrange components on a page with consistent row and/or column spacing. -`Page.layout` has a `grid` argument that sets the overall layout of the page. -`Container.layout` also has a `grid` argument. This enables you to insert a further `grid` into a component's space on the page, -enabling more granular control by breaking the overall page grid into subgrids. +In general, any arbitrarily granular layout can already be achieved by [using `Page.layout`](layouts.md) alone and is our recommended approach if you want to arrange components on a page with consistent row and/or column spacing. + +`Page.layout` has a `grid` argument that sets the overall layout of the page. `Container.layout` also has a `grid` argument. This enables you to insert a further `grid` into a component's space on the page, enabling more granular control by breaking the overall page grid into subgrids. Here are a few cases where you might want to use a `Container` instead of `Page.layout`: @@ -34,14 +26,14 @@ Here are a few cases where you might want to use a `Container` instead of `Page. - If you want different row and column spacing between subgrids - If you want to apply controls to selected subgrids (will be supported soon) - ## Basic containers + To add a [`Container`][vizro.models.Container] to your page, do the following: 1. Insert the `Container` into the `components` argument of the [`Page`][vizro.models.Page] -2. Set a `title` for your `Container` -3. Configure your `components`, [read the overview page for various options](components.md) -4. (optional) Configure your `layout`, see [the guide on `Layout`](layouts.md) +1. Set a `title` for your `Container` +1. Configure your `components`, [read the overview page for various options](components.md) +1. (optional) Configure your `layout`, see [the guide on `Layout`](layouts.md) !!! example "Container" === "app.py" @@ -105,7 +97,7 @@ To add a [`Container`][vizro.models.Container] to your page, do the following: ``` 1. Note that the `Page.layout` argument is not specified here and will therefore defaults to `[[0], [1]]`, meaning the containers will be **vertically stacked** down the page in one column. - 2. **Horizontally stack** the components side-by-side inside this `Container` in one row. + 1. **Horizontally stack** the components side-by-side inside this `Container` in one row. === "app.yaml" ```yaml @@ -149,27 +141,20 @@ To add a [`Container`][vizro.models.Container] to your page, do the following: title: Container II title: Containers ``` - === "Result" - [![Container]][Container] - [Container]: ../../assets/user_guides/components/containers.png + === "Result" + [![Container]][container] Note that an almost identical layout can also be achieved using solely the [`Page.layout`](layouts.md) by configuring the `Page.layout` as `vm.Layout(grid = [[0, 1], [2, 2]])`. ## Nested containers -Containers can be nested, providing a hierarchical structure for organizing components. -This nesting capability enables users to create more complex layouts and manage related components at any level of granularity. + +Containers can be nested, providing a hierarchical structure for organizing components. This nesting capability enables users to create more complex layouts and manage related components at any level of granularity. To create nested containers, add a `Container` to the `components` argument of another `Container`. ```python title="Example" -vm.Container( - title="Parent Container", - components=[ - vm.Container( - title="Child Container", - components=[vm.Button()] - ) - ] -) +vm.Container(title="Parent Container", components=[vm.Container(title="Child Container", components=[vm.Button()])]) ``` + +[container]: ../../assets/user_guides/components/containers.png diff --git a/vizro-core/docs/pages/user-guides/custom-actions.md b/vizro-core/docs/pages/user-guides/custom-actions.md index e5fa3afd8..379a85b23 100644 --- a/vizro-core/docs/pages/user-guides/custom-actions.md +++ b/vizro-core/docs/pages/user-guides/custom-actions.md @@ -1,17 +1,16 @@ # How to create custom actions -This guide demonstrates the usage of custom actions, an idea that shares similarities with, but is not identical to [callbacks](https://dash.plotly.com/basic-callbacks) in `Dash`. -If you want to use the [`Action`][vizro.models.Action] model to perform functions that are not available in the [pre-defined action functions][vizro.actions], you can create your own custom action. -Like other [actions](actions.md), custom actions could also be added as an element inside the [actions chain](actions.md#chain-actions), and it can be triggered with one of many dashboard components. +This guide demonstrates the usage of custom actions, an idea that shares similarities with, but is not identical to [callbacks](https://dash.plotly.com/basic-callbacks) in `Dash`. If you want to use the [`Action`][vizro.models.Action] model to perform functions that are not available in the [pre-defined action functions][vizro.actions], you can create your own custom action. Like other [actions](actions.md), custom actions could also be added as an element inside the [actions chain](actions.md#chain-actions), and it can be triggered with one of many dashboard components. + ## Simple custom action Custom actions enable you to implement your own action function. Simply do the following: 1. define a function -2. decorate it with the `@capture("action")` decorator -3. add it as a `function` argument inside the [`Action`][vizro.models.Action] model +1. decorate it with the `@capture("action")` decorator +1. add it as a `function` argument inside the [`Action`][vizro.models.Action] model The following example shows how to create a custom action that postpones execution of the next action in the chain for `t` seconds. @@ -58,27 +57,24 @@ The following example shows how to create a custom action that postpones executi Vizro().build(dashboard).run() ``` + === "app.yaml" - ```yaml - # Custom actions are currently only possible via Python configuration - ``` - + Custom actions are currently only possible via Python configuration. + ## Interact with inputs and outputs + When a custom action needs to interact with the dashboard, it is possible to define `inputs` and `outputs` for the custom action. -- `inputs` represents dashboard component properties whose values are passed to the custom action function as arguments. -It is a list of strings in the format `"."` (for example, `"my_selector.value`"). -- `outputs` represents dashboard component properties corresponding to the custom action function return value(s). -Similar to `inputs`, it is a list of strings in the format `"."` (for example, `"my_card.children"`). +- `inputs` represents dashboard component properties whose values are passed to the custom action function as arguments. It is a list of strings in the format `"."` (for example, `"my_selector.value`"). +- `outputs` represents dashboard component properties corresponding to the custom action function return value(s). Similar to `inputs`, it is a list of strings in the format `"."` (for example, `"my_card.children"`). ### Example of `value` as input -The following example shows a custom action that takes the `value` of the `vm.RadioItem` and returns it inside a -[`Card`][vizro.models.Card] component. -!!! example "Display `value` in Card" +The following example shows a custom action that takes the `value` of the `vm.RadioItem` and returns it inside a [`Card`][vizro.models.Card] component. +!!! example "Display `value` in Card" === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -113,23 +109,18 @@ The following example shows a custom action that takes the `value` of the `vm.Ra dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` - === "app.yaml" - ```yaml - # Custom actions are currently only possible via Python configuration - ``` - === "Result" - [![ValueAction]][ValueAction] - [ValueAction]: ../../assets/user_guides/custom_actions/value_as_input.png + === "app.yaml" + Custom actions are currently only possible via Python configuration. + === "Result" + [![ValueAction]][valueaction] ### Example of `clickData` as input -The following example shows how to create a custom action that shows the `clickData` of a chart in a -[`Card`][vizro.models.Card] component. For further information on the structure and content of the `clickData` -property, refer to the Dash documentation on [interactive visualizations](https://dash.plotly.com/interactive-graphing). -!!! example "Display `clickData` in Card" +The following example shows how to create a custom action that shows the `clickData` of a chart in a [`Card`][vizro.models.Card] component. For further information on the structure and content of the `clickData` property, refer to the Dash documentation on [interactive visualizations](https://dash.plotly.com/interactive-graphing). +!!! example "Display `clickData` in Card" === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -173,21 +164,18 @@ property, refer to the Dash documentation on [interactive visualizations](https: ``` 1. Just as for any Python function, the names of the arguments `show_species` and `points_data` are arbitrary and do not need to match on to the names of `inputs` in any particular way. - 2. We _bind_ (set) the argument `show_species` to the value `True` in the initial specification of the `function` field. These are static values that are fixed when the dashboard is _built_. - 3. The content of `inputs` will "fill in the gaps" by setting values for the remaining unbound arguments in `my_custom_action`. Here there is one such argument, named `points_data`. Values for these are bound _dynamically at runtime_ to reflect the live state of your dashboard. + 1. We _bind_ (set) the argument `show_species` to the value `True` in the initial specification of the `function` field. These are static values that are fixed when the dashboard is _built_. + 1. The content of `inputs` will "fill in the gaps" by setting values for the remaining unbound arguments in `my_custom_action`. Here there is one such argument, named `points_data`. Values for these are bound _dynamically at runtime_ to reflect the live state of your dashboard. + === "app.yaml" - ```yaml - # Custom actions are currently only possible via Python configuration - ``` - === "Result" - [![CustomAction]][CustomAction] + Custom actions are currently only possible via Python configuration. - [CustomAction]: ../../assets/user_guides/custom_actions/clickdata_as_input.png + === "Result" + [![CustomAction]][customaction] ## Multiple return values -The return value of the custom action function is propagated to the dashboard components that are defined in the `outputs` argument of the [`Action`][vizro.models.Action] model. -If there is a single `output` defined then the function return value is directly assigned to the component property. -If there are multiple `outputs` defined then the return value is iterated through and each part is assigned to each component property given in `outputs` in turn. This behavior is identical to Python's flexibility in managing multiple return values. + +The return value of the custom action function is propagated to the dashboard components that are defined in the `outputs` argument of the [`Action`][vizro.models.Action] model. If there is a single `output` defined then the function return value is directly assigned to the component property. If there are multiple `outputs` defined then the return value is iterated through and each part is assigned to each component property given in `outputs` in turn. This behavior is identical to Python's flexibility in managing multiple return values. !!! example "Multiple return values" === "app.py" @@ -246,17 +234,17 @@ If there are multiple `outputs` defined then the return value is iterated throug ``` 1. `my_custom_action` returns two values (which will be in Python tuple). - 2. These values are assigned to the `outputs` in the same order. - === "app.yaml" - ```yaml - # Custom actions are currently only possible via Python configuration - ``` - === "Result" - [![CustomAction2]][CustomAction2] + 1. These values are assigned to the `outputs` in the same order. - [CustomAction2]: ../../assets/user_guides/custom_actions/custom_action_multiple_return_values.png + === "app.yaml" + Custom actions are currently only possible via Python configuration. + === "Result" + [![CustomAction2]][customaction2] !!! warning - Note that users of this package are responsible for the content of any custom action function that they write - especially with regard to leaking any sensitive information or exposing to any security threat during implementation. You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). + +[customaction]: ../../assets/user_guides/custom_actions/clickdata_as_input.png +[customaction2]: ../../assets/user_guides/custom_actions/custom_action_multiple_return_values.png +[valueaction]: ../../assets/user_guides/custom_actions/value_as_input.png diff --git a/vizro-core/docs/pages/user-guides/custom-charts.md b/vizro-core/docs/pages/user-guides/custom-charts.md index cb26614c8..2bf1af9b5 100644 --- a/vizro-core/docs/pages/user-guides/custom-charts.md +++ b/vizro-core/docs/pages/user-guides/custom-charts.md @@ -1,9 +1,9 @@ # How to create custom charts -This guide shows you how to create custom charts and how to add them to your dashboard. -The [`Graph`][vizro.models.Graph] model accepts the `figure` argument, where you can enter _any_ [`plotly.express`](https://plotly.com/python/plotly-express/) chart as explained in the [user guide on graphs](graph.md). +This guide shows you how to create custom charts and how to add them to your dashboard. The [`Graph`][vizro.models.Graph] model accepts the `figure` argument, where you can enter _any_ [`plotly.express`](https://plotly.com/python/plotly-express/) chart as explained in the [user guide on graphs](graph.md). ## When to use a custom chart + In general, you should use the custom chart decorator `@capture("graph")` if your plotly chart needs any post-update calls or customization. For example: - You want to use any of the post figure update calls by `plotly` such as `update_layout`, `update_xaxes`, `update_traces` (for more details, see the docs on [plotly's update calls](https://plotly.com/python/creating-and-updating-figures/#other-update-methods)) @@ -12,11 +12,10 @@ In general, you should use the custom chart decorator `@capture("graph")` if you ## Steps to create a custom chart 1. Define a function that returns a `go.Figure()`. -2. Decorate it with `@capture("graph")`. -3. The function must accept a `data_frame` argument (of type `pandas.DataFrame`). -4. The visualization should be derived from and require only one `pandas.DataFrame`. Dataframes from other arguments -will not react to dashboard controls such as [`Filter`](filters.md). -5. Pass your function to the `figure` argument of the [`Graph`][vizro.models.Graph] model. +1. Decorate it with `@capture("graph")`. +1. The function must accept a `data_frame` argument (of type `pandas.DataFrame`). +1. The visualization should be derived from and require only one `pandas.DataFrame`. Dataframes from other arguments will not react to dashboard controls such as [`Filter`](filters.md). +1. Pass your function to the `figure` argument of the [`Graph`][vizro.models.Graph] model. The minimal example below can be used as a base to build more sophisticated charts. @@ -39,12 +38,10 @@ To alter the data in the `data_frame` argument, consider using a [Filter](filter ## Enhanced `plotly.express` chart with reference line -The below examples shows a case where we enhance an existing `plotly.express` chart. We add a new argument (`hline`), that is used to draw a grey reference line at the height determined by the value of `hline`. The important thing to note is that we then -add a `Parameter` that enables the dashboard user to interact with the argument, and hence move the line in this case. See the `Result` tab for an animation. +The below examples shows a case where we enhance an existing `plotly.express` chart. We add a new argument (`hline`), that is used to draw a grey reference line at the height determined by the value of `hline`. The important thing to note is that we then add a `Parameter` that enables the dashboard user to interact with the argument, and hence move the line in this case. See the `Result` tab for an animation. !!! example "Custom `plotly.express` scatter chart with a `Parameter`" === "app.py" - ```{.python pycafe-link} import vizro.models as vm import vizro.plotly.express as px @@ -86,17 +83,15 @@ add a `Parameter` that enables the dashboard user to interact with the argument, Vizro().build(dashboard).run() ``` - 1. Note that arguments of the custom chart can be parametrized. Here we choose to parametrize the `hline` argument (see below). - 2. Here we parametrize the `hline` argument, but any other argument can be parametrized as well. Since there is complete flexibility regarding what can be derived from such arguments, the dashboard user has a wide range of customization options. + 1. Note that arguments of the custom chart can be parametrized. Here we choose to parametrize the `hline` argument (see below). + 1. Here we parametrize the `hline` argument, but any other argument can be parametrized as well. Since there is complete flexibility regarding what can be derived from such arguments, the dashboard user has a wide range of customization options. + === "app.yaml" - ```yaml - # Custom charts are currently only possible via Python configuration + Custom charts are currently only possible via Python configuration. ``` - === "Result" - [![Graph2]][Graph2] - - [Graph2]: ../../assets/user_guides/custom_charts/custom_chart_showcase_parameter.gif + === "Result" + [![Graph2]][graph2] ## New Waterfall chart based on `go.Figure()` @@ -104,7 +99,6 @@ The below examples shows a more involved use-case. We create and style a waterfa !!! example "Custom `go.Figure()` waterfall chart with a `Parameter`" === "app.py" - ```{.python pycafe-link} import pandas as pd import plotly.graph_objects as go @@ -162,10 +156,10 @@ The below examples shows a more involved use-case. We create and style a waterfa ``` === "app.yaml" - ```yaml - # Custom charts are currently only possible via Python configuration - ``` + Custom charts are currently only possible via Python configuration. + === "Result" - [![Graph3]][Graph3] + [![Graph3]][graph3] - [Graph3]: ../../assets/user_guides/custom_charts/custom_chart_waterfall.png +[graph2]: ../../assets/user_guides/custom_charts/custom_chart_showcase_parameter.gif +[graph3]: ../../assets/user_guides/custom_charts/custom_chart_waterfall.png diff --git a/vizro-core/docs/pages/user-guides/custom-css.md b/vizro-core/docs/pages/user-guides/custom-css.md index 44e3a3621..af2219838 100755 --- a/vizro-core/docs/pages/user-guides/custom-css.md +++ b/vizro-core/docs/pages/user-guides/custom-css.md @@ -1,25 +1,20 @@ # Customizing Vizro dashboard CSS -Vizro is opinionated about visual formatting, and some elements, such as the layout of the navigation and controls, -are fixed. You can customize some settings such as background colors, fonts, and other styles via CSS overrides. +Vizro is opinionated about visual formatting, and some elements, such as the layout of the navigation and controls, are fixed. You can customize some settings such as background colors, fonts, and other styles via CSS overrides. To make customizations, you need to: 1. **Add a CSS file to your `assets` folder**. Refer to our user guide on [adding static assets](assets.md#how-to-add-static-assets). -2. **Identify the correct CSS selector** for the component you want to style. -3. **Change the relevant CSS properties** in your CSS file. - - +1. **Identify the correct CSS selector** for the component you want to style. +1. **Change the relevant CSS properties** in your CSS file. ## Introduction to Vizro CSS + For a short introduction to CSS, we recommend reading this article: [Get Started with CSS in 5 Minutes](https://www.freecodecamp.org/news/get-started-with-css-in-5-minutes-e0804813fc3e/). -For a more comprehensive tutorial, refer to the [W3Schools CSS tutorial](https://www.w3schools.com/css/default.asp). -The entire tutorial is beneficial, but the section on [CSS selectors](https://www.w3schools.com/css/css_selectors.asp) -will be particularly useful. +For a more comprehensive tutorial, refer to the [W3Schools CSS tutorial](https://www.w3schools.com/css/default.asp). The entire tutorial is beneficial, but the section on [CSS selectors](https://www.w3schools.com/css/css_selectors.asp) will be particularly useful. -In Vizro, the CSS file is read in as an external stylesheet. The most common way of applying any styling to -Vizro is therefore through the use of CSS selectors: +In Vizro, the CSS file is read in as an external stylesheet. The most common way of applying any styling to Vizro is therefore through the use of CSS selectors: - **Element Selector**: Applies the style to all elements inside the Vizro app. @@ -33,8 +28,7 @@ Vizro is therefore through the use of CSS selectors: } ``` -- **Class selector:** Targets all elements with the given class for styling. All CSS classes must be preceded with a -`.` symbol. +- **Class selector:** Targets all elements with the given class for styling. All CSS classes must be preceded with a `.` symbol. ``` .card { @@ -50,30 +44,25 @@ Vizro is therefore through the use of CSS selectors: } ``` - ## Identify the correct CSS selector Use Chrome DevTools or a similar tool (Web Inspector, Web Developer Tools, etc.) to inspect the HTML document in your browser. -1. **Open DevTools:** In Google Chrome, right-click on the app and select "Inspect" from the context menu. This opens the -HTML document of your Vizro app. +1. **Open DevTools:** In Google Chrome, right-click on the app and select "Inspect" from the context menu. This opens the HTML document of your Vizro app. ![Inspect panel](../../assets/user_guides/custom_css/inspect-panel.png) - -2. **Select an element:** Suppose you want to change the background color of your cards. Click the -"Select an element in the page to inspect it" icon in the top left corner of the inspect panel. +1. **Select an element:** Suppose you want to change the background color of your cards. Click the "Select an element in the page to inspect it" icon in the top left corner of the inspect panel. ![Inspect icon](../../assets/user_guides/custom_css/inspect-icon.png) -3. **Find the HTML Block:** Hover over the component you want to style. The corresponding HTML block will be -highlighted in the HTML document. +1. **Find the HTML Block:** Hover over the component you want to style. The corresponding HTML block will be highlighted in the HTML document. ![Highlighted element](../../assets/user_guides/custom_css/highlighted-element.png) Notice that the selected HTML block corresponds to the container of the card and has a CSS class, here it is `card`. -4. **Apply CSS:** Use this CSS class to style the card component. In your CSS file, you can write: +1. **Apply CSS:** Use this CSS class to style the card component. In your CSS file, you can write: ``` .card { @@ -83,25 +72,26 @@ highlighted in the HTML document. This changes the background color for any HTML element with the `card` class. -**Tip:** You can also test your CSS live by editing the CSS attributes in the "Elements" panel. -For example, temporarily add `background: blue;`. Note that this change will be lost upon reloading the page. +**Tip:** You can also test your CSS live by editing the CSS attributes in the "Elements" panel. For example, temporarily add `background: blue;`. Note that this change will be lost upon reloading the page. ![Temporary changes](../../assets/user_guides/custom_css/temporary-changes.png) - ## CSS overwrites ### Overwrite CSS globally -To overwrite any global CSS property, you need to target the element selector and place your CSS file with the -overwrites in the `assets` folder. + +To overwrite any global CSS property, you need to target the element selector and place your CSS file with the overwrites in the `assets` folder. !!! example "Overwrite CSS globally" === "my_css_file.css" + ```css - h1, h2 { - color: hotpink; + h1, + h2 { + color: hotpink; } ``` + === "app.py" ```py import os @@ -134,44 +124,42 @@ overwrites in the `assets` folder. # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - # This is an

tag + - components: + - text: | + # This is an

tag - ## This is an

tag + ## This is an

tag - ###### This is an

tag - type: card - title: Changing the header color + ###### This is an
tag + type: card + title: Changing the header color ``` - === "Result" - [![AssetsCSS]][AssetsCSS] - - [AssetsCSS]: ../../assets/user_guides/assets/css_change.png + === "Result" + [![AssetsCSS]][assetscss] ### Overwrite CSS for selected pages -To style components for a specific page, use the page's `id` in the CSS selectors. By default, this is the -[same as the page `title`](pages.md), but such a value might not be a valid CSS identifier. -A suitable `id` must be unique across all models in the dashboard and should contain only alphanumeric -characters, hyphens (`-`) and underscores (`_`). In particular, note that spaces are _not_ allowed. +To style components for a specific page, use the page's `id` in the CSS selectors. By default, this is the [same as the page `title`](pages.md), but such a value might not be a valid CSS identifier. + +A suitable `id` must be unique across all models in the dashboard and should contain only alphanumeric characters, hyphens (`-`) and underscores (`_`). In particular, note that spaces are _not_ allowed. Suppose you want to hide the page title on one page only. Here's how you can achieve this: 1. Give a valid `id` to the `Page`, for example `Page(id="page-with-hidden-title", title="Page with hidden title", ...)`. -2. Identify the CSS class or CSS `id` you need to target. To hide the page title, you need to hide the parent container with the id `right-header`. -3. Use the `id` to hide the content. -4. Add your custom css file to the `assets` folder. - +1. Identify the CSS class or CSS `id` you need to target. To hide the page title, you need to hide the parent container with the id `right-header`. +1. Use the `id` to hide the content. +1. Add your custom css file to the `assets` folder. !!! example "Hide page title on selected pages" === "my_css_file.css" + ```css #page-with-hidden-title #right-header { - display: none; + display: none; } ``` + === "app.py" ```py import vizro.models as vm @@ -199,25 +187,24 @@ Suppose you want to hide the page title on one page only. Here's how you can ach # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - # Placeholder - type: card - title: Page with hidden title - id: page-with-hidden-title - - components: - - text: | - # Placeholder - type: card - title: Page with shown title + - components: + - text: | + # Placeholder + type: card + title: Page with hidden title + id: page-with-hidden-title + - components: + - text: | + # Placeholder + type: card + title: Page with shown title ``` - === "Result" - [![PageTitle]][PageTitle] - - [PageTitle]: ../../assets/user_guides/assets/css_page_title.png + === "Result" + [![PageTitle]][pagetitle] ### Overwrite CSS for selected components + To adjust CSS properties for specific components, such as altering the appearance of a selected [`Card`][vizro.models.Card] rather than all Cards, you need to supply an `id` to the component you want to style. Let's say we want to change the `background-color` and `color` of a specific `Card`. @@ -225,15 +212,15 @@ Let's say we want to change the `background-color` and `color` of a specific `Ca Here's how you can do it: 1. Assign a unique `id` to the relevant `Card`, for example: `Card(id="custom-card", ...)` -2. Run your dashboard and open it in your browser -3. View the HTML document to find the appropriate CSS class or element you need to target, as explained in the section -on [identifying the correct CSS selector](#identify-the-correct-css-selector). +1. Run your dashboard and open it in your browser +1. View the HTML document to find the appropriate CSS class or element you need to target, as explained in the section on [identifying the correct CSS selector](#identify-the-correct-css-selector). -It's essential to understand the relationship between the targeted CSS class or element and the component assigned -`id`, for example: +It's essential to understand the relationship between the targeted CSS class or element and the component assigned `id`, for example: -```html title="HTML structure of a `Card`" + +\`\`\`html title="HTML structure of a `Card`" +

Lorem ipsum dolor sit amet consectetur adipisicing elit.

@@ -242,24 +229,25 @@ It's essential to understand the relationship between the targeted CSS class or ``` -* **Main element with `id`:** There is a `
` with our `id="custom-card"`. -* **Parent element:** That `
` is wrapped inside a parent `
` with the class name `"card"`. This is the element we need to target to change the background color. -* **Child element:** The card text is wrapped inside a `

` that is a child of the `

` with our `id`. This is the element we need to target to change the font color. - +- **Main element with `id`:** There is a `
` with our `id="custom-card"`. +- **Parent element:** That `
` is wrapped inside a parent `
` with the class name `"card"`. This is the element we need to target to change the background color. +- **Child element:** The card text is wrapped inside a `

` that is a child of the `

` with our `id`. This is the element we need to target to change the font color. !!! example "Customizing CSS properties in selective components" === "my_css_file.css" + ```css /* Apply styling to parent */ .card:has(#custom-card) { - background-color: white; + background-color: white; } /* Apply styling to child */ #custom-card p { - color: black; + color: black; } ``` + === "app.py" ```py import vizro.models as vm @@ -285,69 +273,61 @@ It's essential to understand the relationship between the targeted CSS class or # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - Lorem ipsum dolor sit amet consectetur adipisicing elit. - type: card - id: custom-card - - text: | - Lorem ipsum dolor sit amet consectetur adipisicing elit. - type: card - title: Changing the card color + - components: + - text: | + Lorem ipsum dolor sit amet consectetur adipisicing elit. + type: card + id: custom-card + - text: | + Lorem ipsum dolor sit amet consectetur adipisicing elit. + type: card + title: Changing the card color ``` - === "Result" - [![CardCSS]][CardCSS] - - [CardCSS]: ../../assets/user_guides/assets/css_change_card.png + === "Result" + [![CardCSS]][cardcss] !!! note "Relationship between model ID and CSS ID" + Some Vizro components produce a single HTML element with an ID that matches the model ID, allowing you to target it directly using the CSS #id selector. Other components generate multiple HTML elements. Within these, the "core" element will have an ID matching the model ID, while non-core elements may have IDs that are variations of it, such as `{model-id}-title`. - Some Vizro components produce a single HTML element with an ID that matches the model ID, allowing you to target it - directly using the CSS #id selector. Other components generate multiple HTML elements. Within these, the "core" - element will have an ID matching the model ID, while non-core elements may have IDs that are variations of it, - such as `{model-id}-title`. - - In all instances, you can determine the correct selector by using Chrome DevTools or a similar tool after setting the - appropriate model ID. - + In all instances, you can determine the correct selector by using Chrome DevTools or a similar tool after setting the appropriate model ID. ## Common examples ### Turn off page title + See the example above on [hiding the page title on selected pages](#overwrite-css-for-selected-pages). ### Change the background color of a card + See the example above on [customizing CSS properties in selective components](#overwrite-css-for-selected-components). ### Change the global font + The default fonts for a Vizro app are `Inter, sans-serif, Arial, serif`. If you need to change the global font, perhaps to adhere to branding guidelines, follow these steps: 1. Download the desired font from a font provider such as [Google Fonts](https://fonts.google.com/). -2. Place the font file (`.ttf`, `woff2`, etc.) into your `assets` folder. Here’s an example of what the assets folder might look like: - ![Font Change](../../assets/user_guides/custom_css/font-change.png) +1. Place the font file (`.ttf`, `woff2`, etc.) into your `assets` folder. Here’s an example of what the assets folder might look like: -3. Add the font to your CSS file using the `@font-face` rule and apply the font globally to your Vizro app, making sure -to specify fallback fonts. Add the following to your `custom.css` file: + ![Font Change](../../assets/user_guides/custom_css/font-change.png) +1. Add the font to your CSS file using the `@font-face` rule and apply the font globally to your Vizro app, making sure to specify fallback fonts. Add the following to your `custom.css` file: ```css @font-face { - font-family: PlayfairDisplay; - src: url("PlayfairDisplay-VariableFont_wght.ttf") format("truetype"); + font-family: PlayfairDisplay; + src: url("PlayfairDisplay-VariableFont_wght.ttf") format("truetype"); } * { - font-family: PlayfairDisplay, Inter, sans-serif, Arial, serif; + font-family: PlayfairDisplay, Inter, sans-serif, Arial, serif; } ``` - -4. Note that the modification above applies solely to the dashboard font. To also change the font within the -Plotly charts, you must specify this at the beginning of your `app.py` file: +1. Note that the modification above applies solely to the dashboard font. To also change the font within the Plotly charts, you must specify this at the beginning of your `app.py` file: ```python import plotly.io as pio @@ -357,34 +337,33 @@ Plotly charts, you must specify this at the beginning of your `app.py` file: ``` ### Reposition the logo -By default, the logo appears in the top left corner of the dashboard. You can move it further to the left or right by -adjusting the `padding` of the `#page-header` element. Here is an example of how to achieve this: + +By default, the logo appears in the top left corner of the dashboard. You can move it further to the left or right by adjusting the `padding` of the `#page-header` element. Here is an example of how to achieve this: ```css #page-header { - padding-left: 8px; + padding-left: 8px; } ``` ![Logo positioning](../../assets/user_guides/custom_css/logo-position.png) - ### Change the styling of a container -If you want to make the subsections of your dashboard stand out more, you can do this by placing your components -inside a [Container](container.md) and changing the container's styling, for example, background color, borders, padding, etc. -To do this, you need to change the container's CSS class. Using the DevTool, as explained in the section on -[identifying the correct CSS selector](#identify-the-correct-css-selector), you'll find that the CSS class for the -`Container` is `page-component-container`. You can then use this class to set a new `background-color` and `padding`. +If you want to make the subsections of your dashboard stand out more, you can do this by placing your components inside a [Container](container.md) and changing the container's styling, for example, background color, borders, padding, etc. + +To do this, you need to change the container's CSS class. Using the DevTool, as explained in the section on [identifying the correct CSS selector](#identify-the-correct-css-selector), you'll find that the CSS class for the `Container` is `page-component-container`. You can then use this class to set a new `background-color` and `padding`. !!! example "Style a container" === "custom.css" + ```css .page-component-container { background: var(--surfaces-bg-card); padding: 12px; } ``` + === "app.py" ```py import vizro.models as vm @@ -419,12 +398,12 @@ To do this, you need to change the container's CSS class. Using the DevTool, as # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - title: "Page with subsections" + - title: Page with subsections layout: grid: [[0, 1]] components: - type: container - title: "Container I" + title: Container I components: - type: graph figure: @@ -434,7 +413,7 @@ To do this, you need to change the container's CSS class. Using the DevTool, as y: sepal_length color: species - type: container - title: "Container II" + title: Container II components: - type: graph figure: @@ -444,13 +423,11 @@ To do this, you need to change the container's CSS class. Using the DevTool, as y: sepal_length color: species ``` - === "Result" - [![StyleContainer]][StyleContainer] - [StyleContainer]: ../../assets/user_guides/custom_css/style-container.png + === "Result" + [![StyleContainer]][stylecontainer] -You will notice that the background colors of the charts are different. To align it with the colors of the container, -you can make the charts' background transparent. +You will notice that the background colors of the charts are different. To align it with the colors of the container, you can make the charts' background transparent. To make the background of all charts transparent: @@ -474,3 +451,8 @@ def custom_chart(data_frame): ``` ![Transparent charts](../../assets/user_guides/custom_css/transparent-charts.png) + +[assetscss]: ../../assets/user_guides/assets/css_change.png +[cardcss]: ../../assets/user_guides/assets/css_change_card.png +[pagetitle]: ../../assets/user_guides/assets/css_page_title.png +[stylecontainer]: ../../assets/user_guides/custom_css/style-container.png diff --git a/vizro-core/docs/pages/user-guides/custom-figures.md b/vizro-core/docs/pages/user-guides/custom-figures.md index f135127be..3a178932f 100644 --- a/vizro-core/docs/pages/user-guides/custom-figures.md +++ b/vizro-core/docs/pages/user-guides/custom-figures.md @@ -1,41 +1,36 @@ # How to create custom figures -This guide explains how to create custom figures, which is useful when you need a component that reacts to -[filter](filters.md) and [parameter](parameters.md) controls. +This guide explains how to create custom figures, which is useful when you need a component that reacts to [filter](filters.md) and [parameter](parameters.md) controls. -The [`Figure`][vizro.models.Figure] model accepts the `figure` argument, where you can enter _any_ custom figure function -as explained in the [user guide on figures](figure.md). +The [`Figure`][vizro.models.Figure] model accepts the `figure` argument, where you can enter _any_ custom figure function as explained in the [user guide on figures](figure.md). ## When to use a custom figure -As described in the flowchart detailing [when to use `Figure`](figure.md), custom figures should be used if -**both** of the following conditions are met: + +As described in the flowchart detailing [when to use `Figure`](figure.md), custom figures should be used if **both** of the following conditions are met: - You need a figure that doesn't fit into the existing pre-defined components ([`Graph`][vizro.models.Graph], [`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid]). - You need a figure that isn't available in our pre-defined figure functions [`vizro.figures`](../API-reference/figure-callables.md). ## Steps to create a custom figure -1. Define a function that returns a [Dash component](https://dash.plotly.com/#open-source-component-libraries). -This can, but does not need to, be based on code in our pre-defined figure functions in [`vizro.figures`](../API-reference/figure-callables.md). -2. Decorate it with `@capture("figure")`. -3. The function must accept a `data_frame` argument (of type `pandas.DataFrame`). -4. The figure should be derived from and require only one `pandas.DataFrame`. Dataframes from other arguments -will not react to dashboard controls such as [`Filter`](filters.md). -5. Pass your function to the `figure` argument of the [`Figure`][vizro.models.Figure] model. +1. Define a function that returns a [Dash component](https://dash.plotly.com/#open-source-component-libraries). This can, but does not need to, be based on code in our pre-defined figure functions in [`vizro.figures`](../API-reference/figure-callables.md). +1. Decorate it with `@capture("figure")`. +1. The function must accept a `data_frame` argument (of type `pandas.DataFrame`). +1. The figure should be derived from and require only one `pandas.DataFrame`. Dataframes from other arguments will not react to dashboard controls such as [`Filter`](filters.md). +1. Pass your function to the `figure` argument of the [`Figure`][vizro.models.Figure] model. The following examples can be used as a base to build more sophisticated figures. ## Examples of custom figures ### Custom KPI card -To change the design or content of our existing KPI (key performance indicator) cards from -[`vizro.figures`](../API-reference/figure-callables.md), you can do so by following the steps described above. -For instance, to make a KPI card with the icon positioned on the right side of the title instead of the left, -copy and paste the [source code of `kpi_card`](../API-reference/figure-callables.md#vizro.figures.kpi_card) and -adjust the return statement of the function. +To change the design or content of our existing KPI (key performance indicator) cards from [`vizro.figures`](../API-reference/figure-callables.md), you can do so by following the steps described above. + +For instance, to make a KPI card with the icon positioned on the right side of the title instead of the left, copy and paste the [source code of `kpi_card`](../API-reference/figure-callables.md#vizro.figures.kpi_card) and adjust the return statement of the function. + !!! example "Custom KPI card" === "app.py" ```{.python pycafe-link} @@ -107,29 +102,26 @@ adjust the return statement of the function. ``` 1. Here we decorate our custom figure function with the `@capture("figure")` decorator. - 2. The custom figure function needs to have a `data_frame` argument and return a `Dash` component. - 3. We adjust the return statement to include the icon on the right side of the title. This is achieved by swapping the order of the `html.H2` and `html.P` compared to the original `kpi_card`. - 4. This creates a [`layout`](layouts.md) with four rows and columns. The KPI cards are positioned in the first two cells, while the remaining cells are empty. - 5. For more information, refer to the API reference for the [`kpi_card`](../API-reference/figure-callables.md#vizro.figures.kpi_card). - 6. Our custom figure function `custom_kpi_card` now needs to be passed on to the `vm.Figure`. + 1. The custom figure function needs to have a `data_frame` argument and return a `Dash` component. + 1. We adjust the return statement to include the icon on the right side of the title. This is achieved by swapping the order of the `html.H2` and `html.P` compared to the original `kpi_card`. + 1. This creates a [`layout`](layouts.md) with four rows and columns. The KPI cards are positioned in the first two cells, while the remaining cells are empty. + 1. For more information, refer to the API reference for the [`kpi_card`](../API-reference/figure-callables.md#vizro.figures.kpi_card). + 1. Our custom figure function `custom_kpi_card` now needs to be passed on to the `vm.Figure`. === "app.yaml" - ```yaml - # Custom figures are currently only possible via Python configuration - ``` - === "Result" - [![CustomKPI]][CustomKPI] + Custom figures are currently only possible via Python configuration. - [CustomKPI]: ../../assets/user_guides/figure/custom_kpi.png + === "Result" + [![CustomKPI]][customkpi] ### Dynamic HTML header -You can create a custom figure for any [Dash component](https://dash.plotly.com/#open-source-component-libraries). -Below is an example of a custom figure that returns a `html.H2` component that dynamically updates based on the selected -name from a filter. + +You can create a custom figure for any [Dash component](https://dash.plotly.com/#open-source-component-libraries). Below is an example of a custom figure that returns a `html.H2` component that dynamically updates based on the selected name from a filter. + !!! example "Dynamic HTML header" === "app.py" ```{.python pycafe-link} @@ -159,27 +151,24 @@ name from a filter. ``` 1. Here we decorate our custom figure function with the `@capture("figure")` decorator. - 2. The custom figure function needs to have a `data_frame` argument and return a `Dash` component. - 3. We return a `html.H2` component that dynamically updates based on the selected name from the filter. - 4. Our custom figure function `dynamic_html_header` now needs to be passed on to the `vm.Figure`. + 1. The custom figure function needs to have a `data_frame` argument and return a `Dash` component. + 1. We return a `html.H2` component that dynamically updates based on the selected name from the filter. + 1. Our custom figure function `dynamic_html_header` now needs to be passed on to the `vm.Figure`. === "app.yaml" - ```yaml - # Custom figures are currently only possible via Python configuration - ``` - === "Result" - [![CustomHTML]][CustomHTML] + Custom figures are currently only possible via Python configuration. - [CustomHTML]: ../../assets/user_guides/figure/custom_html.png + === "Result" + [![CustomHTML]][customhtml] - ### Dynamic number of cards -The example below shows how to create multiple cards created from a `pandas.DataFrame` where the -number of cards displayed dynamically adjusts based on a `vm.Parameter`. + +The example below shows how to create multiple cards created from a `pandas.DataFrame` where the number of cards displayed dynamically adjusts based on a `vm.Parameter`. + !!! example "Dynamic number of cards" === "app.py" ```py @@ -239,40 +228,39 @@ number of cards displayed dynamically adjusts based on a `vm.Parameter`. ``` 1. Here we decorate our custom figure function with the `@capture("figure")` decorator. - 2. The custom figure function needs to have a `data_frame` argument and return a `Dash` component. - 3. Our decorated figure function `multiple_cards` now needs to be passed on to the `vm.Figure`. - 4. We add a [`vm.Parameter`](parameters.md) to dynamically adjust the number of cards displayed. - The parameter targets the `n_rows` argument of the `multiple_cards` function, determining the number of rows - taken from the data. + 1. The custom figure function needs to have a `data_frame` argument and return a `Dash` component. + 1. Our decorated figure function `multiple_cards` now needs to be passed on to the `vm.Figure`. + 1. We add a [`vm.Parameter`](parameters.md) to dynamically adjust the number of cards displayed. The parameter targets the `n_rows` argument of the `multiple_cards` function, determining the number of rows taken from the data. PyCafe logoRun and edit this code in PyCafe === "styling.css" ```css .multiple-cards-container { - display: flex; - flex-wrap: wrap; - gap: 12px; + display: flex; + flex-wrap: wrap; + gap: 12px; } .figure-container { - height: unset; - width: unset; + height: unset; + width: unset; } .figure-container .card { - height: 210px; - width: 240px; + height: 210px; + width: 240px; } ``` - === "app.yaml" - ```yaml - # Custom figures are currently only possible via Python configuration - ``` - === "Result" - [![CustomFigure]][CustomFigure] - [CustomFigure]: ../../assets/user_guides/figure/custom_multiple_cards.png + === "app.yaml" + Custom figures are currently only possible via Python configuration. + === "Result" + [![CustomFigure]][customfigure] + +[customfigure]: ../../assets/user_guides/figure/custom_multiple_cards.png +[customhtml]: ../../assets/user_guides/figure/custom_html.png +[customkpi]: ../../assets/user_guides/figure/custom_kpi.png diff --git a/vizro-core/docs/pages/user-guides/custom-tables.md b/vizro-core/docs/pages/user-guides/custom-tables.md index 8fa5f5252..9818fb240 100644 --- a/vizro-core/docs/pages/user-guides/custom-tables.md +++ b/vizro-core/docs/pages/user-guides/custom-tables.md @@ -1,21 +1,18 @@ # How to create custom Dash AG Grids and Dash DataTables -In cases where the available arguments for the [`dash_ag_grid`][vizro.tables.dash_ag_grid] or [`dash_data_table`][vizro.tables.dash_data_table] models are not sufficient, -you can create a custom Dash AG Grid or Dash DataTable. +In cases where the available arguments for the [`dash_ag_grid`][vizro.tables.dash_ag_grid] or [`dash_data_table`][vizro.tables.dash_data_table] models are not sufficient, you can create a custom Dash AG Grid or Dash DataTable. -The [`Table`][vizro.models.Table] and the [`AgGrid`][vizro.models.AgGrid] model accept the `figure` argument, where you can enter -_any_ [`dash_ag_grid`][vizro.tables.dash_ag_grid] or [`dash_data_table`][vizro.tables.dash_data_table] chart as explained in the [user guide on tables](table.md). +The [`Table`][vizro.models.Table] and the [`AgGrid`][vizro.models.AgGrid] model accept the `figure` argument, where you can enter _any_ [`dash_ag_grid`][vizro.tables.dash_ag_grid] or [`dash_data_table`][vizro.tables.dash_data_table] chart as explained in the [user guide on tables](table.md). One reason could be that you want to create a table/grid that requires computations that can be controlled by parameters (see the example below). ### Steps to create a custom table 1. Define a function that returns a `dash_ag_grid.AgGrid` or `dash_table.DataTable` object. -2. Decorate it with `@capture("ag_grid")` or `@capture("table")`. -3. The function must accept a `data_frame` argument (of type `pandas.DataFrame`). -4. The table should be derived from and require only one `pandas.DataFrame`. Dataframes from other arguments -will not react to dashboard controls such as [`Filter`](filters.md). -5. Pass your function to the `figure` argument of the [`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid] model. +1. Decorate it with `@capture("ag_grid")` or `@capture("table")`. +1. The function must accept a `data_frame` argument (of type `pandas.DataFrame`). +1. The table should be derived from and require only one `pandas.DataFrame`. Dataframes from other arguments will not react to dashboard controls such as [`Filter`](filters.md). +1. Pass your function to the `figure` argument of the [`Table`][vizro.models.Table] or [`AgGrid`][vizro.models.AgGrid] model. The following examples show a possible version of a custom table. In this case the argument `chosen_columns` was added, which you can control with a parameter: @@ -70,14 +67,12 @@ The following examples show a possible version of a custom table. In this case t Vizro().build(dashboard).run() ``` + === "app.yaml" - ```yaml - # Custom tables are currently only possible via Python configuration - ``` - === "Result" - [![Table3]][Table3] + Custom tables are currently only possible via Python configuration. - [Table3]: ../../assets/user_guides/table/custom_table.png + === "Result" + [![Table3]][table3] ??? example "Custom Dash AgGrid" === "app.py" @@ -136,11 +131,12 @@ The following examples show a possible version of a custom table. In this case t Vizro().build(dashboard).run() ``` + === "app.yaml" - ```yaml - # Custom Ag Grids are currently only possible via Python configuration - ``` + Custom Ag Grids are currently only possible via Python configuration. + === "Result" - [![GridCustom]][GridCustom] + [![GridCustom]][gridcustom] - [GridCustom]: ../../assets/user_guides/table/custom_grid.png +[gridcustom]: ../../assets/user_guides/table/custom_grid.png +[table3]: ../../assets/user_guides/table/custom_table.png diff --git a/vizro-core/docs/pages/user-guides/dashboard.md b/vizro-core/docs/pages/user-guides/dashboard.md index 0b37e03fa..244f65256 100644 --- a/vizro-core/docs/pages/user-guides/dashboard.md +++ b/vizro-core/docs/pages/user-guides/dashboard.md @@ -1,16 +1,15 @@ # How to create a dashboard -This guide shows you how to configure and call a [`Dashboard`][vizro.models.Dashboard] using either -pydantic models, Python dictionaries, YAML, or JSON. + +This guide shows you how to configure and call a [`Dashboard`][vizro.models.Dashboard] using either pydantic models, Python dictionaries, YAML, or JSON. To create a dashboard: 1. Choose one of the possible configuration syntaxes -2. Create your `pages`, see our [guide on Pages](pages.md) -3. (optional) Choose a `theme`, see our [guide on Themes](themes.md) -4. (optional) Customize your `navigation`, see our [guide on Navigation](navigation.md) -5. (optional) Set a `title` for your dashboard -6. Add your `dashboard` to the `build` call of Vizro - +1. Create your `pages`, see our [guide on Pages](pages.md) +1. (optional) Choose a `theme`, see our [guide on Themes](themes.md) +1. (optional) Customize your `navigation`, see our [guide on Navigation](navigation.md) +1. (optional) Set a `title` for your dashboard +1. Add your `dashboard` to the `build` call of Vizro ## Use dashboard configuration options @@ -37,6 +36,7 @@ To create a dashboard: Vizro().build(dashboard).run() ``` + === "app.py - Python dict" ```py import vizro.plotly.express as px @@ -77,6 +77,7 @@ To create a dashboard: Vizro().build(dashboard).run() ``` + === "dashboard.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -101,50 +102,49 @@ To create a dashboard: type: filter title: My first dashboard ``` + === "dashboard.json" ```json { - "pages": [ + "pages": [ + { + "components": [ + { + "figure": { + "_target_": "scatter", + "color": "species", + "data_frame": "iris", + "x": "sepal_length", + "y": "petal_width" + }, + "type": "graph" + }, { - "components": [ - { - "figure": { - "_target_": "scatter", - "color": "species", - "data_frame": "iris", - "x": "sepal_length", - "y": "petal_width" - }, - "type": "graph" - }, - { - "figure": { - "_target_": "histogram", - "color": "species", - "data_frame": "iris", - "x": "sepal_width", - }, - "type": "graph" - } - ], - "controls": [ - { - "column": "species", - "type": "filter" - } - ], - "title": "My first dashboard" + "figure": { + "_target_": "histogram", + "color": "species", + "data_frame": "iris", + "x": "sepal_width" + }, + "type": "graph" } - ] + ], + "controls": [ + { + "column": "species", + "type": "filter" + } + ], + "title": "My first dashboard" + } + ] } ``` - === "Result" - [![Dashboard]][Dashboard] - [Dashboard]: ../../assets/user_guides/dashboard/dashboard.png + === "Result" + [![Dashboard]][dashboard] !!! note "Extra `.py` files for `yaml` and `json` required" - Note that in the `yaml` and `json` example an extra `.py` is required to register the data and parse the yaml/json configuration. === "app.py for yaml" @@ -164,6 +164,7 @@ To create a dashboard: Vizro().build(dashboard).run() ``` + === "app.py for json" ```py import json @@ -187,7 +188,6 @@ After running the dashboard, you can access the dashboard via `localhost:8050`. If supplied, the `title` of the [`Dashboard`][vizro.models.Dashboard] displays a heading at the top of every page. - ## Add a dashboard logo Vizro will [automatically incorporate the dashboard logo](assets.md/#add-a-logo-image) in the top-left corner of each page if an image named `logo.` is present within the assets folder. @@ -196,11 +196,10 @@ Vizro will [automatically incorporate the dashboard logo](assets.md/#add-a-logo- ## Browser title -The [website icon](assets.md/#change-the-favicon), Dashboard `title` (if supplied) and [Page `title`][vizro.models.Page] are displayed in the browser's -title bar. For example, if your Dashboard `title` is "Vizro Demo" and the Page `title` is "Homepage", then the title in the browser tab will be "Vizro Demo: Homepage". +The [website icon](assets.md/#change-the-favicon), Dashboard `title` (if supplied) and [Page `title`][vizro.models.Page] are displayed in the browser's title bar. For example, if your Dashboard `title` is "Vizro Demo" and the Page `title` is "Homepage", then the title in the browser tab will be "Vizro Demo: Homepage". ## Meta tags for social media -Vizro automatically adds [meta tags](https://metatags.io/) to display a preview card when your app is shared on social media and chat -clients. The preview includes the `URL`, `title`, plus an [image](assets.md/#include-a-meta-tags-image) and -[Page `description`][vizro.models.Page] (if supplied). To see an example, try sharing an example from the [Vizro examples gallery](https://vizro.mckinsey.com/). +Vizro automatically adds [meta tags](https://metatags.io/) to display a preview card when your app is shared on social media and chat clients. The preview includes the `URL`, `title`, plus an [image](assets.md/#include-a-meta-tags-image) and [Page `description`][vizro.models.Page] (if supplied). To see an example, try sharing an example from the [Vizro examples gallery](https://vizro.mckinsey.com/). + +[dashboard]: ../../assets/user_guides/dashboard/dashboard.png diff --git a/vizro-core/docs/pages/user-guides/data.md b/vizro-core/docs/pages/user-guides/data.md index b4fdfeda1..2161486c6 100644 --- a/vizro-core/docs/pages/user-guides/data.md +++ b/vizro-core/docs/pages/user-guides/data.md @@ -2,11 +2,12 @@ Vizro supports two different types of data: -* [Static data](#static-data): pandas DataFrame. This is the simplest method and best to use if you do not need the more advanced functionality of dynamic data. -* [Dynamic data](#dynamic-data): function that returns a pandas DataFrame. This is a bit more complex to understand but has more advanced functionality such as the ability to refresh data while the dashboard is running. +- [Static data](#static-data): pandas DataFrame. This is the simplest method and best to use if you do not need the more advanced functionality of dynamic data. +- [Dynamic data](#dynamic-data): function that returns a pandas DataFrame. This is a bit more complex to understand but has more advanced functionality such as the ability to refresh data while the dashboard is running. The following flowchart shows what you need to consider when choosing how to set up your data. -``` mermaid + +```mermaid graph TD refresh["`Do you need your data to refresh while the dashboard is running?`"] specification["`Do you need to specify your dashboard through a configuration language like YAML?`"] @@ -27,11 +28,10 @@ graph TD ``` ??? note "Static vs. dynamic data comparison" - This table gives a full comparison between static and dynamic data. Do not worry if you do not yet understand everything in it; it will become clearer after reading more about [static data](#static-data) and [dynamic data](#dynamic-data)! | | Static | Dynamic | - |---------------------------------------------------------------|------------------|------------------------------------------| + | ------------------------------------------------------------- | ---------------- | ---------------------------------------- | | Required Python type | pandas DataFrame | Function that returns a pandas DataFrame | | Can be supplied directly in `data_frame` argument of `figure` | Yes | No | | Can be referenced by name after adding to data manager | Yes | Yes | @@ -73,14 +73,13 @@ The below example uses the Iris data saved to a file `iris.csv` in the same dire ``` 1. `iris` is a pandas DataFrame created by reading from the CSV file `iris.csv`. - === "Result" - [![DataBasic]][DataBasic] - [DataBasic]: ../../assets/user_guides/data/data_pandas_dataframe.png + === "Result" + [![DataBasic]][databasic] The [`Graph`][vizro.models.Graph], [`AgGrid`][vizro.models.AgGrid] and [`Table`][vizro.models.Table] models all have an argument called `figure`. This accepts a function (in the above example, `px.scatter`) that takes a pandas DataFrame as its first argument. The name of this argument is always `data_frame`. When configuring the dashboard using Python, it is optional to give the name of the argument: if you like, you could write `data_frame=iris` instead of `iris`. -!!! note +!!! note With static data, once the dashboard is running, the data shown in the dashboard cannot change even if the source data in `iris.csv` changes. The code `iris = pd.read_csv("iris.csv")` is only executed once when the dashboard is first started. If you would like changes to source data to flow through to the dashboard then you must use [dynamic data](#dynamic-data). ### Reference by name @@ -107,27 +106,27 @@ If you would like to specify your dashboard configuration through YAML then you ``` 1. `"iris"` is the name of a data source added to the data manager. This data is a pandas DataFrame created by reading from the CSV file `iris.csv`. + === "dashboard.yaml" ```yaml pages: - - components: - - figure: - _target_: box - data_frame: iris # (1)! - x: species - y: petal_width - color: species - type: graph + - components: + - figure: + _target_: box + data_frame: iris # (1)! + x: species + y: petal_width + color: species + type: graph title: Static data example ``` 1. Refer to the `"iris"` data source in the data manager. - === "Result" - [![DataBasic]][DataBasic] - [DataBasic]: ../../assets/user_guides/data/data_pandas_dataframe.png + === "Result" + [![DataBasic]][databasic] -It is also possible to refer to a named data source using the Python API: `px.scatter("iris", ...)` or `px.scatter(data_frame="iris", ...)` would work if the `"iris"` data source has been registered in the data manager. +It is also possible to refer to a named data source using the Python API: `px.scatter("iris", ...)` or `px.scatter(data_frame="iris", ...)` would work if the `"iris"` data source has been registered in the data manager. ## Dynamic data @@ -166,14 +165,12 @@ The example below shows how data is fetched dynamically every time the page is r ``` 1. `iris` is a pandas DataFrame created by reading from the CSV file `iris.csv`. - 2. To demonstrate that dynamic data can change when the page is refreshed, select 50 points at random. This simulates what would happen if your file `iris.csv` were constantly changing. - 3. To use `load_iris_data` as dynamic data it must be added to the data manager. You should **not** actually call the function as `load_iris_data()`; doing so would result in static data that cannot be reloaded. - 4. Dynamic data is referenced by the name of the data source `"iris"`. + 1. To demonstrate that dynamic data can change when the page is refreshed, select 50 points at random. This simulates what would happen if your file `iris.csv` were constantly changing. + 1. To use `load_iris_data` as dynamic data it must be added to the data manager. You should **not** actually call the function as `load_iris_data()`; doing so would result in static data that cannot be reloaded. + 1. Dynamic data is referenced by the name of the data source `"iris"`. === "Result" - [![DynamicData]][DynamicData] - - [DynamicData]: ../../assets/user_guides/data/dynamic_data.gif + [![DynamicData]][dynamicdata] Since dynamic data sources must always be added to the data manager and referenced by name, they may be used in YAML configuration [exactly the same way as for static data sources](#reference-by-name). @@ -184,10 +181,10 @@ By default, each time the dashboard is refreshed a dynamic data function execute The Vizro data manager has a server-side caching mechanism to help solve this. Vizro's cache uses [Flask-Caching](https://flask-caching.readthedocs.io/en/latest/), which supports a number of possible cache backends and [configuration options](https://flask-caching.readthedocs.io/en/latest/#configuring-flask-caching). By default, the cache is turned off. + In a development environment the easiest way to enable caching is to use a [simple memory cache](https://cachelib.readthedocs.io/en/stable/simple/) with the default configuration options. This is achieved by adding one line to the above example to set `data_manager.cache`: !!! example "Simple cache with default timeout of 5 minutes" - ```py hl_lines="13" from flask_caching import Cache from vizro import Vizro @@ -225,7 +222,6 @@ data_manager.cache = Cache(config={"CACHE_TYPE": "SimpleCache", "CACHE_DEFAULT_T ``` !!! warning - Simple cache exists purely for single-process development purposes and is not intended to be used in production. If you deploy with multiple workers, [for example with Gunicorn](run.md/#gunicorn), then you should use a production-ready cache backend. All of Flask-Caching's [built-in backends](https://flask-caching.readthedocs.io/en/latest/#built-in-cache-backends) other than `SimpleCache` are suitable for production. In particular, you might like to use [`FileSystemCache`](https://cachelib.readthedocs.io/en/stable/file/) or [`RedisCache`](https://cachelib.readthedocs.io/en/stable/redis/): ```py title="Production-ready caches" @@ -239,7 +235,9 @@ data_manager.cache = Cache(config={"CACHE_TYPE": "SimpleCache", "CACHE_DEFAULT_T Since Flask-Caching relies on [`pickle`](https://docs.python.org/3/library/pickle.html), which can execute arbitrary code during unpickling, you should not cache data from untrusted sources. Doing so [could be unsafe](https://github.com/pallets-eco/flask-caching/pull/209). Note that when a production-ready cache backend is used, the cache is persisted beyond the Vizro process and is not cleared by restarting your server. To clear the cache then you must do so manually, for example, if you use `FileSystemCache` then you would delete your `cache` directory. Persisting the cache can also be useful for development purposes when handling data that takes a long time to load: even if you do not need the data to refresh while your dashboard is running, it can speed up your development loop to use dynamic data with a cache that is persisted between repeated runs of Vizro. + + #### Set timeouts You can change the timeout of the cache independently for each dynamic data source in the data manager using the `timeout` setting (measured in seconds). A `timeout` of 0 indicates that the cache does not expire. This is effectively the same as using [static data](#static-data). @@ -268,14 +266,13 @@ data_manager["no_expire_data"].timeout = 0 ### Parametrize data loading -You can supply arguments to your dynamic data loading function that can be modified from the dashboard. -For example, if you are handling big data then you can use an argument to specify the number of entries or size of chunk of data. +You can supply arguments to your dynamic data loading function that can be modified from the dashboard. For example, if you are handling big data then you can use an argument to specify the number of entries or size of chunk of data. To add a parameter to control a dynamic data source, do the following: 1. add the appropriate argument to your dynamic data function and specify a default value for the argument. -2. give an `id` to all components that have the data source you wish to alter through a parameter. -3. [add a parameter](parameters.md) with `targets` of the form `.data_frame.` and a suitable [selector](selectors.md). +1. give an `id` to all components that have the data source you wish to alter through a parameter. +1. [add a parameter](parameters.md) with `targets` of the form `.data_frame.` and a suitable [selector](selectors.md). For example, let us extend the [dynamic data example](#dynamic-data) above to show how the `load_iris_data` can take an argument `number_of_points` controlled from the dashboard with a [`Slider`][vizro.models.Slider]. @@ -314,21 +311,18 @@ For example, let us extend the [dynamic data example](#dynamic-data) above to sh ``` 1. `load_iris_data` takes a single argument, `number_of_points`, with a default value of 10. - 2. `iris` is a pandas DataFrame created by reading from the CSV file `iris.csv`. - 3. Sample points at random, where `number_of_points` gives the number of points selected. - 4. To use `load_iris_data` as dynamic data it must be added to the data manager. You should **not** actually call the function as `load_iris_data()` or `load_iris_data(number_of_points=...)`; doing so would result in static data that cannot be reloaded. - 5. Give the `vm.Graph` component `id="graph"` so that the `vm.Parameter` can target it. Dynamic data is referenced by the name of the data source `"iris"`. - 6. Create a `vm.Parameter` to target the `number_of_points` argument for the `data_frame` used in `graph`. + 1. `iris` is a pandas DataFrame created by reading from the CSV file `iris.csv`. + 1. Sample points at random, where `number_of_points` gives the number of points selected. + 1. To use `load_iris_data` as dynamic data it must be added to the data manager. You should **not** actually call the function as `load_iris_data()` or `load_iris_data(number_of_points=...)`; doing so would result in static data that cannot be reloaded. + 1. Give the `vm.Graph` component `id="graph"` so that the `vm.Parameter` can target it. Dynamic data is referenced by the name of the data source `"iris"`. + 1. Create a `vm.Parameter` to target the `number_of_points` argument for the `data_frame` used in `graph`. === "Result" - [![ParametrizedDynamicData]][ParametrizedDynamicData] - - [ParametrizedDynamicData]: ../../assets/user_guides/data/parametrized_dynamic_data.gif + [![ParametrizedDynamicData]][parametrizeddynamicdata] Parametrized data loading is compatible with [caching](#configure-cache). The cache uses [memoization](https://flask-caching.readthedocs.io/en/latest/#memoization), so that the dynamic data function's arguments are included in the cache key. This means that `load_iris_data(number_of_points=10)` is cached independently of `load_iris_data(number_of_points=20)`. !!! warning - You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). For example, you should not expose a filepath to load without passing it through a function like [`werkzeug.utils.secure_filename`](https://werkzeug.palletsprojects.com/en/3.0.x/utils/#werkzeug.utils.secure_filename), or you might enable arbitrary access to files on your server. You cannot pass [nested parameters](parameters.md#nested-parameters) to dynamic data. You can only target the top-level arguments of the data loading function, not the nested keys in a dictionary. @@ -344,3 +338,7 @@ Although a selector is automatically chosen for you in a filter when your dashbo ```py vm.Filter(column="species", selector=vm.Dropdown(options=["setosa", "versicolor", "virginica"]) ``` + +[databasic]: ../../assets/user_guides/data/data_pandas_dataframe.png +[dynamicdata]: ../../assets/user_guides/data/dynamic_data.gif +[parametrizeddynamicdata]: ../../assets/user_guides/data/parametrized_dynamic_data.gif diff --git a/vizro-core/docs/pages/user-guides/extensions.md b/vizro-core/docs/pages/user-guides/extensions.md index 2c7efc9ac..74a740448 100644 --- a/vizro-core/docs/pages/user-guides/extensions.md +++ b/vizro-core/docs/pages/user-guides/extensions.md @@ -2,64 +2,49 @@ At its simplest, Vizro enables low-code configuration, but you can also customize it to go beyond its default capabilities by incorporating any Dash component, Dash callback, or Plotly chart. -* **[Vizro customizations](#vizro-customizations)**. You can customize Vizro to extend the default functionality of Vizro and create Python functions as customized Plotly charts, tables, dashboard components, actions, or reactive HTML components, and then plug them directly into the existing Vizro dashboard configuration (as explained below). +- **[Vizro customizations](#vizro-customizations)**. You can customize Vizro to extend the default functionality of Vizro and create Python functions as customized Plotly charts, tables, dashboard components, actions, or reactive HTML components, and then plug them directly into the existing Vizro dashboard configuration (as explained below). -* **[Dash customizations](#dash-customizations)**. You can add custom Dash callbacks directly to any Vizro dashboard, enabling you to code beneath the Vizro layer and control Dash directly. +- **[Dash customizations](#dash-customizations)**. You can add custom Dash callbacks directly to any Vizro dashboard, enabling you to code beneath the Vizro layer and control Dash directly. -* **[CSS customizations](#css-customizations)**. You can add custom CSS to any Vizro dashboard, enabling users to deviate from the default styling and create a unique look and feel for their dashboard. - -* **[React.js customizations](#reactjs-customizations)**. You can add custom React.js components directly to any Vizro dashboard, enabling users to go beneath both the Vizro and Dash layers and control React.js directly +- **[CSS customizations](#css-customizations)**. You can add custom CSS to any Vizro dashboard, enabling users to deviate from the default styling and create a unique look and feel for their dashboard. +- **[React.js customizations](#reactjs-customizations)**. You can add custom React.js components directly to any Vizro dashboard, enabling users to go beneath both the Vizro and Dash layers and control React.js directly Vizro offers the ability to combine ease of use of low-code configuration, with the flexibility of a range of high-code extensions to expand your dashboard's functionality. - ## Vizro customizations ### [Custom charts](custom-charts.md) -You can create custom chart functions in Vizro by wrapping Plotly chart code inside a -Vizro chart function wrapper, and then use the functions directly inside the Vizro dashboard configuration. This enables the creation of `plotly.graph_objects` charts with multiple traces, or `plotly_express` charts with post update customizations - +You can create custom chart functions in Vizro by wrapping Plotly chart code inside a Vizro chart function wrapper, and then use the functions directly inside the Vizro dashboard configuration. This enables the creation of `plotly.graph_objects` charts with multiple traces, or `plotly_express` charts with post update customizations ### [Custom tables](custom-tables.md) If the available arguments for the [`dash_ag_grid`][vizro.tables.dash_ag_grid] or [`dash_data_table`][vizro.tables.dash_data_table] models are insufficient, you can create a custom Dash AG Grid or Dash DataTable. - ### [Custom components](custom-components.md) -You can create a custom component based on any dash-compatible component (for example, [dash-core-components](https://dash.plotly.com/dash-core-components), -[dash-bootstrap-components](https://dash-bootstrap-components.opensource.faculty.ai/), [dash-html-components](https://github.com/plotly/dash/tree/dev/components/dash-html-components)). +You can create a custom component based on any dash-compatible component (for example, [dash-core-components](https://dash.plotly.com/dash-core-components), [dash-bootstrap-components](https://dash-bootstrap-components.opensource.faculty.ai/), [dash-html-components](https://github.com/plotly/dash/tree/dev/components/dash-html-components)). All Vizro's components are based on `Dash` and ship with a set of defaults that can be modified. If you would like to overwrite one of those defaults, or if you would like to use extra `args` or `kwargs` of those components, then this is the correct way to include those. You can use any existing attribute of any underlying [Dash component](https://dash.plotly.com/#open-source-component-libraries) with this method. - ### [Custom actions](custom-actions.md) -If you want to use the [`Action`][vizro.models.Action] model to perform functions that are not available in the [pre-defined action functions][vizro.actions], you can create your own custom action. -Like other [actions](actions.md), custom actions can also be added as an element inside the [actions chain](actions.md#chain-actions), and triggered with one of dashboard components. - +If you want to use the [`Action`][vizro.models.Action] model to perform functions that are not available in the [pre-defined action functions][vizro.actions], you can create your own custom action. Like other [actions](actions.md), custom actions can also be added as an element inside the [actions chain](actions.md#chain-actions), and triggered with one of dashboard components. ### [Custom figures](custom-figures.md) -Custom figures are useful when you need a component that reacts to -[filter](filters.md) and [parameter](parameters.md) controls. - -Vizro's [`Figure`][vizro.models.Figure] model accepts the `figure` argument, where you can enter _any_ custom figure function -as described in the [how-to guide for figures](figure.md). +Custom figures are useful when you need a component that reacts to [filter](filters.md) and [parameter](parameters.md) controls. +Vizro's [`Figure`][vizro.models.Figure] model accepts the `figure` argument, where you can enter _any_ custom figure function as described in the [how-to guide for figures](figure.md). ## Dash customizations -Since Vizro is built using Dash, it is possible to use [Dash callbacks](https://dash.plotly.com/basic-callbacks) directly in any Vizro dashboard. This enables you to code beneath the Vizro layer and control Dash directly, -which is especially useful when working with callbacks +Since Vizro is built using Dash, it is possible to use [Dash callbacks](https://dash.plotly.com/basic-callbacks) directly in any Vizro dashboard. This enables you to code beneath the Vizro layer and control Dash directly, which is especially useful when working with callbacks -Here is an example showing a Dash callback within Vizro, -enabling an interaction between data points in a scatter plot and the content of a text card: +Here is an example showing a Dash callback within Vizro, enabling an interaction between data points in a scatter plot and the content of a text card: !!! example "Dash callback example" - === "app.py" ```{.python pycafe-link} from dash import callback, Input, Output @@ -93,14 +78,12 @@ enabling an interaction between data points in a scatter plot and the content of ## CSS customizations -Vizro is opinionated about visual formatting, and some elements, such as the layout of the navigation and controls, -are fixed. You can customize some settings such as background colors, fonts, and other styles via CSS overrides. +Vizro is opinionated about visual formatting, and some elements, such as the layout of the navigation and controls, are fixed. You can customize some settings such as background colors, fonts, and other styles via CSS overrides. For more information, see our documentation on [customizing CSS](custom-css.md) ## React.js customizations -It is possible to create custom React.js components and add them -directly to any Vizro dashboard so enabling you to code beneath both the Vizro and Dash layers and control React.js directly +It is possible to create custom React.js components and add them directly to any Vizro dashboard so enabling you to code beneath both the Vizro and Dash layers and control React.js directly For more information, see the documentation on [using React.js components with Dash](https://dash.plotly.com/plugins) diff --git a/vizro-core/docs/pages/user-guides/figure.md b/vizro-core/docs/pages/user-guides/figure.md index 0589fad3b..32a93d8d3 100644 --- a/vizro-core/docs/pages/user-guides/figure.md +++ b/vizro-core/docs/pages/user-guides/figure.md @@ -1,26 +1,19 @@ # How to use figures -This guide shows you how to add any [Dash component](https://dash.plotly.com/#open-source-component-libraries) that needs to be reactive to [filter](filters.md) and [parameter](parameters.md) controls. -If you want to add a static Dash component to your page, use [custom components](custom-components.md) instead. +This guide shows you how to add any [Dash component](https://dash.plotly.com/#open-source-component-libraries) that needs to be reactive to [filter](filters.md) and [parameter](parameters.md) controls. If you want to add a static Dash component to your page, use [custom components](custom-components.md) instead. -[`Figure`][vizro.models.Figure] provides a flexible foundation for all types of reactive Dash components in Vizro. -The [`Graph`][vizro.models.Graph], [`Table`][vizro.models.Table] and [`AgGrid`][vizro.models.AgGrid] components are -specific implementations of `Figure`. They serve as intuitive shortcuts, embedding behaviors and interactions specific -to their purposes. +[`Figure`][vizro.models.Figure] provides a flexible foundation for all types of reactive Dash components in Vizro. The [`Graph`][vizro.models.Graph], [`Table`][vizro.models.Table] and [`AgGrid`][vizro.models.AgGrid] components are specific implementations of `Figure`. They serve as intuitive shortcuts, embedding behaviors and interactions specific to their purposes. -If these more specific models already achieve what you need then they should be used in preference to -the more generic `Figure`. Remember that it is possible to supply [custom charts](custom-charts.md) to `Graph` -and [custom tables](custom-tables.md) to `Table`. +If these more specific models already achieve what you need then they should be used in preference to the more generic `Figure`. Remember that it is possible to supply [custom charts](custom-charts.md) to `Graph` and [custom tables](custom-tables.md) to `Table`. -There are already a few figure functions you can reuse, see the section on [KPI cards](#key-performance-indicator-kpi-cards) -for more details: +There are already a few figure functions you can reuse, see the section on [KPI cards](#key-performance-indicator-kpi-cards) for more details: - [`kpi_card`][vizro.figures.kpi_card] - [`kpi_card_reference`][vizro.figures.kpi_card_reference] The following flowchart shows what you need to consider when choosing which model to use: -``` mermaid +```mermaid graph TD first["`Does your desired component exist in Vizro, e.g. Graph, Table or AgGrid?`"] specific-component([Use the specific component]) @@ -40,14 +33,12 @@ graph TD classDef clickable color:#4051b5; ``` - To add a `Figure` to your page: 1. Add the `Figure` model to the components argument of the [Page][vizro.models.Page] model. -2. Use an existing figure function from [`vizro.figures`](../API-reference/figure-callables.md) and pass it to the `figure` argument of the `Figure` model. +1. Use an existing figure function from [`vizro.figures`](../API-reference/figure-callables.md) and pass it to the `figure` argument of the `Figure` model. !!! example "Use existing figure functions" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -99,40 +90,25 @@ To add a `Figure` to your page: selector: type: radio_items layout: - grid: - [ - [0, -1, -1, -1], - [-1, -1, -1, -1], - [-1, -1, -1, -1], - [-1, -1, -1, -1], - [-1, -1, -1, -1], - ] + grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], + [-1, -1, -1, -1]] title: KPI card ``` - === "Result" - [![Figure]][Figure] - - [Figure]: ../../assets/user_guides/figure/figure.png + === "Result" + [![Figure]][figure] ### Key Performance Indicator (KPI) cards -A KPI card is a dynamic card that can display a single value, but optionally, can also include a title, icon, and reference value. -It is a common visual component to display key metrics in a dashboard. Vizro supports two pre-defined KPI card functions: -- [`kpi_card`](../API-reference/figure-callables.md#vizro.figures.kpi_card): A KPI card that shows a single value found -by performing an aggregation function (by default, `sum`) over a specified column. -Required arguments are `data_frame` and `value_column`. +A KPI card is a dynamic card that can display a single value, but optionally, can also include a title, icon, and reference value. It is a common visual component to display key metrics in a dashboard. Vizro supports two pre-defined KPI card functions: -- [`kpi_card_with_reference`](../API-reference/figure-callables.md#vizro.figures.kpi_card_reference): A KPI card that shows a single value -and a delta comparison to a reference value found by performing an aggregation function (by default, `sum`) over the specified columns. -Required arguments are `data_frame`, `value_column` and `reference_column`. +- [`kpi_card`](../API-reference/figure-callables.md#vizro.figures.kpi_card): A KPI card that shows a single value found by performing an aggregation function (by default, `sum`) over a specified column. Required arguments are `data_frame` and `value_column`. -As described in the [API reference](../API-reference/figure-callables.md) and illustrated in the below example, these -functions have several arguments to customize your KPI cards. If you require a level of customization that is not -possible with the built-in functions then you can create a [custom figure](custom-figures.md). +- [`kpi_card_with_reference`](../API-reference/figure-callables.md#vizro.figures.kpi_card_reference): A KPI card that shows a single value and a delta comparison to a reference value found by performing an aggregation function (by default, `sum`) over the specified columns. Required arguments are `data_frame`, `value_column` and `reference_column`. -!!! example "KPI card variations" +As described in the [API reference](../API-reference/figure-callables.md) and illustrated in the below example, these functions have several arguments to customize your KPI cards. If you require a level of customization that is not possible with the built-in functions then you can create a [custom figure](custom-figures.md). +!!! example "KPI card variations" === "app.py" ```{.python pycafe-link} import pandas as pd @@ -258,8 +234,8 @@ possible with the built-in functions then you can create a [custom figure](custo value_column: Actual reference_column: Reference title: KPI reference with formatting - value_format: "{value:.2f}€" - reference_format: "{delta:+.2f}€ vs. last year ({reference:.2f}€)" + value_format: '{value:.2f}€' + reference_format: '{delta:+.2f}€ vs. last year ({reference:.2f}€)' type: figure - figure: _target_: kpi_card_reference @@ -276,7 +252,9 @@ possible with the built-in functions then you can create a [custom figure](custo grid: [[0, 1, 2, 3], [4, 5, 6, 7], [-1, -1, -1, -1], [-1, -1, -1, -1]] title: KPI cards ``` + === "Result" - [![KPICards]][KPICards] + [![KPICards]][kpicards] - [KPICards]: ../../assets/user_guides/figure/kpi_cards.png +[figure]: ../../assets/user_guides/figure/figure.png +[kpicards]: ../../assets/user_guides/figure/kpi_cards.png diff --git a/vizro-core/docs/pages/user-guides/filters.md b/vizro-core/docs/pages/user-guides/filters.md index e5dd2ed61..c73e04961 100644 --- a/vizro-core/docs/pages/user-guides/filters.md +++ b/vizro-core/docs/pages/user-guides/filters.md @@ -2,19 +2,16 @@ This guide shows you how to add filters to your dashboard. One main way to interact with the charts/components on your page is by filtering the underlying data. A filter selects a subset of rows of a component's underlying DataFrame which alters the appearance of that component on the page. -The [`Page`][vizro.models.Page] model accepts the `controls` argument, where you can enter a [`Filter`][vizro.models.Filter] model. -This model enables the automatic creation of [selectors](../user-guides/selectors.md) (such as Dropdown, RadioItems, Slider, ...) that operate upon the charts/components on the screen. - +The [`Page`][vizro.models.Page] model accepts the `controls` argument, where you can enter a [`Filter`][vizro.models.Filter] model. This model enables the automatic creation of [selectors](../user-guides/selectors.md) (such as Dropdown, RadioItems, Slider, ...) that operate upon the charts/components on the screen. ## Basic filters To add a filter to your page, do the following: 1. add the [`Filter`][vizro.models.Filter] model into the `controls` argument of the [`Page`][vizro.models.Page] model -2. configure the `column` argument, which denotes the target column to be filtered +1. configure the `column` argument, which denotes the target column to be filtered -By default, all components on a page with such a `column` present will be filtered. The selector type will be chosen -automatically based on the target column, for example, a dropdown for categorical data, a range slider for numerical data, or a date picker for temporal data. +By default, all components on a page with such a `column` present will be filtered. The selector type will be chosen automatically based on the target column, for example, a dropdown for categorical data, a range slider for numerical data, or a date picker for temporal data. !!! example "Basic Filter" === "app.py" @@ -39,6 +36,7 @@ automatically based on the target column, for example, a dropdown for categorica Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -57,16 +55,13 @@ automatically based on the target column, for example, a dropdown for categorica type: filter title: My first page ``` - === "Result" - [![Filter]][Filter] - - [Filter]: ../../assets/user_guides/control/control1.png + === "Result" + [![Filter]][filter] ## Changing selectors -If you want to have a different selector for your filter, you can give the `selector` argument of the [`Filter`][vizro.models.Filter] a different selector model. -Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropdown`][vizro.models.Dropdown], [`RadioItems`][vizro.models.RadioItems], [`RangeSlider`][vizro.models.RangeSlider], [`Slider`][vizro.models.Slider], and [`DatePicker`][vizro.models.DatePicker]. +If you want to have a different selector for your filter, you can give the `selector` argument of the [`Filter`][vizro.models.Filter] a different selector model. Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropdown`][vizro.models.Dropdown], [`RadioItems`][vizro.models.RadioItems], [`RangeSlider`][vizro.models.RangeSlider], [`Slider`][vizro.models.Slider], and [`DatePicker`][vizro.models.DatePicker]. !!! example "Filter with custom Selector" === "app.py" @@ -91,6 +86,7 @@ Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropd Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -110,11 +106,9 @@ Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropd type: filter title: My first page ``` - === "Result" - - [![Selector]][Selector] - [Selector]: ../../assets/user_guides/control/control2.png + === "Result" + [![Selector]][selector] ## Further customization @@ -150,6 +144,7 @@ Below is an advanced example where we only target one page component, and where Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -175,15 +170,17 @@ Below is an advanced example where we only target one page component, and where controls: - column: petal_length targets: - - scatter_chart + - scatter_chart selector: step: 1 type: range_slider type: filter title: My first page ``` - === "Result" - [![Advanced]][Advanced] + === "Result" + [![Advanced]][advanced] - [Advanced]: ../../assets/user_guides/control/control3.png +[advanced]: ../../assets/user_guides/control/control3.png +[filter]: ../../assets/user_guides/control/control1.png +[selector]: ../../assets/user_guides/control/control2.png diff --git a/vizro-core/docs/pages/user-guides/graph.md b/vizro-core/docs/pages/user-guides/graph.md index 36c670997..b0fedebb7 100755 --- a/vizro-core/docs/pages/user-guides/graph.md +++ b/vizro-core/docs/pages/user-guides/graph.md @@ -6,25 +6,18 @@ The [`Graph`][vizro.models.Graph] model is the most used component in many dashb To add a [`Graph`][vizro.models.Graph] to your page, do the following: -1. insert the [`Graph`][vizro.models.Graph] model into the `components` argument of the -[`Page`][vizro.models.Page] model -2. enter any of the currently available charts of the open source library [`plotly.express`](https://plotly.com/python/plotly-express/) into the `figure` argument +1. insert the [`Graph`][vizro.models.Graph] model into the `components` argument of the [`Page`][vizro.models.Page] model +1. enter any of the currently available charts of the open source library [`plotly.express`](https://plotly.com/python/plotly-express/) into the `figure` argument !!! note + In order to use the [`plotly.express`](https://plotly.com/python/plotly-express/) chart in a Vizro dashboard, you need to import it as `import vizro.plotly.express as px`. This leaves any of the [`plotly.express`](https://plotly.com/python/plotly-express/) functionality untouched, but allows _direct insertion_ into the [`Graph`][vizro.models.Graph] model _as is_. - In order to use the [`plotly.express`](https://plotly.com/python/plotly-express/) chart in a Vizro dashboard, you need to import it as `import vizro.plotly.express as px`. - This leaves any of the [`plotly.express`](https://plotly.com/python/plotly-express/) functionality untouched, but allows _direct insertion_ into the [`Graph`][vizro.models.Graph] model _as is_. - - Note also that the `plotly.express` chart needs to have a `data_frame` argument. In case you require a chart without - a `data_frame` argument (for example, the [`imshow` chart](https://plotly.com/python/imshow/)), refer to our - [guide on custom charts](custom-charts.md). - + Note also that the `plotly.express` chart needs to have a `data_frame` argument. In case you require a chart without a `data_frame` argument (for example, the [`imshow` chart](https://plotly.com/python/imshow/)), refer to our [guide on custom charts](custom-charts.md). ## Insert Plotly chart !!! example "Graph" === "app.py" - ```{.python pycafe-link} import vizro.models as vm import vizro.plotly.express as px @@ -47,25 +40,24 @@ To add a [`Graph`][vizro.models.Graph] to your page, do the following: Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: scatter_matrix - color: species - data_frame: iris - dimensions: ["sepal_length", "sepal_width", "petal_length", "petal_width"] - type: graph - title: My first page + - components: + - figure: + _target_: scatter_matrix + color: species + data_frame: iris + dimensions: [sepal_length, sepal_width, petal_length, petal_width] + type: graph + title: My first page ``` - === "Result" - [![Graph]][Graph] - - [Graph]: ../../assets/user_guides/components/graph.png + === "Result" + [![Graph]][graph] In the Python example we directly inserted the pandas DataFrame `df` into `figure=px.scatter_matrix(df, ...)`. This is [one way to supply data to a chart](data.md#supply-directly). For the YAML version, we [refer to the data source by name](data.md#reference-by-name) as `data_frame: iris`. For a full explanation of the different methods you can use to send data to your dashboard, see [our guide to using data in Vizro](data.md). @@ -73,31 +65,24 @@ In the Python example we directly inserted the pandas DataFrame `df` into `figur You will need to create a custom chart if you want to customize the Plotly chart beyond a function call, for example by: -* using post-update methods like `update_layout`, `update_xaxes`, `update_traces`, or -* by creating a custom `plotly.graph_objects.Figure()` object and manually adding traces with `add_trace`. - -For more details, refer to our [user guide on custom chart](custom-charts.md) and the -[Plotly documentation on updating figures](https://plotly.com/python/creating-and-updating-figures/). +- using post-update methods like `update_layout`, `update_xaxes`, `update_traces`, or +- by creating a custom `plotly.graph_objects.Figure()` object and manually adding traces with `add_trace`. +For more details, refer to our [user guide on custom chart](custom-charts.md) and the [Plotly documentation on updating figures](https://plotly.com/python/creating-and-updating-figures/). ## Add title, header, and footer -The [`Graph`][vizro.models.Graph] accepts a `title`, `header` and `footer` argument. This is useful for providing -context to the data being displayed, or for adding a description of the data. +The [`Graph`][vizro.models.Graph] accepts a `title`, `header` and `footer` argument. This is useful for providing context to the data being displayed, or for adding a description of the data. - **title**: Displayed as an [H3 header](https://dash.plotly.com/dash-html-components/h3), useful for summarizing the main topic or insight of the component. - **header**: Accepts markdown text, ideal for extra descriptions, subtitles, or detailed data insights. - **footer**: Accepts markdown text, commonly used for citing data sources, providing information on the last update, or adding disclaimers. - !!! note - - Although you can directly provide a `title` to the Plotly Express chart, we recommend using `Graph.title` for - proper alignment with other components on the screen. + Although you can directly provide a `title` to the Plotly Express chart, we recommend using `Graph.title` for proper alignment with other components on the screen. !!! example "Formatted Graph" === "app.py" - ```{.python pycafe-link} import vizro.models as vm @@ -126,31 +111,34 @@ context to the data being displayed, or for adding a description of the data. dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: scatter - x: sepal_width - y: sepal_length - color: species - data_frame: iris - title: Relationships between Sepal Width and Sepal Length - header: | - Each point in the scatter plot represents one of the 150 iris flowers, with colors indicating their - types. The Setosa type is easily identifiable by its short and wide sepals. - - However, there is still overlap between the Versicolor and Virginica types when considering only sepal - width and length. - footer: | - SOURCE: **Plotly iris data set, 2024** - type: graph - title: Formatted Graph + - components: + - figure: + _target_: scatter + x: sepal_width + y: sepal_length + color: species + data_frame: iris + title: Relationships between Sepal Width and Sepal Length + header: | + Each point in the scatter plot represents one of the 150 iris flowers, with colors indicating their + types. The Setosa type is easily identifiable by its short and wide sepals. + + However, there is still overlap between the Versicolor and Virginica types when considering only sepal + width and length. + footer: | + SOURCE: **Plotly iris data set, 2024** + type: graph + title: Formatted Graph ``` + === "Result" - [![FormattedGraph]][FormattedGraph] + [![FormattedGraph]][formattedgraph] - [FormattedGraph]: ../../assets/user_guides/components/formatted_graph.png +[formattedgraph]: ../../assets/user_guides/components/formatted_graph.png +[graph]: ../../assets/user_guides/components/graph.png diff --git a/vizro-core/docs/pages/user-guides/install.md b/vizro-core/docs/pages/user-guides/install.md index 4d4c01239..6a07911e5 100644 --- a/vizro-core/docs/pages/user-guides/install.md +++ b/vizro-core/docs/pages/user-guides/install.md @@ -8,8 +8,8 @@ We recommend that you create a virtual environment for each Vizro project you wo ## Prerequisites to working locally -* **Python**: Vizro supports macOS, Linux, and Windows. It works with Python 3.9 and later. -* **Virtual environment**: You specify the version of Python to use with Vizro when you set up the virtual environment. See the following references to learn more about [Python virtual environments](https://realpython.com/python-virtual-environments-a-primer/), [Conda virtual environments](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#starting-conda) or [watch an explainer video about them](https://youtu.be/YKfAwIItO7M). +- **Python**: Vizro supports macOS, Linux, and Windows. It works with Python 3.9 and later. +- **Virtual environment**: You specify the version of Python to use with Vizro when you set up the virtual environment. See the following references to learn more about [Python virtual environments](https://realpython.com/python-virtual-environments-a-primer/), [Conda virtual environments](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#starting-conda) or [watch an explainer video about them](https://youtu.be/YKfAwIItO7M). ### How to create a virtual environment for your Vizro project diff --git a/vizro-core/docs/pages/user-guides/kedro-data-catalog.md b/vizro-core/docs/pages/user-guides/kedro-data-catalog.md index 0e2b0954e..cda94d477 100644 --- a/vizro-core/docs/pages/user-guides/kedro-data-catalog.md +++ b/vizro-core/docs/pages/user-guides/kedro-data-catalog.md @@ -3,6 +3,7 @@ This page describes how to integrate Vizro with [Kedro](https://docs.kedro.org/en/stable/index.html), an open-source Python framework to create reproducible, maintainable, and modular data science code. For Pandas datasets registered in a Kedro data catalog, Vizro provides a convenient way to visualize them. ## Installation + If you already have Kedro installed then you do not need to install any extra dependencies. If you do not have Kedro installed then you should run: ```bash @@ -10,7 +11,9 @@ pip install vizro[kedro] ``` ## Use datasets from the Kedro Data Catalog + `vizro.integrations.kedro` provides functions to help generate and process a [Kedro Data Catalog](https://docs.kedro.org/en/stable/data/index.html). Given a Kedro Data Catalog `catalog`, the general pattern to add datasets into the Vizro data manager is: + ```python from vizro.integrations import kedro as kedro_integration from vizro.managers import data_manager @@ -25,13 +28,12 @@ This imports all datasets of type [`kedro_datasets.pandas`](https://docs.kedro.o The `catalog` variable may have been created in a number of different ways: 1. Kedro project path. Vizro exposes a helper function `vizro.integrations.kedro.catalog_from_project` to generate a `catalog` given the path to a Kedro project. -2. [Kedro Jupyter session](https://docs.kedro.org/en/stable/notebooks_and_ipython/kedro_and_notebooks.html). This automatically exposes `catalog`. -3. Data Catalog configuration file (`catalog.yaml`). This can create a `catalog` entirely independently of a Kedro project using [`kedro.io.DataCatalog.from_config`](https://docs.kedro.org/en/stable/kedro.io.DataCatalog.html#kedro.io.DataCatalog.from_config). +1. [Kedro Jupyter session](https://docs.kedro.org/en/stable/notebooks_and_ipython/kedro_and_notebooks.html). This automatically exposes `catalog`. +1. Data Catalog configuration file (`catalog.yaml`). This can create a `catalog` entirely independently of a Kedro project using [`kedro.io.DataCatalog.from_config`](https://docs.kedro.org/en/stable/kedro.io.DataCatalog.html#kedro.io.DataCatalog.from_config). The full code for these different cases is given below. !!! example "Import a Kedro Data Catalog into the Vizro data manager" - === "app.py (Kedro project path)" ```py from vizro.integrations import kedro as kedro_integration @@ -43,6 +45,7 @@ The full code for these different cases is given below. for dataset_name, dataset in kedro_integration.datasets_from_catalog(catalog).items(): data_manager[dataset_name] = dataset ``` + === "app.ipynb (Kedro Jupyter session)" ```py from vizro.managers import data_manager @@ -51,6 +54,7 @@ The full code for these different cases is given below. for dataset_name, dataset in kedro_integration.datasets_from_catalog(catalog).items(): data_manager[dataset_name] = dataset ``` + === "app.py (Data Catalog configuration file)" ```py from kedro.io import DataCatalog diff --git a/vizro-core/docs/pages/user-guides/layouts.md b/vizro-core/docs/pages/user-guides/layouts.md index 8361560db..b2fe500c1 100644 --- a/vizro-core/docs/pages/user-guides/layouts.md +++ b/vizro-core/docs/pages/user-guides/layouts.md @@ -3,11 +3,10 @@ The [`Page`][vizro.models.Page] model accepts a `layout` argument that enables custom arrangement of charts and components on the screen. This guide shows how to customize the grid specifications in the [`Layout`][vizro.models.Layout]. ## The default layout -The `layout` argument of the [`Page`][vizro.models.Page] model is optional. If no layout is specified, all charts/components are automatically [**stacked vertically**](layouts.md#vertical-and-horizontal-stacking) on the page in one column. -If you are happy with that arrangement, you can create your charts/components without providing a [`Layout`][vizro.models.Layout]. -!!! example "Default Layout" +The `layout` argument of the [`Page`][vizro.models.Page] model is optional. If no layout is specified, all charts/components are automatically [**stacked vertically**](layouts.md#vertical-and-horizontal-stacking) on the page in one column. If you are happy with that arrangement, you can create your charts/components without providing a [`Layout`][vizro.models.Layout]. +!!! example "Default Layout" === "app.py" ```{.python pycafe-link} from vizro import Vizro @@ -23,35 +22,33 @@ If you are happy with that arrangement, you can create your charts/components wi dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - # Component 0 - type: card - - text: | - # Component 1 - type: card - title: two_left + - components: + - text: | + # Component 0 + type: card + - text: | + # Component 1 + type: card + title: two_left ``` - === "Result" - [![Layout]][Layout] - - [Layout]: ../../assets/user_guides/layout/two_left.png - + === "Result" + [![Layout]][layout] ## Configure the grid + To customize the grid arrangement, configure the `grid` parameter of the [`Layout`][vizro.models.Layout] model. The example below shows an example of a valid `grid`: ```python title="Basic example" -grid = [[0, 1], - [0, 2]] +grid = [[0, 1], [0, 2]] ``` - The `grid` must be provided as `list[list[int]]` (for example, `grid = [[0, 1], [0, 2]]`). @@ -64,16 +61,12 @@ grid = [[0, 1], - The area spanned by a chart/component in the grid must be rectangular. - The grid can be arbitrarily large, allowing arbitrarily granular control of the grid. - ## Vertical and horizontal stacking + As described above, when no `Layout` is specified, components are presented **vertically** as a single-column stack. If you have three components, the default `Layout.grid` will be as follows, with three equally sized rows, each containing a component spanning the entire width: ```python title="Vertical stacking" -grid = [ - [0], - [1], - [2] - ] +grid = [[0], [1], [2]] ``` To present components **horizontally** in one row: @@ -89,8 +82,8 @@ This defines a single row that occupies the entire width and height, divided int ## Grid - basic example -!!! example "Grid Arrangement - Basic Example" +!!! example "Grid Arrangement - Basic Example" === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -109,39 +102,37 @@ This defines a single row that occupies the entire width and height, divided int dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - # Component 0 - type: card - - text: | - # Component 1 - type: card - - text: | - # Component 2 - type: card - layout: - grid: [[0, 1], [0, 2]] - title: one_left_two_right + - components: + - text: | + # Component 0 + type: card + - text: | + # Component 1 + type: card + - text: | + # Component 2 + type: card + layout: + grid: [[0, 1], [0, 2]] + title: one_left_two_right ``` - === "Result" - [![Grid]][Grid] - [Grid]: ../../assets/user_guides/layout/one_left_two_right.png + === "Result" + [![Grid]][grid] ## Grid - advanced example If you want to divide the grid into subgrids with finer control over these, you can use [`Containers`](container.md). See our section on [when to use `Containers` vs. `Page.layout`](container.md#when-to-use-containers) for more information. -The `Layout` provides full control over the arrangement of top-level components within a page, -allowing arbitrarily granular control of the grid by creating larger grids. +The `Layout` provides full control over the arrangement of top-level components within a page, allowing arbitrarily granular control of the grid by creating larger grids. !!! example "Grid Arrangement - Advanced Example" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -208,6 +199,7 @@ allowing arbitrarily granular control of the grid by creating larger grids. dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -260,44 +252,44 @@ allowing arbitrarily granular control of the grid by creating larger grids. grid: [[0, 1, 3, 4], [2, 2, 3, 4]] title: Custom Layout - Advanced Example ``` - === "Result" - [![GridAdv]][GridAdv] - [GridAdv]: ../../assets/user_guides/layout/grid_advanced.png + === "Result" + [![GridAdv]][gridadv] ## Custom layout examples + Here is a reference table of example layouts: + one row with one component, second row with two components stacked horizontally -| Layout needed | Grid | Code | -|--------------------------------|----------------------------|-------------------------------------------------------------------------------------| -| one component | layout=vm.Layout(grid=[[0]]) | `layout=vm.Layout(grid=[[0]])` | -| two horizontally stacked rows, each with one component | | `layout=vm.Layout(grid=[[0],[1]])` | -| one row with two components set horizontally | layout=vm.Layout(grid=[[0],[1]]) | `layout=vm.Layout(grid=[[0,1]])` | -| three horizontally stacked rows, each with one component | layout=vm.Layout(grid=[[0],[1],[2]] | `layout=vm.Layout(grid=[[0],[1],[2]])` or
`layout=None` | -| one row divided into two separate columns where the left column is one component and the right is two stacked components | layout=vm.Layout(grid=[[0,1],[0,2]]) | `layout=vm.Layout(grid=[[0,1],[0,2]])` | -| two rows with the top as a single component and the bottom divided into two components | layout=vm.Layout(grid=[[0,0],[1,2]]) | `layout=vm.Layout(grid=[[0,0],[1,2]])` | -| two rows with the top divided into two columns where each holds one component, and the bottom as a single component | layout=vm.Layout(grid=[[0,1],[2,2]]) | `layout=vm.Layout(grid=[[0,1],[2,2]])` | -| two columns where the left is a single component and the right is a set of three horizontally stacked components | layout=vm.Layout(grid=[[0,1],[0,2],[0,3]]) | `layout=vm.Layout(grid=[[0,1],[0,2],[0,3]])` | -| two rows where each row is two components | layout=vm.Layout(grid=[[0,1],[2,3]]) | `layout=vm.Layout(grid=[[0,1],[2,3]])` | -| two columns where the left is a set of three horizontally stacked components and the right is a single component | layout=vm.Layout(grid=[[0,3],[1,3],[2,3]]) | `layout=vm.Layout(grid=[[0,3],[1,3],[2,3]])` | -| two rows where the top is a single component and the bottom is three separate components | layout=vm.Layout(grid=[[0,0,0],[1,2,3]]) | `layout=vm.Layout(grid=[[0,0,0],[1,2,3]])` | -| two rows where the top is three separate components and the bottom is a single component | layout=vm.Layout(grid=[[0,1,2],[3,3,3]]) | `layout=vm.Layout(grid=[[0,1,2],[3,3,3]])` | +| Layout needed | Grid | Code | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| one component | layout=vm.Layout(grid=[[0]]) | `layout=vm.Layout(grid=[[0]])` | +| two horizontally stacked rows, each with one component | | `layout=vm.Layout(grid=[[0],[1]])` | +| one row with two components set horizontally | layout=vm.Layout(grid=[[0],[1]]) | `layout=vm.Layout(grid=[[0,1]])` | +| three horizontally stacked rows, each with one component | layout=vm.Layout(grid=[[0],[1],[2]] | `layout=vm.Layout(grid=[[0],[1],[2]])` or
`layout=None` | +| one row divided into two separate columns where the left column is one component and the right is two stacked components | layout=vm.Layout(grid=[[0,1],[0,2]]) | `layout=vm.Layout(grid=[[0,1],[0,2]])` | +| two rows with the top as a single component and the bottom divided into two components | layout=vm.Layout(grid=[[0,0],[1,2]]) | `layout=vm.Layout(grid=[[0,0],[1,2]])` | +| two rows with the top divided into two columns where each holds one component, and the bottom as a single component | layout=vm.Layout(grid=[[0,1],[2,2]]) | `layout=vm.Layout(grid=[[0,1],[2,2]])` | +| two columns where the left is a single component and the right is a set of three horizontally stacked components | layout=vm.Layout(grid=[[0,1],[0,2],[0,3]]) | `layout=vm.Layout(grid=[[0,1],[0,2],[0,3]])` | +| two rows where each row is two components | layout=vm.Layout(grid=[[0,1],[2,3]]) | `layout=vm.Layout(grid=[[0,1],[2,3]])` | +| two columns where the left is a set of three horizontally stacked components and the right is a single component | layout=vm.Layout(grid=[[0,3],[1,3],[2,3]]) | `layout=vm.Layout(grid=[[0,3],[1,3],[2,3]])` | +| two rows where the top is a single component and the bottom is three separate components | layout=vm.Layout(grid=[[0,0,0],[1,2,3]]) | `layout=vm.Layout(grid=[[0,0,0],[1,2,3]])` | +| two rows where the top is three separate components and the bottom is a single component | layout=vm.Layout(grid=[[0,1,2],[3,3,3]]) | `layout=vm.Layout(grid=[[0,1,2],[3,3,3]])` | ## Add empty sections to the grid + One approach to organize the dashboard's layout involves integrating empty sections by specifying `-1` within the grid layout. ```python title="Example" -grid = [[0, 1, -1], - [0, 2, -1]] +grid = [[0, 1, -1], [0, 2, -1]] ``` !!! example "Adding Empty Spaces" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -316,38 +308,38 @@ grid = [[0, 1, -1], dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - # Component 0 - type: card - - text: | - # Component 1 - type: card - - text: | - # Component 2 - type: card - layout: - grid: [[0, 1, -1], [0, 2, -1]] - title: Adding empty spaces + - components: + - text: | + # Component 0 + type: card + - text: | + # Component 1 + type: card + - text: | + # Component 2 + type: card + layout: + grid: [[0, 1, -1], [0, 2, -1]] + title: Adding empty spaces ``` - === "Result" - [![GridEmpty]][GridEmpty] - [GridEmpty]: ../../assets/user_guides/layout/layout_empty_spaces.png + === "Result" + [![GridEmpty]][gridempty] ## Control the scroll behavior + By default, the grid fits all charts/components on the screen. This can lead to distortions such that the chart/component looks squashed. To control the scroll behavior, you can specify the following: - `row_min_height`: Sets a chart/component's minimum height. Defaults to 0px. - `col_min_width`: Sets a chart/component's minimum width. Defaults to 0px. !!! example "Activate Scrolling" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -371,59 +363,63 @@ By default, the grid fits all charts/components on the screen. This can lead to dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - # Component 0 - type: card - - text: | - # Component 1 - type: card - - text: | - # Component 2 - type: card - - text: | - # Component 2 - type: card - - text: | - # Component 4 - type: card - - text: | - # Component 5 - type: card - - text: | - # Component 6 - type: card - - text: | - # Component 7 - type: card - layout: - grid: [[0], [1], [2], [3], [4], [5], [6], [7]] - row_min_height: 240px - title: Activate scrolling + - components: + - text: | + # Component 0 + type: card + - text: | + # Component 1 + type: card + - text: | + # Component 2 + type: card + - text: | + # Component 2 + type: card + - text: | + # Component 4 + type: card + - text: | + # Component 5 + type: card + - text: | + # Component 6 + type: card + - text: | + # Component 7 + type: card + layout: + grid: [[0], [1], [2], [3], [4], [5], [6], [7]] + row_min_height: 240px + title: Activate scrolling ``` - === "Result" - [![GridScroll]][GridScroll] - - [GridScroll]: ../../assets/user_guides/layout/grid_scroll.png + === "Result" + [![GridScroll]][gridscroll] ## Further customization -For further customization, such as changing the gap between row and column, refer to the -documentation of the [`Layout`][vizro.models.Layout] model. + +For further customization, such as changing the gap between row and column, refer to the documentation of the [`Layout`][vizro.models.Layout] model. ## Alternative layout approaches + In general, any arbitrarily granular layout can already be achieved using [`Page.layout`](layouts.md) alone and is our recommended approach if you want to arrange components on a page with consistent row and/or column spacing. !!! note "Alternative layout approaches: `Tabs` and `Containers`" - - [`Tabs`][vizro.models.Tabs] and [`Containers`][vizro.models.Container] provide an alternative approach to customize your page layout. - For example, if you want to have more granular control and break the overall page grid into subgrids, see our [user guide on Containers](container.md). + [`Tabs`][vizro.models.Tabs] and [`Containers`][vizro.models.Container] provide an alternative approach to customize your page layout. For example, if you want to have more granular control and break the overall page grid into subgrids, see our [user guide on Containers](container.md). If you want to display multiple containers on one page by putting them into the same screen space, and letting the user switch between them, see our [user guide on Tabs](tabs.md). ![tabs](../../assets/user_guides/components/tabs-info.png){ width="500" } + +[grid]: ../../assets/user_guides/layout/one_left_two_right.png +[gridadv]: ../../assets/user_guides/layout/grid_advanced.png +[gridempty]: ../../assets/user_guides/layout/layout_empty_spaces.png +[gridscroll]: ../../assets/user_guides/layout/grid_scroll.png +[layout]: ../../assets/user_guides/layout/two_left.png diff --git a/vizro-core/docs/pages/user-guides/navigation.md b/vizro-core/docs/pages/user-guides/navigation.md index 41c6bb9dc..75a661470 100644 --- a/vizro-core/docs/pages/user-guides/navigation.md +++ b/vizro-core/docs/pages/user-guides/navigation.md @@ -2,8 +2,7 @@ This guide shows you how to use and customize the navigation that appears on the left of your dashboard. -The [`Dashboard`][vizro.models.Dashboard] model accepts a `navigation` argument, where you can enter a [`Navigation`][vizro.models.Navigation] model. This enables you to group pages together and customize how they appear in your navigation. -The dashboard includes a collapsible side panel that users can minimize or expand by a button click. The collapse button, located in the top right corner of the side panel, is visible by default for user convenience. +The [`Dashboard`][vizro.models.Dashboard] model accepts a `navigation` argument, where you can enter a [`Navigation`][vizro.models.Navigation] model. This enables you to group pages together and customize how they appear in your navigation. The dashboard includes a collapsible side panel that users can minimize or expand by a button click. The collapse button, located in the top right corner of the side panel, is visible by default for user convenience. ## Use the default navigation @@ -56,8 +55,8 @@ By default, if the `navigation` argument is not specified, Vizro creates a navig type: graph title: My first page - components: - - text: My text here - type: card + - text: My text here + type: card title: My second page - components: - figure: @@ -69,10 +68,9 @@ By default, if the `navigation` argument is not specified, Vizro creates a navig type: graph title: My third page ``` - === "Result" - [![DefaultNavigation]][DefaultNavigation] - [DefaultNavigation]: ../../assets/user_guides/navigation/default_navigation.png + === "Result" + [![DefaultNavigation]][defaultnavigation] ## Include a subset of pages @@ -132,17 +130,15 @@ To include only some of your dashboard pages in your navigation then list them i - My first page - My second page ``` - === "Result" - [![OnlySomePages]][OnlySomePages] - [OnlySomePages]: ../../assets/user_guides/navigation/only_some_pages.png + === "Result" + [![OnlySomePages]][onlysomepages] ## Group pages You can also group your pages together by specifying `pages` as a dictionary: !!! example "Grouping pages" - === "snippet.py" ```py # page_1, page_2, page_3 defined as in default example @@ -154,7 +150,6 @@ You can also group your pages together by specifying `pages` as a dictionary: ``` === "app.py" - ```{.python pycafe-link} from vizro import Vizro import vizro.plotly.express as px @@ -187,6 +182,7 @@ You can also group your pages together by specifying `pages` as a dictionary: ) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -200,18 +196,15 @@ You can also group your pages together by specifying `pages` as a dictionary: Group B: - My third page ``` - === "Result" - [![GroupedNavigation]][GroupedNavigation] - - [GroupedNavigation]: ../../assets/user_guides/navigation/grouped_navigation.png + === "Result" + [![GroupedNavigation]][groupednavigation] ## Use a navigation bar with icons Another way to group together pages in the navigation is to use a [`NavBar`][vizro.models.NavBar] with icons. The simplest way to use this is to change the `nav_selector` specified in [`Navigation`][vizro.models.Navigation]: !!! example "Using `NavBar`" - === "snippet.py" ```py # page_1, page_2, page_3 defined as in default example @@ -223,8 +216,8 @@ Another way to group together pages in the navigation is to use a [`NavBar`][viz ) Vizro().build(dashboard).run() ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro import vizro.plotly.express as px @@ -276,14 +269,11 @@ Another way to group together pages in the navigation is to use a [`NavBar`][viz nav_selector: type: nav_bar ``` - === "Result" - [![NavBar]][NavBar] - - [NavBar]: ../../assets/user_guides/navigation/nav_bar.png + === "Result" + [![NavBar]][navbar] -Here, the first level of the navigation hierarchy ("Group A" and "Group B") is represented by an icon in a navigation bar, and the second level of the navigation (the pages) is represented by an accordion. -By default, the set of icons used are the [`filter` icons from the Google Material icons library](https://fonts.google.com/icons?icon.query=filter). The icon label ("Group A" and "Group B") appears as a tooltip on hovering over the icon. +Here, the first level of the navigation hierarchy ("Group A" and "Group B") is represented by an icon in a navigation bar, and the second level of the navigation (the pages) is represented by an accordion. By default, the set of icons used are the [`filter` icons from the Google Material icons library](https://fonts.google.com/icons?icon.query=filter). The icon label ("Group A" and "Group B") appears as a tooltip on hovering over the icon. ## Customize the navigation bar @@ -314,7 +304,6 @@ The same configuration for [grouping pages](#group-pages) applies inside a `NavL ``` === "app.py" - ```{.python pycafe-link} from vizro import Vizro import vizro.plotly.express as px @@ -375,10 +364,9 @@ The same configuration for [grouping pages](#group-pages) applies inside a `NavL Group B: - My third page ``` - === "Result" - [![AccordionInsideNavBar]][AccordionInsideNavBar] - [AccordionInsideNavBar]: ../../assets/user_guides/navigation/accordion_inside_nav_bar.png + === "Result" + [![AccordionInsideNavBar]][accordioninsidenavbar] You can alter the icons used by specifying the name of the icon in the [Google Material icons library](https://fonts.google.com/icons): @@ -402,8 +390,8 @@ You can alter the icons used by specifying the name of the icon in the [Google M ), ) ``` - === "app.py" + === "app.py" ```{.python pycafe-link} from vizro import Vizro import vizro.plotly.express as px @@ -468,7 +456,13 @@ You can alter the icons used by specifying the name of the icon in the [Google M pages: - My third page ``` - === "Result" - [![CustomIcons]][CustomIcons] - [CustomIcons]: ../../assets/user_guides/navigation/custom_icons.png + === "Result" + [![CustomIcons]][customicons] + +[accordioninsidenavbar]: ../../assets/user_guides/navigation/accordion_inside_nav_bar.png +[customicons]: ../../assets/user_guides/navigation/custom_icons.png +[defaultnavigation]: ../../assets/user_guides/navigation/default_navigation.png +[groupednavigation]: ../../assets/user_guides/navigation/grouped_navigation.png +[navbar]: ../../assets/user_guides/navigation/nav_bar.png +[onlysomepages]: ../../assets/user_guides/navigation/only_some_pages.png diff --git a/vizro-core/docs/pages/user-guides/pages.md b/vizro-core/docs/pages/user-guides/pages.md index 7ae944e9b..71e01e9f9 100644 --- a/vizro-core/docs/pages/user-guides/pages.md +++ b/vizro-core/docs/pages/user-guides/pages.md @@ -1,7 +1,6 @@ # How to use pages -This guide shows you how to add pages to your dashboard and customize the URL paths if needed. -A [`Page`][vizro.models.Page] lets you place and arrange your dashboard content (for example, chart/components, tables, and text) -and configure your dashboard interactions (such as filters and parameters). + +This guide shows you how to add pages to your dashboard and customize the URL paths if needed. A [`Page`][vizro.models.Page] lets you place and arrange your dashboard content (for example, chart/components, tables, and text) and configure your dashboard interactions (such as filters and parameters). The [`Dashboard`][vizro.models.Dashboard] model accepts the `pages` argument, where you can insert your [`Page`][vizro.models.Page]. @@ -10,19 +9,19 @@ The [`Dashboard`][vizro.models.Dashboard] model accepts the `pages` argument, wh A [`Page`][vizro.models.Page] is split up into four main containers: 1. The **navigation container** where you can customize your `navigation` (see [Dashboard](dashboard.md) and [Navigation](navigation.md) for more information). Note that the navigation container needs to be configured via the Dashboard. -2. The **control container** where you can add your `controls` (see [Filters](filters.md) or [Parameters](parameters.md)) to interact with the dashboard -3. The **page header** that contains the page title and the theme toggle switch button -4. The **component container** where you can add your [components](components.md) to visualize your data +1. The **control container** where you can add your `controls` (see [Filters](filters.md) or [Parameters](parameters.md)) to interact with the dashboard +1. The **page header** that contains the page title and the theme toggle switch button +1. The **component container** where you can add your [components](components.md) to visualize your data ![Page Container](../../assets/user_guides/pages/page_containers.png) To create and add a page to your dashboard, do the following steps: 1. Set a `title` for your [`Page`][vizro.models.Page] -2. Configure your `components`, see our guide on the [various options](components.md) -3. (optional) Configure your `controls` , see our guides on [Filters](filters.md) and [Parameters](parameters.md) -4. (optional) Configure your `layout` , see our guide on [Layouts](layouts.md) -5. (optional) Give a `description` of your `Page` to the app's [meta tags](https://metatags.io/) +1. Configure your `components`, see our guide on the [various options](components.md) +1. (optional) Configure your `controls` , see our guides on [Filters](filters.md) and [Parameters](parameters.md) +1. (optional) Configure your `layout` , see our guide on [Layouts](layouts.md) +1. (optional) Give a `description` of your `Page` to the app's [meta tags](https://metatags.io/) !!! example "Page" === "app.py" @@ -51,51 +50,47 @@ To create and add a page to your dashboard, do the following steps: Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: sunburst - path: ['continent', 'country'] - values: pop - color: lifeExp - data_frame: gapminder - id: sunburst - type: graph - controls: - - column: continent - targets: - - sunburst - type: filter - - selector: - options: ['lifeExp', 'pop'] - title: Color - type: radio_items - targets: - - sunburst.color - type: parameter - title: Page Title - description: "Longer description of the page content" + - components: + - figure: + _target_: sunburst + path: [continent, country] + values: pop + color: lifeExp + data_frame: gapminder + id: sunburst + type: graph + controls: + - column: continent + targets: [sunburst] + type: filter + - selector: + options: [lifeExp, pop] + title: Color + type: radio_items + targets: [sunburst.color] + type: parameter + title: Page Title + description: Longer description of the page content ``` - === "Result" - [![Page]][Page] - [Page]: ../../assets/user_guides/pages/page_sunburst.png + === "Result" + [![Page]][page] An accordion page selector is automatically added to your dashboard in the top-left of the control container for through the different pages. It will not be added if your dashboard consists of only one page. You can additionally navigate through the different pages by going directly to the relevant page URL (more details in next section). - ## Customize the page URL -By default, the page URL is automatically generated based on the `id` of the page. For example, if `id="This is my first page"` -the generated page URL will be `path=this-is-my-first-page`. You can then access the page via `localhost:/this-is-my-first-page`. -Note that the page `id` defaults to be the same as the page `title` if not set. -If you have multiple pages with the same `title` then you must assign a unique `id`. +By default, the page URL is automatically generated based on the `id` of the page. For example, if `id="This is my first page"` the generated page URL will be `path=this-is-my-first-page`. You can then access the page via `localhost:/this-is-my-first-page`. + +Note that the page `id` defaults to be the same as the page `title` if not set. If you have multiple pages with the same `title` then you must assign a unique `id`. The first page always has the URL prefix `/` assigned. A custom URL can, therefore, not be created for the first page. @@ -137,39 +132,40 @@ To customize the page URL, pass a valid URL name to the `path` argument of [`Pag Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - text: | - Commodi repudiandae consequuntur voluptatum. - type: card - title: Page 1 - - components: - - figure: - _target_: sunburst - path: ['continent', 'country'] - values: pop - color: lifeExp - data_frame: gapminder - id: sunburst - type: graph - controls: - - column: continent - targets: - - sunburst - type: filter - - selector: - options: ['lifeExp', 'pop'] - title: Color - type: radio_items - targets: - - sunburst.color - type: parameter - title: Page 2 - path: my-custom-url + - components: + - text: | + Commodi repudiandae consequuntur voluptatum. + type: card + title: Page 1 + - components: + - figure: + _target_: sunburst + path: [continent, country] + values: pop + color: lifeExp + data_frame: gapminder + id: sunburst + type: graph + controls: + - column: continent + targets: [sunburst] + type: filter + - selector: + options: [lifeExp, pop] + title: Color + type: radio_items + targets: [sunburst.color] + type: parameter + title: Page 2 + path: my-custom-url ``` You can now access the first page via `localhost:/` and the second page via `localhost:/my-custom-url`. + +[page]: ../../assets/user_guides/pages/page_sunburst.png diff --git a/vizro-core/docs/pages/user-guides/parameters.md b/vizro-core/docs/pages/user-guides/parameters.md index bb39a7a0c..c82707d4a 100644 --- a/vizro-core/docs/pages/user-guides/parameters.md +++ b/vizro-core/docs/pages/user-guides/parameters.md @@ -9,8 +9,8 @@ The [`Page`][vizro.models.Page] model accepts the `controls` argument, where you To add a parameter to your page, do the following: 1. add the [`Parameter`][vizro.models.Parameter] model into the `controls` argument of the [`Page`][vizro.models.Page] model. -2. add the `targets` argument -3. add a selector model to the `selector` argument. +1. add the `targets` argument +1. add a selector model to the `selector` argument. In the `targets` argument, you can specify the component and function argument that the parameter should be applied to in the form of `.` (for example, `scatter_chart.title`). @@ -48,6 +48,7 @@ Unlike for the [`Filter`][vizro.models.Filter] model, you also have to configure Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -64,18 +65,17 @@ Unlike for the [`Filter`][vizro.models.Filter] model, you also have to configure type: graph controls: - selector: - options: ["My scatter chart", "A better title!", "Another title..."] - multi: False + options: [My scatter chart, A better title!, Another title...] + multi: false type: dropdown targets: - scatter_chart.title type: parameter title: My first page ``` - === "Result" - [![Parameter]][Parameter] - [Parameter]: ../../assets/user_guides/control/control4.png + === "Result" + [![Parameter]][parameter] If you would like to pass `None` as a parameter and make a parameter optional, you can specify the string `"NONE"` in the `options` or `value` field. @@ -133,6 +133,7 @@ If you want to change nested parameters, you can specify the `targets` argument Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -146,7 +147,7 @@ If you want to change nested parameters, you can specify the `targets` argument y: sepal_length size: petal_length color: species - color_discrete_map: {"setosa": "#00b4ff", "versicolor": "#ff9222"} + color_discrete_map: {setosa: '#00b4ff', versicolor: '#ff9222'} id: scatter_chart type: graph - figure: @@ -155,23 +156,22 @@ If you want to change nested parameters, you can specify the `targets` argument x: sepal_width y: sepal_length color: species - color_discrete_map: {"setosa": "#00b4ff", "versicolor": "#ff9222"} + color_discrete_map: {setosa: '#00b4ff', versicolor: '#ff9222'} id: bar_chart type: graph controls: - selector: - options: ["#ff5267", "#3949ab"] + options: ['#ff5267', '#3949ab'] value: #3949ab - multi: False + multi: false type: dropdown - targets: ["scatter_chart.color_discrete_map.virginica", "bar_chart.color_discrete_map.virginica"] + targets: [scatter_chart.color_discrete_map.virginica, bar_chart.color_discrete_map.virginica] type: parameter title: My first page ``` - === "Result" - [![Nested]][Nested] - [Nested]: ../../assets/user_guides/control/control5.png + === "Result" + [![Nested]][nested] In the above example, the object passed to the function argument `color_discrete_map` is a dictionary which maps the different flower species to fixed colors (for example, `{"virginica":"blue"}`). In this case, only the value `blue` should be changed instead of the entire dictionary. This can be achieved by specifying a target as `scatter.color_discrete_map.virginica`. @@ -180,3 +180,6 @@ Note that in the above example, one parameter affects multiple targets. ## Dynamic data parameters If you use [dynamic data](data.md/#dynamic-data) that can be updated while the dashboard is running then you can pass parameters to the dynamic data function to alter the data loaded into your dashboard. For detailed instructions, refer to the section on [parametrized data loading](data.md/#parametrize-data-loading). + +[nested]: ../../assets/user_guides/control/control5.png +[parameter]: ../../assets/user_guides/control/control4.png diff --git a/vizro-core/docs/pages/user-guides/run.md b/vizro-core/docs/pages/user-guides/run.md index 29ada2935..d1b0710b4 100644 --- a/vizro-core/docs/pages/user-guides/run.md +++ b/vizro-core/docs/pages/user-guides/run.md @@ -15,7 +15,6 @@ Most of our examples have a link below the code, [Run and edit this code in PyCa You can use [PyCafe](https://py.cafe/snippet/vizro/v1) snippet mode to experiment with your own Vizro dashboards by dropping code into a new project. - ## Default built-in Flask development server !!! example "Default built-in Flask development server" @@ -38,9 +37,10 @@ You can use [PyCafe](https://py.cafe/snippet/vizro/v1) snippet mode to experimen Vizro().build(dashboard).run() ``` + 1. create a Python file named `app.py`. -2. type the command `python app.py` into your terminal. -3. information below will be displayed in your terminal, go to [http://127.0.0.1:8050/](http://127.0.0.1:8050/). +1. type the command `python app.py` into your terminal. +1. information below will be displayed in your terminal, go to [http://127.0.0.1:8050/](http://127.0.0.1:8050/). ``` Dash is running on http://127.0.0.1:8050/ @@ -51,7 +51,6 @@ INFO:werkzeug:WARNING: This is a development server. Do not use it in a producti ``` !!! warning "In production" - As per the above warning message, which is [further explained in the Flask documentation](https://flask.palletsprojects.com/en/3.0.x/deploying/), the Flask development server is intended for use only during local development and **should not** be used when deploying to production. Instead, you should instead use a production-ready solution such as [Gunicorn](#gunicorn). ### Automatic reloading and debugging @@ -64,11 +63,11 @@ Setting `debug=True` enables [Dash Dev Tools](https://dash.plotly.com/devtools). In addition, some errors generated at run time can also be viewed via the browser console (for example in `Chrome` see `View > Developer > Developer Tools > Console`). - ## Jupyter + The dashboard application can be launched in a Jupyter environment in `inline`, `external`, and `jupyterlab` mode. -!!! example "Run in a Jupyter Notebook in inline mode" +!!! example "Run in a Jupyter Notebook in inline mode" === "app.ipynb" ```py linenums="1" from vizro import Vizro @@ -87,16 +86,16 @@ The dashboard application can be launched in a Jupyter environment in `inline`, dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run(jupyter_mode="external") ``` + - by default, the mode is set to `inline` in `run()` and the dashboard will be displayed inside your Jupyter environment. - you can specify `jupyter_mode="external"` and a link will be displayed to direct you to the localhost where the dashboard is running. - you can use tab mode by `jupyter_mode="tab"` to automatically open the app in a new browser !!! note "Reloading and debugging" - Code reloading and hot reloading do not work within a Jupyter Notebook. Instead, there are two methods to reload the dashboard: - * Restart the Jupyter kernel and re-run your notebook. - * Add a cell containing `from vizro import Vizro; Vizro._reset()` to the top of your notebook and re-run it. With this method, there is no need to restart the Jupyter kernel. + - Restart the Jupyter kernel and re-run your notebook. + - Add a cell containing `from vizro import Vizro; Vizro._reset()` to the top of your notebook and re-run it. With this method, there is no need to restart the Jupyter kernel. ## Gunicorn @@ -126,16 +125,17 @@ The dashboard application can be launched in a Jupyter environment in `inline`, ``` 1. The Vizro `app` object is a WSGI application that exposes the underlying Flask app; this will be used by Gunicorn. - 2. Enable the same app to still be run using the built-in Flask server with `python app.py` for development purposes. + 1. Enable the same app to still be run using the built-in Flask server with `python app.py` for development purposes. To run using Gunicorn with four worker processes, execute + ```bash gunicorn app:app --workers 4 ``` + in the command line. For more Gunicorn configuration options, refer to [Gunicorn documentation](https://docs.gunicorn.org/). !!! warning "In production" - If your dashboard uses [dynamic data](data.md#dynamic-data) that can be refreshed while the dashboard is running then you should [configure your data manager cache](data.md#configure-cache) to use a backend that supports multiple processes. ## Deployment diff --git a/vizro-core/docs/pages/user-guides/selectors.md b/vizro-core/docs/pages/user-guides/selectors.md index 944515ab6..8b81b6fb7 100644 --- a/vizro-core/docs/pages/user-guides/selectors.md +++ b/vizro-core/docs/pages/user-guides/selectors.md @@ -6,10 +6,7 @@ The [`Filter`][vizro.models.Filter] or the [`Parameter`][vizro.models.Parameter] ## Categorical selectors -Within the categorical selectors, a clear distinction exists between multi-option and single-option selectors. -For instance, the [`Checklist`][vizro.models.Checklist] functions as a multi-option selector by default while -the [`RadioItem`][vizro.models.RadioItems] serves as a single-option selector by default. However, the -[`Dropdown`][vizro.models.Dropdown] can function as both a multi-option or single-option selector. +Within the categorical selectors, a clear distinction exists between multi-option and single-option selectors. For instance, the [`Checklist`][vizro.models.Checklist] functions as a multi-option selector by default while the [`RadioItem`][vizro.models.RadioItems] serves as a single-option selector by default. However, the [`Dropdown`][vizro.models.Dropdown] can function as both a multi-option or single-option selector. For more information, refer to the API reference of the selector, or the documentation of its underlying Dash component: @@ -18,15 +15,12 @@ For more information, refer to the API reference of the selector, or the documen - [`RadioItems`][vizro.models.RadioItems] based on [`dcc.RadioItems`](https://dash.plotly.com/dash-core-components/radioitems) !!! note - When configuring the `options` of the categorical selectors, you can either provide: - a list of values `options = ['Value A', 'Value B', 'Value C']` - or a dictionary of label-value mappings `options=[{'label': 'True', 'value': True}, {'label': 'False', 'value': False}]` - The later is required if you want to provide different display labels to your option values or in case you want to - provide boolean values as options. In this case, you need to provide a string label for your boolean values as - boolean values cannot be displayed properly as labels in the underlying Dash components. + The later is required if you want to provide different display labels to your option values or in case you want to provide boolean values as options. In this case, you need to provide a string label for your boolean values as boolean values cannot be displayed properly as labels in the underlying Dash components. ## Numerical selectors @@ -36,11 +30,7 @@ For more information, refer to the API reference of the selector, or the documen - [`RangeSlider`][vizro.models.RangeSlider] based on [`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider) !!! note - - When configuring the [`Slider`][vizro.models.Slider] and the [`RangeSlider`][vizro.models.RangeSlider] with float values, and using `step` with an integer value, you may notice - unexpected behavior, such as the drag value being outside its indicated marks. - To our knowledge, this is a current bug in the underlying [`dcc.Slider`](https://dash.plotly.com/dash-core-components/slider) and - [`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider) component, which you can circumvent by adapting the `step` size accordingly. + When configuring the [`Slider`][vizro.models.Slider] and the [`RangeSlider`][vizro.models.RangeSlider] with float values, and using `step` with an integer value, you may notice unexpected behavior, such as the drag value being outside its indicated marks. To our knowledge, this is a current bug in the underlying [`dcc.Slider`](https://dash.plotly.com/dash-core-components/slider) and [`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider) component, which you can circumvent by adapting the `step` size accordingly. ## Temporal selectors @@ -49,7 +39,6 @@ For more information, refer to the API reference of the selector, or the documen - [`DatePicker`][vizro.models.DatePicker] based on [`dmc.DateRangePicker`](https://www.dash-mantine-components.com/components/datepicker#daterangepicker) and [`dmc.DatePicker`](https://www.dash-mantine-components.com/components/datepicker) !!! note - When the [`DatePicker`][vizro.models.DatePicker] is configured with `range=True` (the default), the underlying component is `dmc.DateRangePicker`. When `range=False` the underlying component is `dmc.DatePicker`. When configuring the [`DatePicker`][vizro.models.DatePicker] make sure to provide your dates for `min`, `max` and `value` arguments in `"yyyy-mm-dd"` format or as `datetime` type (for example, `datetime.datetime(2024, 01, 01)`). @@ -60,21 +49,18 @@ If you don't specify a selector, a default selector is applied based on the data Default selectors for: - - categorical data: [`Dropdown`][vizro.models.Dropdown] - - numerical data: [`RangeSlider`][vizro.models.RangeSlider] - - temporal data: [`DatePicker(range=True)`][vizro.models.DatePicker] +- categorical data: [`Dropdown`][vizro.models.Dropdown] +- numerical data: [`RangeSlider`][vizro.models.RangeSlider] +- temporal data: [`DatePicker(range=True)`][vizro.models.DatePicker] Categorical selectors can be used independently of the data type of the column being filtered. -To use numerical [`Filter`][vizro.models.Filter] selectors, the filtered column must be of `numeric` format, -indicating that [pandas.api.types.is_numeric_dtype()](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_numeric_dtype.html) must return `True` for the filtered column. +To use numerical [`Filter`][vizro.models.Filter] selectors, the filtered column must be of `numeric` format, indicating that [pandas.api.types.is_numeric_dtype()](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_numeric_dtype.html) must return `True` for the filtered column. -To use temporal [`Filter`][vizro.models.Filter] selectors, the filtered column must be of `datetime` format, -indicating that [pandas.api.types.is_datetime64_any_dtype()](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_datetime64_any_dtype.html) must return `True` for the filtered column. +To use temporal [`Filter`][vizro.models.Filter] selectors, the filtered column must be of `datetime` format, indicating that [pandas.api.types.is_datetime64_any_dtype()](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_datetime64_any_dtype.html) must return `True` for the filtered column. `pd.DataFrame` column types can be changed to `datetime` using [pandas.to_datetime()](https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html) or - ### Example of default Filter selectors !!! example "Default Filter selectors" @@ -113,6 +99,7 @@ indicating that [pandas.api.types.is_datetime64_any_dtype()](https://pandas.pyda Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -135,10 +122,10 @@ indicating that [pandas.api.types.is_datetime64_any_dtype()](https://pandas.pyda type: filter title: My first page ``` - === "Result" - [![Filter]][Filter] - - [Filter]: ../../assets/user_guides/selectors/default_filter_selectors.png + === "Result" + [![Filter]][filter] To enhance existing selectors, see our [how-to-guide on creating custom components](custom-components.md). + +[filter]: ../../assets/user_guides/selectors/default_filter_selectors.png diff --git a/vizro-core/docs/pages/user-guides/table.md b/vizro-core/docs/pages/user-guides/table.md index 19197c465..80e8e53dc 100755 --- a/vizro-core/docs/pages/user-guides/table.md +++ b/vizro-core/docs/pages/user-guides/table.md @@ -2,46 +2,32 @@ This guide shows you how to visualize tables in Vizro. -There are two ways to visualize tables in Vizro, using either [AG Grid](#ag-grid) or [Dash DataTable](#dash-datatable). -In general, [AG Grid](#ag-grid) is Vizro's recommended table implementation, but sometimes it may make sense to use the [Dash DataTable](#dash-datatable) instead. +There are two ways to visualize tables in Vizro, using either [AG Grid](#ag-grid) or [Dash DataTable](#dash-datatable). In general, [AG Grid](#ag-grid) is Vizro's recommended table implementation, but sometimes it may make sense to use the [Dash DataTable](#dash-datatable) instead. ## Choose between AG Grid and Dash DataTable -Vizro offers two models - the [`AgGrid`][vizro.models.AgGrid] model and the [`Table`][vizro.models.Table] model - for the above two approaches respectively. -They both visualize tabular data in similar ways. +Vizro offers two models - the [`AgGrid`][vizro.models.AgGrid] model and the [`Table`][vizro.models.Table] model - for the above two approaches respectively. They both visualize tabular data in similar ways. -The main difference between the two is that the [`AgGrid`][vizro.models.AgGrid] model is based on Plotly's [Dash AG Grid](https://dash.plotly.com/dash-ag-grid) component, -while the [`Table`][vizro.models.Table] model is based on the [Dash DataTable](https://dash.plotly.com/datatable) component. - -Both approaches have similar base features, and are configurable in similar ways. However, the AG Grid offers more advanced features out-of-the-box, is more customizable -and also ships a powerful enterprise version. This is why it is Vizro's recommended table implementation. At the same time, the Dash DataTable can be used if developers are -already familiar with it, or if some custom functionality is easier to implement using the Dash DataTable. +The main difference between the two is that the [`AgGrid`][vizro.models.AgGrid] model is based on Plotly's [Dash AG Grid](https://dash.plotly.com/dash-ag-grid) component, while the [`Table`][vizro.models.Table] model is based on the [Dash DataTable](https://dash.plotly.com/datatable) component. +Both approaches have similar base features, and are configurable in similar ways. However, the AG Grid offers more advanced features out-of-the-box, is more customizable and also ships a powerful enterprise version. This is why it is Vizro's recommended table implementation. At the same time, the Dash DataTable can be used if developers are already familiar with it, or if some custom functionality is easier to implement using the Dash DataTable. ## AG Grid -[AG Grid](https://www.ag-grid.com/) is an interactive table/grid component designed for viewing, editing, and exploring large datasets. It -is Vizro's recommended table implementation. +[AG Grid](https://www.ag-grid.com/) is an interactive table/grid component designed for viewing, editing, and exploring large datasets. It is Vizro's recommended table implementation. -The Vizro [`AgGrid`][vizro.models.AgGrid] model is based on the [Dash AG Grid](https://dash.plotly.com/dash-ag-grid), which is in turn based the -original [Javascript implementation](https://www.ag-grid.com/). +The Vizro [`AgGrid`][vizro.models.AgGrid] model is based on the [Dash AG Grid](https://dash.plotly.com/dash-ag-grid), which is in turn based the original [Javascript implementation](https://www.ag-grid.com/). ### Basic usage To add a [`AgGrid`][vizro.models.AgGrid] to your page, do the following: -1. Insert the [`AgGrid`][vizro.models.AgGrid] model into the `components` argument of the -[`Page`][vizro.models.Page] model. -2. Enter the `dash_ag_grid` function under the `figure` argument (imported via `from vizro.tables import dash_ag_grid`). - -The Vizro version of this AG Grid differs in one way from the original Dash AG Grid: it requires the user to pass a pandas DataFrame as the source of data. -As explained in [our guide to using data in Vizro](data.md), this must be entered under the argument `data_frame`. Most other [parameters of the Dash AG Grid](https://dash.plotly.com/dash-ag-grid/reference) can be entered as keyword arguments. -Note that some defaults are set for some arguments (for example, for `columnDefs`) to help with styling and usability. -Sometimes a parameter may not work because it requires a callback to function. In that case you can try [creating a custom AG Grid callable](custom-tables.md). +1. Insert the [`AgGrid`][vizro.models.AgGrid] model into the `components` argument of the [`Page`][vizro.models.Page] model. +1. Enter the `dash_ag_grid` function under the `figure` argument (imported via `from vizro.tables import dash_ag_grid`). +The Vizro version of this AG Grid differs in one way from the original Dash AG Grid: it requires the user to pass a pandas DataFrame as the source of data. As explained in [our guide to using data in Vizro](data.md), this must be entered under the argument `data_frame`. Most other [parameters of the Dash AG Grid](https://dash.plotly.com/dash-ag-grid/reference) can be entered as keyword arguments. Note that some defaults are set for some arguments (for example, for `columnDefs`) to help with styling and usability. Sometimes a parameter may not work because it requires a callback to function. In that case you can try [creating a custom AG Grid callable](custom-tables.md). !!! example "Basic Dash AG Grid" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -59,29 +45,28 @@ Sometimes a parameter may not work because it requires a callback to function. I Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - figure: - _target_: dash_ag_grid - data_frame: gapminder - type: ag_grid - title: Default Dash AG Grid + - components: + - figure: + _target_: dash_ag_grid + data_frame: gapminder + type: ag_grid + title: Default Dash AG Grid ``` - === "Result" - [![AGGrid]][AGGrid] - [AGGrid]: ../../assets/user_guides/table/aggrid.png + === "Result" + [![AGGrid]][aggrid] ### Enable pagination -Pagination is a visual alternative to using vertical scroll. It can also improve loading time if you have many rows. -You can turn it on by setting `dashGridOptions={"pagination": True}`. -!!! example "Basic Dash AG Grid" +Pagination is a visual alternative to using vertical scroll. It can also improve loading time if you have many rows. You can turn it on by setting `dashGridOptions={"pagination": True}`. +!!! example "Basic Dash AG Grid" === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -99,37 +84,34 @@ You can turn it on by setting `dashGridOptions={"pagination": True}`. Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - figure: - _target_: dash_ag_grid - data_frame: gapminder - dashGridOptions: - pagination: true - type: ag_grid - title: Dash AG Grid with pagination + - components: + - figure: + _target_: dash_ag_grid + data_frame: gapminder + dashGridOptions: + pagination: true + type: ag_grid + title: Dash AG Grid with pagination ``` - === "Result" - [![AGGrid]][AGGrid] - [AGGrid]: ../../assets/user_guides/table/aggrid-pagination.png + === "Result" + [![AGGrid]][aggrid] ### Formatting columns #### Numbers -One of the most common tasks when working with tables is to format the columns so that displayed numbers are more readable. -To do this, you can use the native functionality of [value formatters](https://dash.plotly.com/dash-ag-grid/value-formatters) -or the Vizro pre-defined [custom cell data types](https://dash.plotly.com/dash-ag-grid/cell-data-types#providing-custom-cell-data-types) as shown below. +One of the most common tasks when working with tables is to format the columns so that displayed numbers are more readable. To do this, you can use the native functionality of [value formatters](https://dash.plotly.com/dash-ag-grid/value-formatters) or the Vizro pre-defined [custom cell data types](https://dash.plotly.com/dash-ag-grid/cell-data-types#providing-custom-cell-data-types) as shown below. The available custom cell types for Vizro are `dollar`, `euro`, `percent` and `numeric`. -To use these, define your desired `` alongside the chosen `cellDataType` in -the `columnDefs` argument of your `dash_ag_grid` function: +To use these, define your desired `` alongside the chosen `cellDataType` in the `columnDefs` argument of your `dash_ag_grid` function: ```py columnDefs = [{"field": "", "cellDataType": "euro"}] @@ -138,7 +120,6 @@ columnDefs = [{"field": "", "cellDataType": "euro"}] In the example below we select and format some columns of the gapminder data. !!! example "AG Grid with formatted columns" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -168,6 +149,7 @@ In the example below we select and format some columns of the gapminder data. Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -190,33 +172,23 @@ In the example below we select and format some columns of the gapminder data. type: ag_grid title: Example of AG Grid with formatted columns ``` - === "Result" - [![AGGrid2]][AGGrid2] - [AGGrid2]: ../../assets/user_guides/table/formatted_aggrid.png + === "Result" + [![AGGrid2]][aggrid2] #### Dates -For the [`AgGrid`][vizro.models.AgGrid] model to sort and filter dates correctly, the date must either be of -string format `yyyy-mm-dd` (see [Dash AG Grid docs](https://dash.plotly.com/dash-ag-grid/date-filters#example:-date-filter)) -or a pandas datetime object. Any pandas datetime column will be transformed into the `yyyy-mm-dd` format automatically. +For the [`AgGrid`][vizro.models.AgGrid] model to sort and filter dates correctly, the date must either be of string format `yyyy-mm-dd` (see [Dash AG Grid docs](https://dash.plotly.com/dash-ag-grid/date-filters#example:-date-filter)) or a pandas datetime object. Any pandas datetime column will be transformed into the `yyyy-mm-dd` format automatically. #### Objects and strings -No specific formatting is available for custom objects and strings, however you can make use of [Value Formatters](https://dash.plotly.com/dash-ag-grid/value-formatters) -to format displayed strings automatically. - +No specific formatting is available for custom objects and strings, however you can make use of [Value Formatters](https://dash.plotly.com/dash-ag-grid/value-formatters) to format displayed strings automatically. ### Styling and changing the AG Grid -As mentioned above, all [parameters of the Dash AG Grid](https://dash.plotly.com/dash-ag-grid/reference) can be entered as keyword arguments. Below you can find -an example of a styled AG Grid where some conditional formatting is applied, and where the columns are editable, but -not filterable or resizable. There are more ways to alter the grid beyond this showcase. AG Grid, like any other Vizro -component, can be customized using custom CSS. You can find information in -the [guide to overwriting CSS properties](custom-css.md#overwrite-css-for-selected-components). +As mentioned above, all [parameters of the Dash AG Grid](https://dash.plotly.com/dash-ag-grid/reference) can be entered as keyword arguments. Below you can find an example of a styled AG Grid where some conditional formatting is applied, and where the columns are editable, but not filterable or resizable. There are more ways to alter the grid beyond this showcase. AG Grid, like any other Vizro component, can be customized using custom CSS. You can find information in the [guide to overwriting CSS properties](custom-css.md#overwrite-css-for-selected-components). !!! example "Styled and modified Dash AG Grid" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -284,6 +256,7 @@ the [guide to overwriting CSS properties](custom-css.md#overwrite-css-for-select Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -299,28 +272,28 @@ the [guide to overwriting CSS properties](custom-css.md#overwrite-css-for-select - field: year - field: lifeExp valueFormatter: - function: "d3.format('.1f')(params.value)" + function: d3.format('.1f')(params.value) - field: gdpPercap valueFormatter: - function: "d3.format('$,.1f')(params.value)" + function: d3.format('$,.1f')(params.value) cellStyle: styleConditions: - condition: params.value < 1045 style: - backgroundColor: "#ff9222" + backgroundColor: '#ff9222' - condition: params.value >= 1045 && params.value <= 4095 style: - backgroundColor: "#de9e75" + backgroundColor: '#de9e75' - condition: params.value > 4095 && params.value <= 12695 style: - backgroundColor: "#aaa9ba" + backgroundColor: '#aaa9ba' - condition: params.value > 12695 style: - backgroundColor: "#00b4ff" + backgroundColor: '#00b4ff' - field: pop type: rightAligned valueFormatter: - function: "d3.format(',.0f')(params.value)" + function: d3.format(',.0f')(params.value) defaultColDef: resizable: false filter: false @@ -329,10 +302,9 @@ the [guide to overwriting CSS properties](custom-css.md#overwrite-css-for-select type: ag_grid title: Example of a Dash AG Grid ``` - === "Result" - [![AGGrid3]][AGGrid3] - [AGGrid3]: ../../assets/user_guides/table/styled_aggrid.png + === "Result" + [![AGGrid3]][aggrid3] If the available arguments are not sufficient, there is always the option to [create a custom AG Grid callable](custom-tables.md). @@ -348,19 +320,14 @@ The Vizro [`Table`][vizro.models.Table] model is based on the [Dash DataTable](h To add a [`Table`][vizro.models.Table] to your page, do the following: -1. Insert the [`Table`][vizro.models.Table] model into the `components` argument of the -[`Page`][vizro.models.Page] model. -2. Enter the `dash_data_table` function under the `figure` argument (imported via `from vizro.tables import dash_data_table`). - +1. Insert the [`Table`][vizro.models.Table] model into the `components` argument of the [`Page`][vizro.models.Page] model. +1. Enter the `dash_data_table` function under the `figure` argument (imported via `from vizro.tables import dash_data_table`). -The Vizro version of this table differs in one way from the original table: it requires the user to pass a pandas DataFrame as the source of data. -As explained in [our guide to using data in Vizro](data.md), this must be entered under the argument `data_frame`. +The Vizro version of this table differs in one way from the original table: it requires the user to pass a pandas DataFrame as the source of data. As explained in [our guide to using data in Vizro](data.md), this must be entered under the argument `data_frame`. -All other [parameters of the Dash DataTable](https://dash.plotly.com/datatable/reference) can be entered as keyword arguments. Note that we are -setting some defaults for some arguments to help with styling. +All other [parameters of the Dash DataTable](https://dash.plotly.com/datatable/reference) can be entered as keyword arguments. Note that we are setting some defaults for some arguments to help with styling. !!! example "Dash DataTable" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -380,31 +347,29 @@ setting some defaults for some arguments to help with styling. Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: dash_data_table - data_frame: gapminder_2007 - title: Dash DataTable - type: table - title: Example of a Dash DataTable + - components: + - figure: + _target_: dash_data_table + data_frame: gapminder_2007 + title: Dash DataTable + type: table + title: Example of a Dash DataTable ``` - === "Result" - [![Table]][Table] - [Table]: ../../assets/user_guides/table/table.png + === "Result" + [![Table]][table] ### Styling and changing the Dash DataTable -As mentioned above, all [parameters of the Dash DataTable](https://dash.plotly.com/datatable/reference) can be entered as keyword arguments. Below you can find -an example of a styled table where some conditional formatting is applied. There are many more ways to alter the table beyond this showcase. +As mentioned above, all [parameters of the Dash DataTable](https://dash.plotly.com/datatable/reference) can be entered as keyword arguments. Below you can find an example of a styled table where some conditional formatting is applied. There are many more ways to alter the table beyond this showcase. !!! example "Styled Dash DataTable" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -467,6 +432,7 @@ an example of a styled table where some conditional formatting is applied. There Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -504,12 +470,12 @@ an example of a styled table where some conditional formatting is applied. There backgroundColor: dodgerblue color: white - if: - filter_query: "{lifeExp} < 55" + filter_query: '{lifeExp} < 55' column_id: lifeExp - backgroundColor: "#85144b" + backgroundColor: '#85144b' color: white - if: - filter_query: "{gdpPercap} > 10000" + filter_query: '{gdpPercap} > 10000' column_id: gdpPercap backgroundColor: green color: white @@ -524,26 +490,20 @@ an example of a styled table where some conditional formatting is applied. There title: Dash DataTable ``` - === "Result" - [![Table2]][Table2] - [Table2]: ../../assets/user_guides/table/styled_table.png + === "Result" + [![Table2]][table2] If the available arguments are not sufficient, there is always the option to create a [custom Dash DataTable](custom-tables.md). - ## Add title, header, and footer -The [`Table`][vizro.models.Table] and the [`AgGrid`][vizro.models.AgGrid] models accept a `title`, `header` and -`footer` argument. This is useful for providing context to the data being displayed, or for adding a description of -the data. +The [`Table`][vizro.models.Table] and the [`AgGrid`][vizro.models.AgGrid] models accept a `title`, `header` and `footer` argument. This is useful for providing context to the data being displayed, or for adding a description of the data. - **title**: Displayed as an [H3 header](https://dash.plotly.com/dash-html-components/h3), useful for summarizing the main topic or insight of the component. - **header**: Accepts markdown text, ideal for extra descriptions, subtitles, or detailed data insights. - **footer**: Accepts markdown text, commonly used for citing data sources, providing information on the last update, or adding disclaimers. - - ### Formatted AgGrid !!! example "Formatted AgGrid" @@ -571,30 +531,29 @@ the data. dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: dash_ag_grid - data_frame: gapminder_2007 - dashGridOptions: - pagination: true - title: Gapminder Data Insights - header: | - #### An Interactive Exploration of Global Health, Wealth, and Population - footer: | - SOURCE: **Plotly gapminder data set, 2024** - type: ag_grid - title: Formatted AgGrid + - components: + - figure: + _target_: dash_ag_grid + data_frame: gapminder_2007 + dashGridOptions: + pagination: true + title: Gapminder Data Insights + header: | + #### An Interactive Exploration of Global Health, Wealth, and Population + footer: | + SOURCE: **Plotly gapminder data set, 2024** + type: ag_grid + title: Formatted AgGrid ``` - === "Result" - [![FormattedGrid]][FormattedGrid] - - [FormattedGrid]: ../../assets/user_guides/components/formatted_aggrid.png + === "Result" + [![FormattedGrid]][formattedgrid] ### Formatted DataTable @@ -623,24 +582,32 @@ the data. dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: dash_data_table - data_frame: gapminder_2007 - title: Gapminder Data Insights - header: | - #### An Interactive Exploration of Global Health, Wealth, and Population - footer: | - SOURCE: **Plotly gapminder data set, 2024** - type: table - title: Formatted DataTable + - components: + - figure: + _target_: dash_data_table + data_frame: gapminder_2007 + title: Gapminder Data Insights + header: | + #### An Interactive Exploration of Global Health, Wealth, and Population + footer: | + SOURCE: **Plotly gapminder data set, 2024** + type: table + title: Formatted DataTable ``` - === "Result" - [![FormattedTable]][FormattedTable] - [FormattedTable]: ../../assets/user_guides/components/formatted_table.png + === "Result" + [![FormattedTable]][formattedtable] + +[aggrid]: ../../assets/user_guides/table/aggrid.png +[aggrid2]: ../../assets/user_guides/table/formatted_aggrid.png +[aggrid3]: ../../assets/user_guides/table/styled_aggrid.png +[formattedgrid]: ../../assets/user_guides/components/formatted_aggrid.png +[formattedtable]: ../../assets/user_guides/components/formatted_table.png +[table]: ../../assets/user_guides/table/table.png +[table2]: ../../assets/user_guides/table/styled_table.png diff --git a/vizro-core/docs/pages/user-guides/tabs.md b/vizro-core/docs/pages/user-guides/tabs.md index 09154177e..1811d0cac 100755 --- a/vizro-core/docs/pages/user-guides/tabs.md +++ b/vizro-core/docs/pages/user-guides/tabs.md @@ -1,8 +1,6 @@ # How to use tabs -[`Tabs`][vizro.models.Tabs] organize and separate groups of related content in a dashboard, letting users switch between different sections or views. -They are essentially a way of putting multiple [`Containers`][vizro.models.Container] in the same screen space, and letting the user switch between them. -`Containers` enable the grouping of page components into sections and subsections. See our [user guide on `Containers`](container.md) for more information. +[`Tabs`][vizro.models.Tabs] organize and separate groups of related content in a dashboard, letting users switch between different sections or views. They are essentially a way of putting multiple [`Containers`][vizro.models.Container] in the same screen space, and letting the user switch between them. `Containers` enable the grouping of page components into sections and subsections. See our [user guide on `Containers`](container.md) for more information.
![tabs](../../assets/user_guides/components/tabs-info.png){ width="400"} @@ -16,14 +14,12 @@ This guide shows you how to use tabs to organize your `Containers` into subsecti By using [`Tabs`][vizro.models.Tabs], the following applies: - [`Filters`][vizro.models.Filter] affect all components on all tabs (opened and closed) of the page if not specified otherwise inside `Filter.targets` -- The `title` of the [`Container`][vizro.models.Container] inserted into `Tabs.tabs` will be displayed as a tab label, and the title will be removed from the `Container` - +- The `title` of the [`Container`][vizro.models.Container] inserted into `Tabs.tabs` will be displayed as a tab label, and the title will be removed from the `Container` To add [`Tabs`][vizro.models.Tabs] to your page, do the following: 1. Insert the [`Tabs`][vizro.models.Tabs] into the `components` argument of the [`Page`][vizro.models.Page] -2. Insert your [`Containers`][vizro.models.Container] into the `tabs` argument of the [`Tabs`][vizro.models.Tabs] - +1. Insert your [`Containers`][vizro.models.Container] into the `tabs` argument of the [`Tabs`][vizro.models.Tabs] !!! example "Tabs" === "app.py" @@ -88,52 +84,53 @@ To add [`Tabs`][vizro.models.Tabs] to your page, do the following: Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - tabs: - - title: Tab I - type: container - components: - - type: graph - figure: - _target_: bar - data_frame: gapminder_2007 - title: Graph 1 - x: continent - y: lifeExp - color: continent - - type: graph - figure: - _target_: box - data_frame: gapminder_2007 - title: Graph 2 - x: continent - y: lifeExp - color: continent - - title: Tab II - type: container - components: - - type: graph - figure: - _target_: scatter - data_frame: gapminder_2007 - title: Graph 3 - x: gdpPercap - y: lifeExp - size: pop - color: continent - type: tabs + components: + - type: tabs + tabs: + - title: Tab I + type: container + components: + - type: graph + figure: + _target_: bar + data_frame: gapminder_2007 + title: Graph 1 + x: continent + y: lifeExp + color: continent + - type: graph + figure: + _target_: box + data_frame: gapminder_2007 + title: Graph 2 + x: continent + y: lifeExp + color: continent + - title: Tab II + type: container + components: + - type: graph + figure: + _target_: scatter + data_frame: gapminder_2007 + title: Graph 3 + x: gdpPercap + y: lifeExp + size: pop + color: continent controls: - - type: filter - column: continent + - type: filter + column: continent title: Tabs ``` - === "Result" - [![Tabs]][Tabs] + === "Result" + [![Tabs]][tabs] - [Tabs]: ../../assets/user_guides/components/tabs.png +[tabs]: ../../assets/user_guides/components/tabs.png diff --git a/vizro-core/docs/pages/user-guides/themes.md b/vizro-core/docs/pages/user-guides/themes.md index 6f78441d5..8a78752a4 100644 --- a/vizro-core/docs/pages/user-guides/themes.md +++ b/vizro-core/docs/pages/user-guides/themes.md @@ -1,15 +1,13 @@ # How to use themes -This guide shows you how to use themes. Themes are pre-designed collections of stylings that are applied to entire charts and dashboards. -The themes provided by Vizro are infused with our design best practices that make charts and dashboards look visually consistent and professional. +This guide shows you how to use themes. Themes are pre-designed collections of stylings that are applied to entire charts and dashboards. The themes provided by Vizro are infused with our design best practices that make charts and dashboards look visually consistent and professional. ## Themes in dashboards -The [`Dashboard`][vizro.models.Dashboard] model accepts an optional `theme` argument, where you can choose between -a `vizro_dark` and a `vizro_light` theme. If not specified then `theme` defaults to `vizro_dark`. The theme is applied to the entire dashboard and its charts/components when a user first loads your dashboard. Regardless of the theme applied on first load, users can always switch between light and dark themes via the toggle button in the upper-right corner of the dashboard. + +The [`Dashboard`][vizro.models.Dashboard] model accepts an optional `theme` argument, where you can choose between a `vizro_dark` and a `vizro_light` theme. If not specified then `theme` defaults to `vizro_dark`. The theme is applied to the entire dashboard and its charts/components when a user first loads your dashboard. Regardless of the theme applied on first load, users can always switch between light and dark themes via the toggle button in the upper-right corner of the dashboard. !!! example "Change theme" === "app.py" - ```{.python pycafe-link hl_lines="18"} import vizro.models as vm import vizro.plotly.express as px @@ -32,47 +30,40 @@ a `vizro_dark` and a `vizro_light` theme. If not specified then `theme` defaults Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml hl_lines="12" # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example pages: - - components: - - figure: - _target_: scatter_matrix - color: species - data_frame: iris - dimensions: ["sepal_length", "sepal_width", "petal_length", "petal_width"] - type: graph - title: Changing themes + - components: + - figure: + _target_: scatter_matrix + color: species + data_frame: iris + dimensions: [sepal_length, sepal_width, petal_length, petal_width] + type: graph + title: Changing themes theme: vizro_light ``` + === "Result - vizro_light" - [![Light]][Light] + [![Light]][light] - [Light]: ../../assets/user_guides/themes/light.png === "Result - vizro_dark" - [![Dark]][Dark] - - [Dark]: ../../assets/user_guides/themes/dark.png - + [![Dark]][dark] ## Themes in plotly charts You can also use our templates for plotly charts outside the dashboard. This is useful in a few contexts: -* Creation of standalone charts to be used independently of a Vizro dashboard. -* Rapid development of charts for eventual use in a Vizro dashboard, for example in a Jupyter Notebook. +- Creation of standalone charts to be used independently of a Vizro dashboard. +- Rapid development of charts for eventual use in a Vizro dashboard, for example in a Jupyter Notebook. !!! note + Using `import vizro.plotly.express as px` is equivalent to using `import plotly.express as px`, but with the added benefit of being able to integrate the resulting chart code into a Vizro dashboard. Vizro offers a minimal layer on top of Plotly's existing charting library, allowing you to seamlessly use all the existing charts and functionalities provided by plotly.express without any modifications. - Using `import vizro.plotly.express as px` is equivalent to using `import plotly.express as px`, - but with the added benefit of being able to integrate the resulting chart code into a Vizro dashboard. - Vizro offers a minimal layer on top of Plotly's existing charting library, allowing you to seamlessly use all the - existing charts and functionalities provided by plotly.express without any modifications. - -Our `vizro_dark` and `vizro_light` themes are automatically registered to `plotly.io.templates` when importing Vizro. -Consult the plotly documentation for [more details on how templates work in plotly](https://plotly.com/python/templates/#theming-and-templates). +Our `vizro_dark` and `vizro_light` themes are automatically registered to `plotly.io.templates` when importing Vizro. Consult the plotly documentation for [more details on how templates work in plotly](https://plotly.com/python/templates/#theming-and-templates). By default, plots imported from `vizro.plotly.express` have the `vizro_dark` theme applied. This can be altered either globally or for individual plots. @@ -87,14 +78,20 @@ pio.templates.default = "vizro_light" ``` ### Set themes for selected charts + To change the template for a selected chart only, use the `template` parameter and run: ```python import vizro.plotly.express as px df = px.data.iris() -px.scatter_matrix(df, - dimensions=["sepal_length", "sepal_width", "petal_length", "petal_width"], - color="species", - template="vizro_light") +px.scatter_matrix( + df, + dimensions=["sepal_length", "sepal_width", "petal_length", "petal_width"], + color="species", + template="vizro_light", +) ``` + +[dark]: ../../assets/user_guides/themes/dark.png +[light]: ../../assets/user_guides/themes/light.png diff --git a/vizro-core/docs/pages/user-guides/visual-formatting.md b/vizro-core/docs/pages/user-guides/visual-formatting.md index 7b384f3e9..56d1d2d52 100644 --- a/vizro-core/docs/pages/user-guides/visual-formatting.md +++ b/vizro-core/docs/pages/user-guides/visual-formatting.md @@ -1,17 +1,13 @@ # How to customize the style of Vizro dashboards -Vizro has a default styling to help users with no design experience get started. -There are several options if you want to customize the style: +Vizro has a default styling to help users with no design experience get started. There are several options if you want to customize the style: -* **[Configure the `Layout`](layouts.md)**: Customize the arrangement of your components inside your Vizro dashboard. +- **[Configure the `Layout`](layouts.md)**: Customize the arrangement of your components inside your Vizro dashboard. -* **[Apply a theme](themes.md)**: Choose between a dark or light theme. +- **[Apply a theme](themes.md)**: Choose between a dark or light theme. -* **[Manage assets](assets.md)**: Enhance your dashboard by adding images, scripts, and stylesheets to your assets folder. +- **[Manage assets](assets.md)**: Enhance your dashboard by adding images, scripts, and stylesheets to your assets folder. -* **[Customize CSS](custom-css.md)**: Incorporate custom CSS to deviate from the default styling and create a -unique appearance for your Vizro dashboard. +- **[Customize CSS](custom-css.md)**: Incorporate custom CSS to deviate from the default styling and create a unique appearance for your Vizro dashboard. -* **[Customize your `component`](components.md)**: Change the appearance of components like the [Graph](graph.md), the -[Table](table.md) and the [AgGrid](table.md), by passing extra arguments. Refer to the relevant user guide for -more details. +- **[Customize your `component`](components.md)**: Change the appearance of components like the [Graph](graph.md), the [Table](table.md) and the [AgGrid](table.md), by passing extra arguments. Refer to the relevant user guide for more details. diff --git a/vizro-core/examples/README.md b/vizro-core/examples/README.md index 72146bfb7..53cf932b7 100644 --- a/vizro-core/examples/README.md +++ b/vizro-core/examples/README.md @@ -4,8 +4,7 @@ Please note that this folder contains only example dashboards that are still **i ### Vizro examples gallery -To view a comprehensive list of available demos, please visit our [examples gallery](http://vizro.mckinsey.com/). -There, you can explore a wide range of dashboards and applications created with Vizro. +To view a comprehensive list of available demos, please visit our [examples gallery](http://vizro.mckinsey.com/). There, you can explore a wide range of dashboards and applications created with Vizro. diff --git a/vizro-core/examples/visual-vocabulary/README.md b/vizro-core/examples/visual-vocabulary/README.md index 667742e8c..fe6051bcb 100644 --- a/vizro-core/examples/visual-vocabulary/README.md +++ b/vizro-core/examples/visual-vocabulary/README.md @@ -2,14 +2,11 @@ ### Welcome to our visual vocabulary dashboard! 🎨 -This dashboard serves as a comprehensive guide for selecting and creating various types of charts. It helps you decide -when to use each chart type, and offers sample Python code using [Plotly](https://plotly.com/python/), and -instructions for embedding these charts into a [Vizro](https://github.com/mckinsey/vizro) dashboard. +This dashboard serves as a comprehensive guide for selecting and creating various types of charts. It helps you decide when to use each chart type, and offers sample Python code using [Plotly](https://plotly.com/python/), and instructions for embedding these charts into a [Vizro](https://github.com/mckinsey/vizro) dashboard. The charts in this dashboard are designed to make it easy for anyone to create beautiful and sophisticated visuals. -Our goal is to help you understand best practices in data visualization, ensure your charts effectively communicate -your message, and streamline the creation of high-quality, interactive visualizations. +Our goal is to help you understand best practices in data visualization, ensure your charts effectively communicate your message, and streamline the creation of high-quality, interactive visualizations. Created by: @@ -19,12 +16,9 @@ Created by: Inspired by: -- [The FT Visual Vocabulary](https://github.com/Financial-Times/chart-doctor/blob/main/visual-vocabulary/README.md): - [Alan Smith](https://github.com/alansmithy), [Chris Campbell](https://github.com/digitalcampbell), Ian Bott, - Liz Faunce, Graham Parrish, Billy Ehrenberg, Paul McCallum, [Martin Stabe](https://github.com/martinstabe). +- [The FT Visual Vocabulary](https://github.com/Financial-Times/chart-doctor/blob/main/visual-vocabulary/README.md): [Alan Smith](https://github.com/alansmithy), [Chris Campbell](https://github.com/digitalcampbell), Ian Bott, Liz Faunce, Graham Parrish, Billy Ehrenberg, Paul McCallum, [Martin Stabe](https://github.com/martinstabe). -- [The Graphic Continuum](https://www.informationisbeautifulawards.com/showcase/611-the-graphic-continuum): - Jon Swabish and Severino Ribecca +- [The Graphic Continuum](https://www.informationisbeautifulawards.com/showcase/611-the-graphic-continuum): Jon Swabish and Severino Ribecca Credits and sources: @@ -102,14 +96,13 @@ The dashboard is still in development. Below is an overview of the chart types f Contributions are welcome! To contribute a chart, follow the steps below: 1. Check that a `svg` file named after the chart type is contained in the [assets](https://github.com/mckinsey/vizro/tree/main/vizro-core/examples/visual-vocabulary/assets/images/charts) folder. If not, [raise an issue](https://github.com/mckinsey/vizro/issues) in the repository. -2. Add the data set to `_pages_utils.py` if it doesn't already exist. Use existing data sets preferably or any other data set that is publicly available e.g. [plotly.express.data](https://plotly.com/python-api-reference/generated/plotly.express.data.html) -3. Create a new page for the chart type and add it to the relevant category `.py` file such as `correlation.py`, - `deviation.py`, `distribution.py`, etc. Ensure you add the page to the list of `pages` at the end of the `.py` file. -4. Add a `.py` file containing a code example of the chart type in the `pages/examples` folder, for instance, `area.py`. Take a look at existing examples. -5. Remove the `IncompletePage(..)` entry for that chart type in `chart_groups.py`. -6. Update this `README.md` with the new chart type, its status, category, and API links. +1. Add the data set to `_pages_utils.py` if it doesn't already exist. Use existing data sets preferably or any other data set that is publicly available e.g. [plotly.express.data](https://plotly.com/python-api-reference/generated/plotly.express.data.html) +1. Create a new page for the chart type and add it to the relevant category `.py` file such as `correlation.py`, `deviation.py`, `distribution.py`, etc. Ensure you add the page to the list of `pages` at the end of the `.py` file. +1. Add a `.py` file containing a code example of the chart type in the `pages/examples` folder, for instance, `area.py`. Take a look at existing examples. +1. Remove the `IncompletePage(..)` entry for that chart type in `chart_groups.py`. +1. Update this `README.md` with the new chart type, its status, category, and API links. ## How to run the example locally 1. Run the example with the command `hatch run example visual-vocabulary`. -2. You should now be able to access the app locally via http://127.0.0.1:8050/. +1. You should now be able to access the app locally via http://127.0.0.1:8050/. From 2b5c61cf0ebcbbaf2802bc25d0f2f34e2dc918c1 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Thu, 14 Nov 2024 10:45:46 +0000 Subject: [PATCH 02/54] Some more manual fixes --- README.md | 3 +- vizro-ai/CHANGELOG.md | 3 +- vizro-ai/README.md | 3 +- .../pages/user-guides/advanced-options.md | 50 +++++++++++-------- vizro-ai/docs/pages/user-guides/install.md | 27 ++++------ vizro-core/README.md | 3 +- .../20241114_103750_antony.milne_mdformat.md | 48 ++++++++++++++++++ vizro-core/docs/pages/user-guides/assets.md | 2 +- .../docs/pages/user-guides/card-button.md | 2 - .../docs/pages/user-guides/custom-charts.md | 1 - 10 files changed, 90 insertions(+), 52 deletions(-) create mode 100644 vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md diff --git a/README.md b/README.md index 43c26d456..6c77b4ae8 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,7 @@
-FIXME: maybe use two new lines between each -[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +FIXME: maybe use two new lines between each [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
diff --git a/vizro-ai/CHANGELOG.md b/vizro-ai/CHANGELOG.md index 72186c8b1..98a162904 100644 --- a/vizro-ai/CHANGELOG.md +++ b/vizro-ai/CHANGELOG.md @@ -141,5 +141,4 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse ## Highlights ✨ -- Initial release of Vizro-AI package. Vizro-AI is a tool for generating data - visualizations. ([#138](https://github.com/mckinsey/vizro/pull/138)) +- Initial release of Vizro-AI package. Vizro-AI is a tool for generating data visualizations. ([#138](https://github.com/mckinsey/vizro/pull/138)) diff --git a/vizro-ai/README.md b/vizro-ai/README.md index 28fd2df39..fdca6d99d 100644 --- a/vizro-ai/README.md +++ b/vizro-ai/README.md @@ -2,8 +2,7 @@
-FIXME: maybe use two new lines between each -[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +FIXME: maybe use two new lines between each [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) Gif to demonstrate vizro-ai diff --git a/vizro-ai/docs/pages/user-guides/advanced-options.md b/vizro-ai/docs/pages/user-guides/advanced-options.md index 528a74912..b82f6edca 100644 --- a/vizro-ai/docs/pages/user-guides/advanced-options.md +++ b/vizro-ai/docs/pages/user-guides/advanced-options.md @@ -4,19 +4,20 @@ This guide shows you how to use the advanced options of `VizroAI.plot`. First we show how to change the input parameters of the function, as follows: -* control over whether code gets executed, -* the number of retries of `.plot` when it fails validation, -* how to request a comprehensive output (when `return_elements=True`). +- control over whether code gets executed, +- the number of retries of `.plot` when it fails validation, +- how to request a comprehensive output (when `return_elements=True`). Second we show how to use this more comprehensive output, enabling control of code generation and `fig` object production. ## Inputs of `VizroAI.plot` ### `user_input` -This is the natural language query from which, together with a data sample, the LLM creates a plotly chart. For the query, you can [use English or a different language](use-different-languages.md). The complexity of the resulting chart [depends on the vendor model capabilities](customize-vizro-ai.md#what-model-to-choose). +This is the natural language query from which, together with a data sample, the LLM creates a plotly chart. For the query, you can [use English or a different language](use-different-languages.md). The complexity of the resulting chart [depends on the vendor model capabilities](customize-vizro-ai.md#what-model-to-choose). ### `df` + Supply any `pandas` data frame to base your query on. The LLM will receive a sample of this data frame to form an appropriate graph. If the option `validate_code` is set to `True` (which it is by default), the LLM created chart code will be evaluated on a sample of this data frame. @@ -24,10 +25,13 @@ If the option `validate_code` is set to `True` (which it is by default), the LLM If `return_elements` is set to `False`, then the returned `fig` object will be created based on this (entire) data frame. + ### `max_debug_retry` + This number determines how often the tool will try to correct an incorrect response (that fails various validation criteria). Under the hood this is [implemented via pydantic validators](https://docs.pydantic.dev/1.10/usage/validators/). The last response will be re-sent to the LLM together with the validation error(s) in order to receive an improved response. This concept is [inspired by the amazing instructor library](https://github.com/jxnl/instructor). ### `return_elements` + This boolean (by default `False`) determines the return type of `VizroAI.plot`. If set to `False`, then dynamically generated Python code is executed to produce a `plotly.graph_objects.Figure` object from the LLM response and the user supplied data frame. Strictly speaking, it produces a `vizro.charts._charts_utils._DashboardReadyFigure`, which behaves essentially like the former, but is ready to be [inserted](add-generated-chart-usecase.md) into a [Vizro](https://vizro.readthedocs.io/en/stable/) dashboard. It also comes with the default Vizro dark theme. @@ -35,8 +39,11 @@ If set to `False`, then dynamically generated Python code is executed to produce If set to `True`, a class (pydantic model) is returned from which the `fig` object, but also various other outputs can be generated. (see below) ### `validate_code` + This boolean (by default `True`) determines whether the LLM generated Python code executes with a sample of the data in order to verify that it runs and produces a plotly figure. Be sure [to read and understand what it means when dynamically generated code is executed](../explanation/safety-in-vizro-ai.md#execution-of-dynamic-code-in-vizro-ai). + + If `return_elements=True` **and** `validate_code=False`, then no code is executed to obtain the return of `VizroAI.plot`. This means that the code string obtained is not validated, but also that no code was executed. ## Output if `return_elements=True` @@ -44,10 +51,10 @@ If `return_elements=True` **and** `validate_code=False`, then no code is execute If `return_elements=True`, then instead of a `fig` object, a class is returned, which enables the following options: ### Obtain `vizro` code string + You can obtain the code string that would produce the answer to the user query as a Vizro dashboard ready figure as follows. The name for the function will be `custom_chart`: !!! example "Vizro code" - === "Code" ```py from vizro_ai import VizroAI @@ -76,10 +83,10 @@ You can obtain the code string that would produce the answer to the user query a ``` ### Obtain `plotly` code string + You can obtain the code string that would produce the answer to the user query as a pure `plotly.graph_objects.Figure` as follows. The name for the function will be `custom_chart`: !!! example "Plotly code" - === "Code" ```py from vizro_ai import VizroAI @@ -110,10 +117,10 @@ You can obtain the code string that would produce the answer to the user query a You can create the `fig` object using either of the above produced code strings (vizro or plotly), changing the chart name, and using different data. Note that when executing this function, the produced code string will be dynamically executed. Be sure [to read and understand what it means when dynamically generated code is executed](../explanation/safety-in-vizro-ai.md#execution-of-dynamic-code-in-vizro-ai). #### Vizro ready + This `fig` object is in the standard `vizro_dark` theme, and can [be inserted into a Vizro dashboard](add-generated-chart-usecase.md). !!! example "Vizro `fig` object" - === "Code" ```py from vizro_ai import VizroAI @@ -128,15 +135,16 @@ This `fig` object is in the standard `vizro_dark` theme, and can [be inserted in ``` === "Result" - [![VizroAIChartVizro]][VizroAIChartVizro] + [![VizroAIChartVizro]][vizroaichartvizro] + + ``` ``` - [VizroAIChartVizro]: ../../assets/user_guides/VizroAIVizro.png #### Pure Plotly/Dash + This `fig` object is a basic plotly figure. !!! example "Plotly `fig` object" - === "Code" ```py from vizro_ai import VizroAI @@ -151,19 +159,18 @@ This `fig` object is a basic plotly figure. ``` === "Result" - [![VizroAIChartPlotly]][VizroAIChartPlotly] - ``` - [VizroAIChartPlotly]: ../../assets/user_guides/VizroAIPlotly.png + [![VizroAIChartPlotly]][vizroaichartplotly] #### Using different data + + You can create the `fig` object with different data while ensuring the overall schema remains consistent. You can re-evaluate this function to generate various `fig` objects for different data. For example, the code could be generated using fake or sample data fed into Vizro-AI. When moving to production, you can switch the data source to the complete dataset, as long as the data schema is consistent. + !!! example "Different data" - === "Code" - ```py from vizro_ai import VizroAI import plotly.express as px @@ -180,19 +187,14 @@ You can create the `fig` object with different data while ensuring the overall s ``` === "Result" - [![VizroAINewData]][VizroAINewData] - ``` - [VizroAINewData]: ../../assets/user_guides/VizroAINewData.png - ``` + [![VizroAINewData]][vizroainewdata] #### Changing the chart name -This option executes the chart code with the name given under `chart_name`. This can be important when you want to avoid overwriting variables in the namespace. +This option executes the chart code with the name given under `chart_name`. This can be important when you want to avoid overwriting variables in the namespace. !!! example "Changing the `chart_name`" - === "Code" - ```py from vizro_ai import VizroAI import plotly.express as px @@ -209,3 +211,7 @@ This option executes the chart code with the name given under `chart_name`. This ```py ``` + +[vizroaichartplotly]: ../../assets/user_guides/VizroAIPlotly.png +[vizroaichartvizro]: ../../assets/user_guides/VizroAIVizro.png +[vizroainewdata]: ../../assets/user_guides/VizroAINewData.png diff --git a/vizro-ai/docs/pages/user-guides/install.md b/vizro-ai/docs/pages/user-guides/install.md index 9ecee589f..7db393e51 100644 --- a/vizro-ai/docs/pages/user-guides/install.md +++ b/vizro-ai/docs/pages/user-guides/install.md @@ -4,12 +4,11 @@ In this guide you'll learn how to set up the prerequisites needed for Vizro-AI, Vizro-AI supports macOS, Linux, and Windows. It works with Python 3.9 and later. You can specify the version of Python to use with Vizro-AI when you set up a virtual environment. - ## Set up a virtual environment + You should create a virtual environment for each Vizro-AI project you work on to isolate its Python dependencies from those of other projects. See the following references to learn more about [Python virtual environments](https://realpython.com/python-virtual-environments-a-primer/), [Conda virtual environments](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html#starting-conda) or [watch an explainer video about them](https://youtu.be/YKfAwIItO7M). ??? information "How to create a virtual environment for your Vizro-AI project" - The simplest way to create a virtual environment in Python is `venv`, which is included in the Python standard library. Create a directory for your project and navigate to it. For example: ```bash @@ -18,6 +17,7 @@ You should create a virtual environment for each Vizro-AI project you work on to ``` Next, create and activate a new virtual environment in this directory with `venv`: + ```bash python3 -m venv .venv source .venv/bin/activate @@ -62,8 +62,8 @@ You should see a return output of the form `x.y.z`. Vizro-AI supports **any** model that is available via [Langchain's `BaseChatModel` class](https://api.python.langchain.com/en/latest/language_models/langchain_core.language_models.chat_models.BaseChatModel.html#langchain_core.language_models.chat_models.BaseChatModel), and that has the [`with_structured_output` method](https://python.langchain.com/v0.2/docs/how_to/structured_output/#the-with_structured_output-method) implemented. An overview of the [most common vendor models supporting this functionality](https://python.langchain.com/v0.2/docs/integrations/chat/) can be found in Langchain's documentation. - ### Set up access to OpenAI (as an example for any vendor) + To use OpenAI with Vizro-AI you need an API key, which you can get by [creating an OpenAI account if you don't already have one](https://platform.openai.com/account/api-keys). We recommend that you consult the [third-party API key section of the disclaimer documentation](../explanation/disclaimer.md) documentation. @@ -72,8 +72,7 @@ There are two common ways to set up the API key in a development environment. __Method 1: Set an environment variable for a single project__ -To make the API key available for a single project, you can create a local `.env` -file to store it. Then, you can load the API key from that `.env` file in your development environment. +To make the API key available for a single project, you can create a local `.env` file to store it. Then, you can load the API key from that `.env` file in your development environment. The `.env` file should look as follows (containing your key rather than `abc123`): @@ -86,7 +85,6 @@ By default, `vizro-ai` automatically loads the `.env` file, by searching the cur If you would like to customize the `.env` file location and name, you can manually customize the search to override the default and specify the path and name of a custom `.env` file. ??? example "How to override the default location of the .`env` file:" - ```py from dotenv import load_dotenv, find_dotenv from pathlib import Path @@ -100,33 +98,26 @@ If you would like to customize the `.env` file location and name, you can manual # Load the specified .env file load_dotenv(env_file) ``` + Refer to [Python-dotenv documentation](https://saurabh-kumar.com/python-dotenv/reference/) for further information. !!! warning "Don't share your secret API key!" - You should avoid committing the `.env` file to version control. You can do this for Git by adding `.env` to your `.gitignore` file. - __Method 2: Set an environment variable for all projects__ -To make the OpenAI API key available for all projects, you can set it as a system environment -variable. Refer to the section ["Set up your API key for all projects"](https://platform.openai.com/docs/quickstart/step-2-setup-your-api-key?context=python) -in the OpenAI documentation. (It is under the dropdown of "Step 2: Set up your API key"). +To make the OpenAI API key available for all projects, you can set it as a system environment variable. Refer to the section ["Set up your API key for all projects"](https://platform.openai.com/docs/quickstart/step-2-setup-your-api-key?context=python) in the OpenAI documentation. (It is under the dropdown of "Step 2: Set up your API key"). -The documentation gives step-by-step instructions for setting up the API key as an environment -variable, on operating systems including Windows and MacOS. +The documentation gives step-by-step instructions for setting up the API key as an environment variable, on operating systems including Windows and MacOS. -!!!note +!!! note Sometimes setting up the `.env` file can be fiddly. If necessary, you can supply the API key directly to the instantiated model. See [our user guide](./customize-vizro-ai.md#setting-model-via-class-for-additional-configuration) for this option. Remember not to commit this API key to any public space! __Set the base URL (optional)__ You might need to give the base URL if you are using a custom OpenAI resource endpoint. -The API base URL used for the OpenAI connector is set to `https://api.openai.com/v1` by default. -If you are using a custom API endpoint, for example, if your organization has a designated API gateway, -you can change the base URL by setting it as an environment variable. - +The API base URL used for the OpenAI connector is set to `https://api.openai.com/v1` by default. If you are using a custom API endpoint, for example, if your organization has a designated API gateway, you can change the base URL by setting it as an environment variable. Follow the approach above in Method 2 to add the environment variable `OPENAI_API_BASE` for use by all projects. diff --git a/vizro-core/README.md b/vizro-core/README.md index 729f13298..a8bb03617 100644 --- a/vizro-core/README.md +++ b/vizro-core/README.md @@ -11,8 +11,7 @@
-FIXME: maybe use two new lines between each -[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +FIXME: maybe use two new lines between each [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
diff --git a/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md b/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md new file mode 100644 index 000000000..7c0d58d4f --- /dev/null +++ b/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/vizro-core/docs/pages/user-guides/assets.md b/vizro-core/docs/pages/user-guides/assets.md index e4f8538ff..87c79fb07 100644 --- a/vizro-core/docs/pages/user-guides/assets.md +++ b/vizro-core/docs/pages/user-guides/assets.md @@ -1,6 +1,6 @@ # How to add static assets - This guide shows you how to add static assets to your dashboard. Static assets are images that you would like to show in your dashboard, or custom CSS and JS files with which you would like to enhance/change the appearance of your dashboard. +This guide shows you how to add static assets to your dashboard. Static assets are images that you would like to show in your dashboard, or custom CSS and JS files with which you would like to enhance/change the appearance of your dashboard. To add images, custom CSS or JS files, create a folder named `assets` in the root of your app directory and insert your files. Assets included in that folder are automatically served after serving Vizro's static files via the `external_stylesheets` and `external_scripts` arguments of [Dash](https://dash.plotly.com/external-resources#adding-external-css/javascript). The user's `assets` folder thus always takes precedence. diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index 541449527..bf9bc2913 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -223,7 +223,6 @@ An image ALT text offers a description to your image and serves as a text placeh PyCafe logo
Run and edit this code in PyCafe -```` === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -246,7 +245,6 @@ An image ALT text offers a description to your image and serves as a text placeh [![CardImageDefault]][CardImageDefault] [CardImageDefault]: ../../assets/user_guides/components/card_image_default.png -```` !!! note Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. diff --git a/vizro-core/docs/pages/user-guides/custom-charts.md b/vizro-core/docs/pages/user-guides/custom-charts.md index 2bf1af9b5..1b77d0869 100644 --- a/vizro-core/docs/pages/user-guides/custom-charts.md +++ b/vizro-core/docs/pages/user-guides/custom-charts.md @@ -88,7 +88,6 @@ The below examples shows a case where we enhance an existing `plotly.express` ch === "app.yaml" Custom charts are currently only possible via Python configuration. - ``` === "Result" [![Graph2]][graph2] From 1a97231e566cc02c7b2f860d94dcc30df83af1c5 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Thu, 14 Nov 2024 10:49:18 +0000 Subject: [PATCH 03/54] Some more manual fixes --- .../pages/user-guides/advanced-options.md | 3 --- .../docs/pages/user-guides/card-button.md | 24 +++++++++---------- .../docs/pages/user-guides/custom-css.md | 2 +- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/advanced-options.md b/vizro-ai/docs/pages/user-guides/advanced-options.md index b82f6edca..4d63eaa35 100644 --- a/vizro-ai/docs/pages/user-guides/advanced-options.md +++ b/vizro-ai/docs/pages/user-guides/advanced-options.md @@ -137,9 +137,6 @@ This `fig` object is in the standard `vizro_dark` theme, and can [be inserted in === "Result" [![VizroAIChartVizro]][vizroaichartvizro] - ``` - ``` - #### Pure Plotly/Dash This `fig` object is a basic plotly figure. diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index bf9bc2913..12d4ff0fa 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -228,23 +228,22 @@ An image ALT text offers a description to your image and serves as a text placeh # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![continent](assets/images/continents/africa.svg) + - components: + - text: | + ![continent](assets/images/continents/africa.svg) - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - title: My card with image! - type: card - title: Placing Images + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + title: My card with image! + type: card + title: Placing Images ``` -=== "Result" - [![CardImageDefault]][CardImageDefault] -[CardImageDefault]: ../../assets/user_guides/components/card_image_default.png +=== "Result" + [![CardImageDefault]][cardimagedefault] !!! note Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. @@ -677,6 +676,7 @@ vm.Page.add_type("controls", vm.Button) [button]: ../../assets/user_guides/components/button.png [card]: ../../assets/user_guides/components/card.png [cardicon]: ../../assets/user_guides/components/card_icon.png +[cardimagedefault]: ../../assets/user_guides/components/card_image_default.png [cardimagefloating]: ../../assets/user_guides/components/card_image_floating.png [cardimagestyled]: ../../assets/user_guides/components/card_image_styled.png [cardtext]: ../../assets/user_guides/components/card_text.png diff --git a/vizro-core/docs/pages/user-guides/custom-css.md b/vizro-core/docs/pages/user-guides/custom-css.md index af2219838..233561c16 100755 --- a/vizro-core/docs/pages/user-guides/custom-css.md +++ b/vizro-core/docs/pages/user-guides/custom-css.md @@ -219,7 +219,7 @@ It's essential to understand the relationship between the targeted CSS class or -\`\`\`html title="HTML structure of a `Card`" +```html title="HTML structure of a `Card`"
From 691d7a5d780884c115b88e98034188f6e5269519 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Thu, 14 Nov 2024 10:50:27 +0000 Subject: [PATCH 04/54] Some more manual fixes --- vizro-core/docs/pages/user-guides/custom-css.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-core/docs/pages/user-guides/custom-css.md b/vizro-core/docs/pages/user-guides/custom-css.md index 233561c16..7b10e8f9b 100755 --- a/vizro-core/docs/pages/user-guides/custom-css.md +++ b/vizro-core/docs/pages/user-guides/custom-css.md @@ -219,7 +219,7 @@ It's essential to understand the relationship between the targeted CSS class or -```html title="HTML structure of a `Card`" +```html {title="HTML structure of a `Card`"}
From 3c78977e2d83d77f447a5bb5d264c02a78a59ec4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:00:07 +0000 Subject: [PATCH 05/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/pull_request_template.md | 10 +++++----- .pre-commit-config.yaml | 7 ++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ea40a09f2..44e958f1c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,8 +6,8 @@ - [ ] I acknowledge and agree that, by checking this box and clicking "Submit Pull Request": - - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. - - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. - - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. - - I have not referenced individuals, products or companies in any commits, directly or indirectly. - - I have not added data or restricted code in any commits, directly or indirectly. + - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. + - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. + - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. + - I have not referenced individuals, products or companies in any commits, directly or indirectly. + - I have not added data or restricted code in any commits, directly or indirectly. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5fa161ada..3b6c066b5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -87,7 +87,12 @@ repos: rev: 0.7.18 hooks: - id: mdformat - args: [--ignore-missing-references, --wrap=no, --align-semantic-breaks-in-lists] + args: + [ + --ignore-missing-references, + --wrap=no, + --align-semantic-breaks-in-lists, + ] exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference additional_dependencies: - mdformat-mkdocs[recommended]==3.1.1 From b9a9f119815f5c8a1def66e49678aa9022d25b95 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Thu, 28 Nov 2024 17:23:07 +0000 Subject: [PATCH 06/54] Fix merge --- .github/pull_request_template.md | 10 +- vizro-ai/docs/index.md | 26 +- .../pages/explanation/safety-in-vizro-ai.md | 4 +- .../user-guides/create-advanced-charts.md | 28 +- .../user-guides/create-complex-dashboard.md | 11 +- .../user-guides/run-vizro-ai-dashboard.md | 51 +-- vizro-core/CHANGELOG.md | 3 +- .../20241114_103750_antony.milne_mdformat.md | 6 + vizro-core/docs/pages/explanation/authors.md | 22 +- .../docs/pages/user-guides/card-button.md | 385 +++++++++--------- .../docs/pages/user-guides/custom-css.md | 8 +- .../examples/visual-vocabulary/README.md | 25 +- 12 files changed, 266 insertions(+), 313 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 44e958f1c..ea40a09f2 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,8 +6,8 @@ - [ ] I acknowledge and agree that, by checking this box and clicking "Submit Pull Request": - - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. - - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. - - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. - - I have not referenced individuals, products or companies in any commits, directly or indirectly. - - I have not added data or restricted code in any commits, directly or indirectly. + - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. + - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. + - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. + - I have not referenced individuals, products or companies in any commits, directly or indirectly. + - I have not added data or restricted code in any commits, directly or indirectly. diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index 4c87daffb..1fe4f93d2 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -8,34 +8,25 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre Gif to demonstrate vizro-ai -
-- :fontawesome-solid-forward-fast:{ .lg .middle } __New to Vizro-AI?__ +- :fontawesome-solid-forward-fast:{ .lg .middle } __New to Vizro-AI?__ --- - [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
- [:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
- [:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
+ [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
- :fontawesome-solid-keyboard:{ .lg .middle } __Get hands-on__ --- - [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
- [:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
- [:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
- [:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
- [:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) + [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
[:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
[:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
[:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
[:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) - :material-format-font:{ .lg .middle } __Find out more__ --- - [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
- [:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
- [:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) + [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
[:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
[:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro__ @@ -43,14 +34,9 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre [:octicons-arrow-right-24: Vizro documentation](https://vizro.readthedocs.io/) -
!!! notice "Notice" + Review the [disclaimer](pages/explanation/disclaimer.md) before using the `vizro-ai` package. - Review the [disclaimer](pages/explanation/disclaimer.md) - before using the `vizro-ai` package. - - Users must connect to large language models (LLMs) to use Vizro-AI. - Please review our [guidelines on the use of LLMs](pages/explanation/safety-in-vizro-ai.md) - and the required [safeguarding for dynamic code evaluation](pages/explanation/safeguard.md). + Users must connect to large language models (LLMs) to use Vizro-AI. Please review our [guidelines on the use of LLMs](pages/explanation/safety-in-vizro-ai.md) and the required [safeguarding for dynamic code evaluation](pages/explanation/safeguard.md). diff --git a/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md b/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md index 552d5cd29..fc54596bb 100644 --- a/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md +++ b/vizro-ai/docs/pages/explanation/safety-in-vizro-ai.md @@ -72,11 +72,9 @@ Users must exercise caution when executing code generated by or influenced by AI To learn more, refer to the section that describes how to [safeguard execution of dynamic code](safeguard.md). - ## Debugging in Vizro-AI with LangSmith and LangFuse -[LangSmith](https://docs.smith.langchain.com/) and [LangFuse](https://langfuse.com/docs) are tools designed to enhance transparency and interpretability in AI workflows. -To improve debugging and traceability, you can use the advanced observability and evaluation features of these tools with Vizro-AI. +[LangSmith](https://docs.smith.langchain.com/) and [LangFuse](https://langfuse.com/docs) are tools designed to enhance transparency and interpretability in AI workflows. To improve debugging and traceability, you can use the advanced observability and evaluation features of these tools with Vizro-AI. To ensure responsible use, review their data privacy and security policies. See [LangFuse Data Security & Privacy ](https://langfuse.com/docs/data-security-privacy) and [LangSmith Privacy Policy](https://www.langchain.com/privacy-policy) site for more details. diff --git a/vizro-ai/docs/pages/user-guides/create-advanced-charts.md b/vizro-ai/docs/pages/user-guides/create-advanced-charts.md index 20abb95ec..4a8604511 100644 --- a/vizro-ai/docs/pages/user-guides/create-advanced-charts.md +++ b/vizro-ai/docs/pages/user-guides/create-advanced-charts.md @@ -1,4 +1,5 @@ # Advanced charts + This page explains how to use Vizro-AI to create charts with advanced visualizations and enhanced formatting. ## Animated map chart @@ -6,7 +7,6 @@ This page explains how to use Vizro-AI to create charts with advanced visualizat We'll create an animated map chart illustrating the GDP per capita of each continent over time. Run the code below and look at the result. !!! example "Vizro-AI animated chart" - === "Code" ```py from vizro_ai import VizroAI @@ -18,16 +18,13 @@ We'll create an animated map chart illustrating the GDP per capita of each conti fig = vizro_ai.plot(df, "Visualize GDP per capita over the years for each country using map chart.") fig.show() ``` - === "Result" - [![AnimatedChart1]][AnimatedChart1] - [AnimatedChart1]: ../../assets/tutorials/chart/advanced_chart_1.png + === "Result" + [![AnimatedChart1]][animatedchart1] -Having unveiled our animated map chart showcasing GDP per capita development per country, it's clear that the map area is small, and it is difficult to differentiate countries. -Next, we will try to tweak our prompt to improve the overall layout. +Having unveiled our animated map chart showcasing GDP per capita development per country, it's clear that the map area is small, and it is difficult to differentiate countries. Next, we will try to tweak our prompt to improve the overall layout. !!! example "Vizro-AI animated chart" - === "Code" ```py from vizro_ai import VizroAI @@ -41,18 +38,15 @@ Next, we will try to tweak our prompt to improve the overall layout. Show countries on the map. Increase the width and height of the figure.""") fig.show() ``` - === "Result" - [![AnimatedChart2]][AnimatedChart2] - - [AnimatedChart2]: ../../assets/tutorials/chart/advanced_chart_2.png + === "Result" + [![AnimatedChart2]][animatedchart2] By incorporating the directive `Increase the width and height of the figure.` and `Show countries on the map.` we've successfully refined our animation. Upon closer inspection, the title is too long and the color palette used does not match our needs. We can fix those issues with better and more specific prompting. Let's run the code below to visually improve the chart. !!! example "Vizro-AI animated chart" - === "Code" ```py from vizro_ai import VizroAI @@ -67,12 +61,14 @@ Upon closer inspection, the title is too long and the color palette used does no Set title to be: `GDP per Capita over the years`. Use `Blues` as color sequence. """) fig.show() ``` - === "Result" - [![AnimatedChart3]][AnimatedChart3] - [AnimatedChart3]: ../../assets/tutorials/chart/animated_advanced_chart.gif + === "Result" + [![AnimatedChart3]][animatedchart3] Congratulations! You've now gained insights into harnessing the power of a LLM and Vizro-AI for crafting advanced charts and improving formatting. Don't forget, enabling `return_elements=True` in `.plot()` and check `chart_insights` and `code_explanation` is a good way of learning more about how a chart can be further improved and formatted. - Advanced charts are well-suited for [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard applications. You can create a chart using `vizro-ai` to plug into your `vizro` dashboard in seconds! + +[animatedchart1]: ../../assets/tutorials/chart/advanced_chart_1.png +[animatedchart2]: ../../assets/tutorials/chart/advanced_chart_2.png +[animatedchart3]: ../../assets/tutorials/chart/animated_advanced_chart.gif diff --git a/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md b/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md index 0e6e282b1..fbec99025 100644 --- a/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md +++ b/vizro-ai/docs/pages/user-guides/create-complex-dashboard.md @@ -9,6 +9,7 @@ The following example shows how to use Vizro-AI to generate a complex Vizro dash If you haven't already installed Vizro-AI and set up the API key for OpenAI, follow the [installation guide](../user-guides/install.md). ## 1. Prepare the data + Next, prepare the data to pass to Vizro-AI. In this example, we use the [election data](https://plotly.com/python-api-reference/generated/plotly.express.data.html#plotly.express.data.election) and the [stocks data](https://plotly.com/python-api-reference/generated/plotly.express.data.html#plotly.express.data.stocks). ```py @@ -18,7 +19,6 @@ df1 = px.data.election() df2 = px.data.stocks(datetimes=True) ``` - ## 2. Prepare the user prompt Devise a string of text to form the prompt that requests Vizro-AI to generate the Vizro dashboard. @@ -104,7 +104,6 @@ dashboard = vizro_ai.dashboard([df1, df2], user_question) The call to `dashboard()` triggers the dashboard building process. Once Vizro-AI finishes this process, you can launch the dashboard with `build()`. !!! example "Generated dashboard" - === "Code" ```py import vizro_ai @@ -176,10 +175,10 @@ The call to `dashboard()` triggers the dashboard building process. Once Vizro-AI ``` === "Page1" - [![VizroAIDashboardPage1]][VizroAIDashboardPage1] + [![VizroAIDashboardPage1]][vizroaidashboardpage1] === "Page2" - [![VizroAIDashboardPage2]][VizroAIDashboardPage2] + [![VizroAIDashboardPage2]][vizroaidashboardpage2] - [VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard1_page1.png - [VizroAIDashboardPage2]: ../../assets/user_guides/dashboard/dashboard1_page2.png +[vizroaidashboardpage1]: ../../assets/user_guides/dashboard/dashboard1_page1.png +[vizroaidashboardpage2]: ../../assets/user_guides/dashboard/dashboard1_page2.png diff --git a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md index 2a9e59b52..2ae3018ac 100644 --- a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md +++ b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md @@ -3,13 +3,11 @@ This guide offers insights into different ways of running `VizroAI.dashboard` to generate a Vizro dashboards from natural language prompts. ??? note "Note: API key" - Make sure you have followed the [LLM setup guide](../user-guides/install.md#set-up-access-to-a-large-language-model) and that your API key is set up in a `.env` file in the same folder as your Notebook file (`.ipynb`). ## Run Vizro-AI dashboard !!! example "Generated dashboard" - === "Code" ```py import vizro.plotly.express as px @@ -36,24 +34,26 @@ This guide offers insights into different ways of running `VizroAI.dashboard` to ``` === "Result" - [![VizroAIDashboardPage1]][VizroAIDashboardPage1] - + \[!\[VizroAIDashboardPage1\]\]\[VizroAIDashboardPage1\] - [VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard2_page1.png +``` +[VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard2_page1.png +``` This triggers the dashboard building process. Once Vizro-AI finishes the dashboard generation process, you can now launch the dashboard. ## Retrieve the Python code of the dashboard To illustrate the process, lets use the example above. + + Like the `VizroAI.plot` method, in order to produce more comprehensive output we need to set `return_elements=True`. `return_elements` is a boolean (by default `False`) which determines the return type of `VizroAI.dashboard`. - If set to `False` it produces a `Vizro` dashboard object. - If set to `True`, it returns a class (a Pydantic model) containing both the dashboard object and the code string used to generate it. !!! example "View dashboard code" - === "Code" ```py import vizro.plotly.express as px @@ -79,6 +79,7 @@ Like the `VizroAI.plot` method, in order to produce more comprehensive output we print(result.code) ``` + === "Result" ```py ######## Module Imports ########## @@ -124,9 +125,11 @@ Like the `VizroAI.plot` method, in order to produce more comprehensive output we To use the above code, you will still need to add three simple steps: - Import your data. + ```py data = pd.read_csv('data.csv') # Replace 'data.csv' with your filename or path to your data ``` + - After importing your data, register it in the data manager by uncommenting the data manager instance and assigning the imported data to it. See the Vizro guide on [connecting dashboard to data](https://vizro.readthedocs.io/en/stable/pages/user-guides/data/#reference-by-name/). ```py @@ -134,9 +137,11 @@ To use the above code, you will still need to add three simple steps: ``` - Launch the dashboard by adding the code below at the end of the file: + ```py Vizro().build(dashboard).run() ``` + Detailed guidance is provided in [dashboard generation tutorial](https://vizro.readthedocs.io/projects/vizro-ai/en/latest/pages/tutorials/quickstart/). ## Available Vizro components @@ -144,22 +149,22 @@ Detailed guidance is provided in [dashboard generation tutorial](https://vizro.r The following list is a table of the Vizro components currently supported by Vizro-AI. This list is not exhaustive, and we are actively working on adding more features to Vizro-AI. | Feature type | Feature | Availability | -|----------------------|------------------------------------------------------------------------------------------------------------------------------------------|-------------| -| **Components** | [Graph](https://vizro.readthedocs.io/en/stable/pages/user-guides/graph/) | ✔ | -| | [AG Grid](https://vizro.readthedocs.io/en/stable/pages/user-guides/table/#ag-grid) | ✔ | -| | [Card](https://vizro.readthedocs.io/en/stable/pages/user-guides/card-button/) | ✔ | -| | [Button](https://vizro.readthedocs.io/en/stable/pages/user-guides/card-button/) | ✖ | -| | [Tabs](https://vizro.readthedocs.io/en/stable/pages/user-guides/tabs/) | ✖ | -| | [Containers](https://vizro.readthedocs.io/en/stable/pages/user-guides/container/) | ✖ | -| **Controls** | [Filter](https://vizro.readthedocs.io/en/stable/pages/user-guides/filters/) | ✔ | -| | [Parameter](https://vizro.readthedocs.io/en/stable/pages/user-guides/parameters/) | ✖ | -| **Navigation** | [Default navigation](https://vizro.readthedocs.io/en/stable/pages/user-guides/navigation/#use-the-default-navigation) | ✔ | -| | [Custom navigation](https://vizro.readthedocs.io/en/stable/pages/user-guides/navigation/#customize-the-navigation-bar) | ✖ | -| **Layout** | [Layout](https://vizro.readthedocs.io/en/stable/pages/user-guides/layouts/) | ✔ | -| **Dashboard header** | [Dashboard title](https://vizro.readthedocs.io/en/stable/pages/user-guides/dashboard/) | ✔ | -| | [Logo](https://vizro.readthedocs.io/en/stable/pages/user-guides/dashboard/) | ✖ | -| **Actions** | [Pre-defined actions](https://vizro.readthedocs.io/en/stable/pages/user-guides/actions/#pre-defined-actions/) | ✖ | -| | [Filter interaction between charts](https://vizro.readthedocs.io/en/stable/pages/user-guides/actions/#filter-data-by-clicking-on-chart/) | ✖ | -| | [Custom actions](https://vizro.readthedocs.io/en/stable/pages/user-guides/actions/#custom-actions/) | ✖ | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------ | +| **Components** | [Graph](https://vizro.readthedocs.io/en/stable/pages/user-guides/graph/) | ✔ | +| | [AG Grid](https://vizro.readthedocs.io/en/stable/pages/user-guides/table/#ag-grid) | ✔ | +| | [Card](https://vizro.readthedocs.io/en/stable/pages/user-guides/card-button/) | ✔ | +| | [Button](https://vizro.readthedocs.io/en/stable/pages/user-guides/card-button/) | ✖ | +| | [Tabs](https://vizro.readthedocs.io/en/stable/pages/user-guides/tabs/) | ✖ | +| | [Containers](https://vizro.readthedocs.io/en/stable/pages/user-guides/container/) | ✖ | +| **Controls** | [Filter](https://vizro.readthedocs.io/en/stable/pages/user-guides/filters/) | ✔ | +| | [Parameter](https://vizro.readthedocs.io/en/stable/pages/user-guides/parameters/) | ✖ | +| **Navigation** | [Default navigation](https://vizro.readthedocs.io/en/stable/pages/user-guides/navigation/#use-the-default-navigation) | ✔ | +| | [Custom navigation](https://vizro.readthedocs.io/en/stable/pages/user-guides/navigation/#customize-the-navigation-bar) | ✖ | +| **Layout** | [Layout](https://vizro.readthedocs.io/en/stable/pages/user-guides/layouts/) | ✔ | +| **Dashboard header** | [Dashboard title](https://vizro.readthedocs.io/en/stable/pages/user-guides/dashboard/) | ✔ | +| | [Logo](https://vizro.readthedocs.io/en/stable/pages/user-guides/dashboard/) | ✖ | +| **Actions** | [Pre-defined actions](https://vizro.readthedocs.io/en/stable/pages/user-guides/actions/#pre-defined-actions/) | ✖ | +| | [Filter interaction between charts](https://vizro.readthedocs.io/en/stable/pages/user-guides/actions/#filter-data-by-clicking-on-chart/) | ✖ | +| | [Custom actions](https://vizro.readthedocs.io/en/stable/pages/user-guides/actions/#custom-actions/) | ✖ | If a feature you need for your dashboard isn't currently supported by Vizro-AI you can retrieve the dashboard code and add it by hand before running the dashboard. diff --git a/vizro-core/CHANGELOG.md b/vizro-core/CHANGELOG.md index 1780c8e6e..25cdb2a92 100644 --- a/vizro-core/CHANGELOG.md +++ b/vizro-core/CHANGELOG.md @@ -17,8 +17,7 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse ## Removed -- Removed all CSS variables from `variables.css` and `token_names.css`, replacing them with CSS variables from `vizro-bootstrap.min.css`. - Refer to [`vizro-bootstrap.min.css](https://github.com/mckinsey/vizro/blob/main/vizro-core/src/vizro/static/css/vizro-bootstrap.min.css) for the updated CSS variables. ([#886](https://github.com/mckinsey/vizro/pull/886)) +- Removed all CSS variables from `variables.css` and `token_names.css`, replacing them with CSS variables from `vizro-bootstrap.min.css`. Refer to [\`vizro-bootstrap.min.css](https://github.com/mckinsey/vizro/blob/main/vizro-core/src/vizro/static/css/vizro-bootstrap.min.css) for the updated CSS variables. ([#886](https://github.com/mckinsey/vizro/pull/886)) ## Added diff --git a/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md b/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md index 7c0d58d4f..4abc0f11e 100644 --- a/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md +++ b/vizro-core/changelog.d/20241114_103750_antony.milne_mdformat.md @@ -10,36 +10,42 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + + + + + + -[Alexey Snigir](https://github.com/l0uden), -[Antony Milne](https://github.com/antonymilne), -[Dan Dumitriu](https://github.com/dandumitriu1), -[Huong Li Nguyen](https://github.com/huong-li-nguyen), -[Jo Stichbury](https://github.com/stichbury), -[Joseph Perkins](https://github.com/Joseph-Perkins), -[Lingyi Zhang](https://github.com/lingyielia), -[Maximilian Schulz](https://github.com/maxschulz-COL), -[Nadija Graca](https://github.com/nadijagraca), and -[Petar Pejovic](https://github.com/petar-qb) - +[Alexey Snigir](https://github.com/l0uden), [Antony Milne](https://github.com/antonymilne), [Dan Dumitriu](https://github.com/dandumitriu1), [Huong Li Nguyen](https://github.com/huong-li-nguyen), [Jo Stichbury](https://github.com/stichbury), [Joseph Perkins](https://github.com/Joseph-Perkins), [Lingyi Zhang](https://github.com/lingyielia), [Maximilian Schulz](https://github.com/maxschulz-COL), [Nadija Graca](https://github.com/nadijagraca), and [Petar Pejovic](https://github.com/petar-qb) + + ## Previous team members and code contributors + -[Ann Marie Ward](https://github.com/AnnMarieW), [Anna Xiong](https://github.com/Anna-Xiong), [Annie Wachsmuth](https://github.com/anniecwa), [ataraexia](https://github.com/ataraexia), [axa99](https://github.com/axa99), [Bhavana Sundar](https://github.com/bhavanaeh), [Bo Xu](https://github.com/boxuboxu), [Chiara Pullem](https://github.com/chiara-sophie), [Denis Lebedev](https://github.com/DenisLebedevMcK), [Elena Fridman](https://github.com/EllenWie), [Ferida Mohammed](https://github.com/feridaaa), [Hamza Oza](https://github.com/hamzaoza), [Hansaem Park](https://github.com/sammitako), [Hilary Ivy](https://github.com/hxe00570), [Jasmine Wu](https://github.com/jazwu), [Jenelle Yonkman](https://github.com/yonkmanjl), [Jingjing Guo](https://github.com/jjguo-mck), [Juan Luis Cano Rodríguez](https://github.com/astrojuanlu), [Kee Wen Ng](https://github.com/KeeWenNgQB), [Leon Nallamuthu](https://github.com/leonnallamuthu), [Lydia Pitts](https://github.com/LydiaPitts), [Ned Letcher](https://github.com/ned2), [Nikolaos Tsaousis](https://github.com/tsanikgr), [njmcgrat](https://github.com/njmcgrat), [Oleksandr Serdiuk](https://github.com/oserdiuk-lohika), [Prateek Bajaj](https://github.com/prateekdev552), [Qiuyi Chen](https://github.com/Qiuyi-Chen), [Rashida Kanchwala](https://github.com/rashidakanchwala), [Riley Dou](https://github.com/rilieo), [Rosheen C.](https://github.com/rc678), [Sylvie Zhang](https://github.com/sylviezhang37), and [Upekesha Ngugi](https://github.com/upekesha). +[Ann Marie Ward](https://github.com/AnnMarieW), [Anna Xiong](https://github.com/Anna-Xiong), [Annie Wachsmuth](https://github.com/anniecwa), [ataraexia](https://github.com/ataraexia), [axa99](https://github.com/axa99), [Bhavana Sundar](https://github.com/bhavanaeh), [Bo Xu](https://github.com/boxuboxu), [Chiara Pullem](https://github.com/chiara-sophie), [Denis Lebedev](https://github.com/DenisLebedevMcK), [Elena Fridman](https://github.com/EllenWie), [Ferida Mohammed](https://github.com/feridaaa), [Hamza Oza](https://github.com/hamzaoza), [Hansaem Park](https://github.com/sammitako), [Hilary Ivy](https://github.com/hxe00570), [Jasmine Wu](https://github.com/jazwu), [Jenelle Yonkman](https://github.com/yonkmanjl), [Jingjing Guo](https://github.com/jjguo-mck), [Juan Luis Cano Rodríguez](https://github.com/astrojuanlu), [Kee Wen Ng](https://github.com/KeeWenNgQB), [Leon Nallamuthu](https://github.com/leonnallamuthu), [Lydia Pitts](https://github.com/LydiaPitts), [Ned Letcher](https://github.com/ned2), [Nikolaos Tsaousis](https://github.com/tsanikgr), [njmcgrat](https://github.com/njmcgrat), [Oleksandr Serdiuk](https://github.com/oserdiuk-lohika), [Prateek Bajaj](https://github.com/prateekdev552), [Qiuyi Chen](https://github.com/Qiuyi-Chen), [Rashida Kanchwala](https://github.com/rashidakanchwala), [Riley Dou](https://github.com/rilieo), [Rosheen C.](https://github.com/rc678), [Sylvie Zhang](https://github.com/sylviezhang37), and [Upekesha Ngugi](https://github.com/upekesha). with thanks to Sam Bourton and Kevin Staight for sponsorship, inspiration and guidance, -and special thanks to -[Wesley Leong](https://github.com/wesleyleong), [Jonas Kemper](https://github.com/jonasrk) and team for origination and support +and special thanks to [Wesley Leong](https://github.com/wesleyleong), [Jonas Kemper](https://github.com/jonasrk) and team for origination and support (plus everyone else who helped to test, guide, support and encourage development) + diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index 08103c472..1ccbb0a3d 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -4,12 +4,10 @@ This guide shows you how to use cards and buttons to visualize and interact with ## Cards -The [`Card`][vizro.models.Card] is a flexible and extensible component that enables customization via markdown text. -Refer to any online guide for [basic markdown usage](https://markdown-guide.readthedocs.io/en/latest/). +The [`Card`][vizro.models.Card] is a flexible and extensible component that enables customization via markdown text. Refer to any online guide for [basic markdown usage](https://markdown-guide.readthedocs.io/en/latest/). You can add a [`Card`][vizro.models.Card] to your dashboard by inserting the [`Card`][vizro.models.Card] into the `components` argument of the [`Page`][vizro.models.Page]. - !!! example "Card" === "app.py" ```{.python pycafe-link} @@ -32,28 +30,26 @@ You can add a [`Card`][vizro.models.Card] to your dashboard by inserting the [`C Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - Commodi repudiandae consequuntur voluptatum. - title: Card Title - type: card - title: Card + - components: + - text: | + Commodi repudiandae consequuntur voluptatum. + title: Card Title + type: card + title: Card ``` - === "Result" - [![Card]][Card] - [Card]: ../../assets/user_guides/components/card.png + === "Result" + [![Card]][card] ### Customize card text -The [`Card`][vizro.models.Card] uses the `dcc.Markdown` component from Dash as its underlying text component. -For more details on customizing the markdown text, refer to the [`dcc.Markdown` component documentation](https://dash.plotly.com/dash-core-components/markdown). -Based on examples from Dash, the [`Card`][vizro.models.Card] model supports the following: +The [`Card`][vizro.models.Card] uses the `dcc.Markdown` component from Dash as its underlying text component. For more details on customizing the markdown text, refer to the [`dcc.Markdown` component documentation](https://dash.plotly.com/dash-core-components/markdown). Based on examples from Dash, the [`Card`][vizro.models.Card] model supports the following: - Headers - Emphasis @@ -130,58 +126,58 @@ Based on examples from Dash, the [`Card`][vizro.models.Card] model supports the Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - # Header level 1

- - ## Header level 2

- - ### Header level 3

- - #### Header level 4

- type: card - - text: | - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - - Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. - title: Paragraphs - type: card - - text: | - > - > A block quote is a long quotation, indented to create a separate block of text. - > - title: Block Quotes - type: card - - text: | - * Item A - * Sub Item 1 - * Sub Item 2 - * Item B - title: Lists - type: card - - text: | - This word will be *italic* - - This word will be **bold** - - This word will be _**bold and italic**_ - title: Emphasis - type: card - title: Customizing Text + - components: + - text: | + # Header level 1

+ + ## Header level 2

+ + ### Header level 3

+ + #### Header level 4

+ type: card + - text: | + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + + Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. + title: Paragraphs + type: card + - text: | + > + > A block quote is a long quotation, indented to create a separate block of text. + > + title: Block Quotes + type: card + - text: | + * Item A + * Sub Item 1 + * Sub Item 2 + * Item B + title: Lists + type: card + - text: | + This word will be *italic* + + This word will be **bold** + + This word will be _**bold and italic**_ + title: Emphasis + type: card + title: Customizing Text ``` - === "Result" - [![CardText]][CardText] - [CardText]: ../../assets/user_guides/components/card_text.png + === "Result" + [![CardText]][cardtext] ### Place an image on a card @@ -189,11 +185,10 @@ Images can be added to the `text` parameter by using the standard markdown synta `![Image ALT text](Image URL)` -An image ALT text offers a description to your image and serves as a text placeholder or to improve the -accessibility of your app. Providing an image ALT text is optional. +An image ALT text offers a description to your image and serves as a text placeholder or to improve the accessibility of your app. Providing an image ALT text is optional. 1. To use a relative Image URL, place an image of your choice into your `assets` folder first -2. Use markdown to render your image by using one of the following syntax: +1. Use markdown to render your image by using one of the following syntax: - Relative Image URL: `![Image ALT text](/path/to/image.png)` - Absolute Image URL: `![Image ALT text](https://XXXXXX)` @@ -237,11 +232,11 @@ accessibility of your app. Providing an image ALT text is optional. - components: - text: | ![continent](assets/images/continents/africa.svg) - + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. title: My card with image! type: card @@ -249,34 +244,32 @@ accessibility of your app. Providing an image ALT text is optional. ``` === "Result" [![CardImageDefault]][CardImageDefault] - + [CardImageDefault]: ../../assets/user_guides/components/card_image_default.png !!! note - - Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed - to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. + Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. You might notice that the image is quite large. You'll find out how to style images in terms of their position and size in the next section. - ### Style a card image To change the size or position of the image, add a URL hash to your image like this: `![Image ALT text](Image URL#my-image)` -Note the added URL hash `#my-image`. Now create a CSS file placed in your `assets` folder -and give an attribute selector to select images with that matching URL hash. +Note the added URL hash `#my-image`. Now create a CSS file placed in your `assets` folder and give an attribute selector to select images with that matching URL hash. !!! example "Card with styled image" === "images.css" + ```css img[src*="#my-image"] { - width: 120px; - height: 120px; + width: 120px; + height: 120px; } ``` + === "app.py" ```py import vizro.models as vm @@ -313,23 +306,22 @@ and give an attribute selector to select images with that matching URL hash. # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![](assets/images/continents/europe.svg#my-image) + - components: + - text: | + ![](assets/images/continents/europe.svg#my-image) - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - title: My card with image! - type: card - title: Styling Images + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + title: My card with image! + type: card + title: Styling Images ``` - === "Result" - [![CardImageStyled]][CardImageStyled] - [CardImageStyled]: ../../assets/user_guides/components/card_image_styled.png + === "Result" + [![CardImageStyled]][cardimagestyled] Use the following pre-defined URL hashes in your image path to apply Vizro's default styling. @@ -341,12 +333,14 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def !!! example "Card with floating image" === "images.css" + ```css img[src*="#my-image"] { - width: 120px; - height: 120px; + width: 120px; + height: 120px; } ``` + === "app.py" ```py import vizro.models as vm @@ -389,29 +383,28 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![](assets/images/continents/europe.svg#my-image#floating-right) + - components: + - text: | + ![](assets/images/continents/europe.svg#my-image#floating-right) - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. + Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. - title: My card with floating image! - type: card - title: Floating Images + Culpa officia aut! Impedit sit sunt quaerat, odit, tenetur error, harum nesciunt ipsum debitis quas. + title: My card with floating image! + type: card + title: Floating Images ``` - === "Result" - [![CardImageFloating]][CardImageFloating] - [CardImageFloating]: ../../assets/user_guides/components/card_image_floating.png + === "Result" + [![CardImageFloating]][cardimagefloating] #### Card with icon @@ -442,38 +435,34 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![](assets/images/icons/hypotheses.svg#icon-top) + - components: + - text: | + ![](assets/images/icons/hypotheses.svg#icon-top) - ### Card Title + ### Card Title - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut fringilla dictum lacus eget fringilla. - Maecenas in various nibh, quis venenatis nulla. Integer et libero ultrices, scelerisque velit sed. - type: card - title: Card with icon + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut fringilla dictum lacus eget fringilla. + Maecenas in various nibh, quis venenatis nulla. Integer et libero ultrices, scelerisque velit sed. + type: card + title: Card with icon ``` - === "Result" - [![CardIcon]][CardIcon] - - [CardIcon]: ../../assets/user_guides/components/card_icon.png + === "Result" + [![CardIcon]][cardicon] ### Make an icon responsive to theme switch -To make an icon responsive to the theme switch, override the value of the [`filter` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/filter). -The `filter` CSS property lets you add visual effects to elements using different functions. In our example, we're using the `--inverse-color` CSS variable from the Vizro theme. -It uses the CSS `invert()` function to flip the color of the icon when you switch themes. Note that this only works if your initial icon has a white fill color. If your icon is not white, you can change its color by adding `fill="white"` to the SVG code. -Assign the predefined CSS variable `--inverse-color` to the `filter` property of your selected icon. +To make an icon responsive to the theme switch, override the value of the [`filter` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/filter). The `filter` CSS property lets you add visual effects to elements using different functions. In our example, we're using the `--inverse-color` CSS variable from the Vizro theme. It uses the CSS `invert()` function to flip the color of the icon when you switch themes. Note that this only works if your initial icon has a white fill color. If your icon is not white, you can change its color by adding `fill="white"` to the SVG code. Assign the predefined CSS variable `--inverse-color` to the `filter` property of your selected icon. ```css img[src*="#my-image"] { - filter: var(--inverse-color); + filter: var(--inverse-color); } ``` @@ -482,18 +471,15 @@ img[src*="#my-image"] { ### Create a navigation card -This section describes how to use the [`Card`][vizro.models.Card] component to create a navigation card, -enabling users to navigate to another page by clicking on the card area. +This section describes how to use the [`Card`][vizro.models.Card] component to create a navigation card, enabling users to navigate to another page by clicking on the card area. -For a button-style link navigation component, see the [separate guide on creating a link button](#create-a-link-button). -To configure the navigation panel on the left hand side of the screen, refer to the -[separate guide on navigation](navigation.md). +For a button-style link navigation component, see the [separate guide on creating a link button](#create-a-link-button). To configure the navigation panel on the left hand side of the screen, refer to the [separate guide on navigation](navigation.md). To create a navigation card: 1. Insert the [`Card`][vizro.models.Card] into the `components` argument of the [`Page`][vizro.models.Page]. -2. Pass your markdown text to the `Card.text`. -3. Pass a relative or absolute URL to the `Card.href`. +1. Pass your markdown text to the `Card.text`. +1. Pass a relative or absolute URL to the `Card.href`. !!! example "Navigation Card" === "app.py" @@ -537,72 +523,65 @@ To create a navigation card: Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ### Filters and parameters - - Leads to the first page on click - href: /filters-and-parameters - type: card - - text: | - ### Google - External Link - - Leads to an external link on click. - href: https://google.com - type: card - title: Homepage - - components: - - figure: - _target_: scatter - color: sepal_width - data_frame: iris - x: sepal_length - y: petal_width - type: graph - title: Filters and parameters + - components: + - text: | + ### Filters and parameters + + Leads to the first page on click + href: /filters-and-parameters + type: card + - text: | + ### Google - External Link + + Leads to an external link on click. + href: https://google.com + type: card + title: Homepage + - components: + - figure: + _target_: scatter + color: sepal_width + data_frame: iris + x: sepal_length + y: petal_width + type: graph + title: Filters and parameters ``` - === "Result" - [![NavCard]][NavCard] - [NavCard]: ../../assets/user_guides/components/nav_card.png + === "Result" + [![NavCard]][navcard] If you now click on the card area, you should automatically be redirected to the relevant `href`. !!! note - When using the [`Card`][vizro.models.Card], keep the following in mind: - If the href given is a relative URL, it should match the `path` of the [`Page`][vizro.models.Page] that the [`Card`][vizro.models.Card] should navigate to. - If the href given is an absolute link, it should start with `https://` or an equivalent protocol. - ### Create a KPI card -To create a KPI card, you can use the existing KPI card functions from [`vizro.figures`](../API-reference/figure-callables.md). -Unlike the static text card `vm.Card`, a KPI card must be created using a figure function, -which enables the text content of the KPI to change based on input from controls or actions. + +To create a KPI card, you can use the existing KPI card functions from [`vizro.figures`](../API-reference/figure-callables.md). Unlike the static text card `vm.Card`, a KPI card must be created using a figure function, which enables the text content of the KPI to change based on input from controls or actions. For detailed examples on how to create a KPI card, refer to the [figure user guide on KPI cards](figure.md#key-performance-indicator-kpi-cards). ## Buttons -The Button component is commonly used for interactive dashboard interactions -such as form submissions, navigation links, and other action triggers. - -To add a [`Button`][vizro.models.Button], insert it into the `components` argument of the -[`Page`][vizro.models.Page]. +The Button component is commonly used for interactive dashboard interactions such as form submissions, navigation links, and other action triggers. +To add a [`Button`][vizro.models.Button], insert it into the `components` argument of the [`Page`][vizro.models.Page]. ### Customize button text You can configure the `text` argument to alter the display text of the [`Button`][vizro.models.Button]. !!! example "Customize text" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -616,26 +595,24 @@ You can configure the `text` argument to alter the display text of the [`Button` dashboard = vm.Dashboard(pages=[page]) Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - components: - - type: button - text: I'm a button! + - type: button + text: I'm a button! title: Button with text ``` - === "Result" - [![ButtonText]][ButtonText] - - [ButtonText]: ../../assets/user_guides/components/button_text.png + === "Result" + [![ButtonText]][buttontext] ### Create a link button -To navigate to a different page using a button with an anchor tag, assign an absolute or relative URL to the -`Button.href`. +To navigate to a different page using a button with an anchor tag, assign an absolute or relative URL to the `Button.href`. ```python import vizro.models as vm @@ -645,16 +622,11 @@ vm.Button(text="Leave us a star! ⭐", href="https://github.com/mckinsey/vizro") ### Attach an action -You can use the [`Button`][vizro.models.Button] to trigger predefined action functions, such as exporting data. -To explore the available options for [`Actions`][vizro.models.Action], refer to our [API reference][vizro.actions]. -Use the `Button.actions` argument to specify which action function executes when the button is clicked. - -The example below demonstrates how to configure a button to export the filtered data of a target chart using the -[export_data][vizro.actions.export_data] action function. +You can use the [`Button`][vizro.models.Button] to trigger predefined action functions, such as exporting data. To explore the available options for [`Actions`][vizro.models.Action], refer to our [API reference][vizro.actions]. Use the `Button.actions` argument to specify which action function executes when the button is clicked. +The example below demonstrates how to configure a button to export the filtered data of a target chart using the [export_data][vizro.actions.export_data] action function. !!! example "Button with action" - === "app.py" ```{.python pycafe-link} import vizro.models as vm @@ -690,29 +662,30 @@ The example below demonstrates how to configure a button to export the filtered Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - components: - - figure: - _target_: scatter - x: sepal_width - y: sepal_length - color: species - size: petal_length - data_frame: iris - id: scatter_chart - type: graph - - type: button - text: Export data - id: export_data - actions: - - function: - _target_: export_data - targets: - - scatter_chart + - figure: + _target_: scatter + x: sepal_width + y: sepal_length + color: species + size: petal_length + data_frame: iris + id: scatter_chart + type: graph + - type: button + text: Export data + id: export_data + actions: + - function: + _target_: export_data + targets: + - scatter_chart controls: - column: species selector: @@ -728,14 +701,13 @@ The example below demonstrates how to configure a button to export the filtered - [1] title: My first page ``` - === "Result" - [![Button]][Button] - [Button]: ../../assets/user_guides/components/button.png + === "Result" + [![Button]][button] ### Use as a control -The [`Button`][vizro.models.Button] component is currently reserved to be used inside the main panel (right-side) of the dashboard. -However, there might be use cases where one would like to place the `Button` inside the control panel (left-side) with the other controls. + +The [`Button`][vizro.models.Button] component is currently reserved to be used inside the main panel (right-side) of the dashboard. However, there might be use cases where one would like to place the `Button` inside the control panel (left-side) with the other controls. In this case, follow the user-guide outlined for [creating custom components](custom-components.md) and manually add the `Button` as a valid type to the `controls` argument by running the following lines before your dashboard configurations: @@ -748,3 +720,12 @@ vm.Page.add_type("controls", vm.Button) # Add dashboard configurations below ... ``` + +[button]: ../../assets/user_guides/components/button.png +[buttontext]: ../../assets/user_guides/components/button_text.png +[card]: ../../assets/user_guides/components/card.png +[cardicon]: ../../assets/user_guides/components/card_icon.png +[cardimagefloating]: ../../assets/user_guides/components/card_image_floating.png +[cardimagestyled]: ../../assets/user_guides/components/card_image_styled.png +[cardtext]: ../../assets/user_guides/components/card_text.png +[navcard]: ../../assets/user_guides/components/nav_card.png diff --git a/vizro-core/docs/pages/user-guides/custom-css.md b/vizro-core/docs/pages/user-guides/custom-css.md index 3c8ea1979..4a31aedbb 100755 --- a/vizro-core/docs/pages/user-guides/custom-css.md +++ b/vizro-core/docs/pages/user-guides/custom-css.md @@ -295,12 +295,8 @@ It's essential to understand the relationship between the targeted CSS class or ## Common examples ### Make your CSS responsive to theme switches with variables -To ensure your CSS adapts to theme changes, we recommend using CSS variables (`var`) whenever possible. For a -comprehensive list of available variable names, refer to the -[Bootstrap documentation](https://getbootstrap.com/docs/5.3/customize/css-variables/). Note that our -Bootstrap stylesheet is still under development, so not all Bootstrap variables are currently available. -Additionally, you can define your own CSS variables, as demonstrated in the example on -[changing the container background color](#change-the-styling-of-a-container). + +To ensure your CSS adapts to theme changes, we recommend using CSS variables (`var`) whenever possible. For a comprehensive list of available variable names, refer to the [Bootstrap documentation](https://getbootstrap.com/docs/5.3/customize/css-variables/). Note that our Bootstrap stylesheet is still under development, so not all Bootstrap variables are currently available. Additionally, you can define your own CSS variables, as demonstrated in the example on [changing the container background color](#change-the-styling-of-a-container). ### Turn off page title diff --git a/vizro-core/examples/visual-vocabulary/README.md b/vizro-core/examples/visual-vocabulary/README.md index 3b298520e..e59b3103c 100644 --- a/vizro-core/examples/visual-vocabulary/README.md +++ b/vizro-core/examples/visual-vocabulary/README.md @@ -2,14 +2,11 @@ ### Welcome to our visual vocabulary dashboard! 🎨 -This dashboard serves as a comprehensive guide for selecting and creating various types of charts. It helps you decide -when to use each chart type, and offers sample Python code using [Plotly](https://plotly.com/python/), and -instructions for embedding these charts into a [Vizro](https://github.com/mckinsey/vizro) dashboard. +This dashboard serves as a comprehensive guide for selecting and creating various types of charts. It helps you decide when to use each chart type, and offers sample Python code using [Plotly](https://plotly.com/python/), and instructions for embedding these charts into a [Vizro](https://github.com/mckinsey/vizro) dashboard. The charts in this dashboard are designed to make it easy for anyone to create beautiful and sophisticated visuals. -Our goal is to help you understand best practices in data visualization, ensure your charts effectively communicate -your message, and streamline the creation of high-quality, interactive visualizations. +Our goal is to help you understand best practices in data visualization, ensure your charts effectively communicate your message, and streamline the creation of high-quality, interactive visualizations. Created by: @@ -19,12 +16,9 @@ Created by: Inspired by: -- [The FT Visual Vocabulary](https://github.com/Financial-Times/chart-doctor/blob/main/visual-vocabulary/README.md): - [Alan Smith](https://github.com/alansmithy), [Chris Campbell](https://github.com/digitalcampbell), Ian Bott, - Liz Faunce, Graham Parrish, Billy Ehrenberg, Paul McCallum, [Martin Stabe](https://github.com/martinstabe). +- [The FT Visual Vocabulary](https://github.com/Financial-Times/chart-doctor/blob/main/visual-vocabulary/README.md): [Alan Smith](https://github.com/alansmithy), [Chris Campbell](https://github.com/digitalcampbell), Ian Bott, Liz Faunce, Graham Parrish, Billy Ehrenberg, Paul McCallum, [Martin Stabe](https://github.com/martinstabe). -- [The Graphic Continuum](https://www.informationisbeautifulawards.com/showcase/611-the-graphic-continuum): - Jon Swabish and Severino Ribecca +- [The Graphic Continuum](https://www.informationisbeautifulawards.com/showcase/611-the-graphic-continuum): Jon Swabish and Severino Ribecca Credits and sources: @@ -102,13 +96,12 @@ The dashboard is still in development. Below is an overview of the chart types f Contributions are welcome! To contribute a chart, follow the steps below: 1. Check that a `svg` file named after the chart type is contained in the [assets](https://github.com/mckinsey/vizro/tree/main/vizro-core/examples/visual-vocabulary/assets/images/charts) folder. If not, [raise an issue](https://github.com/mckinsey/vizro/issues) in the repository. -2. Add a `.py` file containing a code example of the chart type in the `pages/examples` folder, for instance, `area.py`. Take a look at existing examples. -3. Create a new page for the chart type and add it to the relevant category `.py` file such as `correlation.py`, - `deviation.py`, `distribution.py`, etc. Ensure you add the page to the list of `pages` at the end of the `.py` file. -4. Remove the `IncompletePage(..)` entry for that chart type in `chart_groups.py`. -5. Update this `README.md` with the new chart type, its status, category, and API links. +1. Add a `.py` file containing a code example of the chart type in the `pages/examples` folder, for instance, `area.py`. Take a look at existing examples. +1. Create a new page for the chart type and add it to the relevant category `.py` file such as `correlation.py`, `deviation.py`, `distribution.py`, etc. Ensure you add the page to the list of `pages` at the end of the `.py` file. +1. Remove the `IncompletePage(..)` entry for that chart type in `chart_groups.py`. +1. Update this `README.md` with the new chart type, its status, category, and API links. ## How to run the example locally 1. Run the example with the command `hatch run example visual-vocabulary`. -2. You should now be able to access the app locally via http://127.0.0.1:8051/. +1. You should now be able to access the app locally via http://127.0.0.1:8051/. From 9360c3d2c96290ead1c512fcffc62d764fe0c911 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Thu, 28 Nov 2024 17:28:45 +0000 Subject: [PATCH 07/54] Fix merge again --- .../docs/pages/user-guides/card-button.md | 31 +++++++++---------- .../docs/pages/user-guides/custom-css.md | 12 ++++--- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index 1ccbb0a3d..0cc51009b 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -223,29 +223,27 @@ An image ALT text offers a description to your image and serves as a text placeh PyCafe logoRun and edit this code in PyCafe - === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example pages: - - components: - - text: | - ![continent](assets/images/continents/africa.svg) - - Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. - - Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. - - Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. - title: My card with image! - type: card - title: Placing Images + - components: + - text: | + ![continent](assets/images/continents/africa.svg) + + Commodi repudiandae consequuntur voluptatum laborum numquam blanditiis harum quisquam eius sed odit. + + Fugiat iusto fuga praesentium option, eaque rerum! Provident similique accusantium nemo autem. + + Obcaecati tenetur iure eius earum ut molestias architecto voluptate aliquam nihil, eveniet aliquid. + title: My card with image! + type: card + title: Placing Images ``` + === "Result" - [![CardImageDefault]][CardImageDefault] - - [CardImageDefault]: ../../assets/user_guides/components/card_image_default.png + [![CardImageDefault]][cardimagedefault] !!! note Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. @@ -725,6 +723,7 @@ vm.Page.add_type("controls", vm.Button) [buttontext]: ../../assets/user_guides/components/button_text.png [card]: ../../assets/user_guides/components/card.png [cardicon]: ../../assets/user_guides/components/card_icon.png +[cardimagedefault]: ../../assets/user_guides/components/card_image_default.png [cardimagefloating]: ../../assets/user_guides/components/card_image_floating.png [cardimagestyled]: ../../assets/user_guides/components/card_image_styled.png [cardtext]: ../../assets/user_guides/components/card_text.png diff --git a/vizro-core/docs/pages/user-guides/custom-css.md b/vizro-core/docs/pages/user-guides/custom-css.md index 4a31aedbb..1548417e8 100755 --- a/vizro-core/docs/pages/user-guides/custom-css.md +++ b/vizro-core/docs/pages/user-guides/custom-css.md @@ -219,14 +219,16 @@ It's essential to understand the relationship between the targeted CSS class or -```html {title="HTML structure of a `Card`"} - +```html title="HTML structure of a card"
-
-

Lorem ipsum dolor sit amet consectetur adipisicing elit.

-
+
+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. +

+
``` + - **Main element with `id`:** There is a `
` with our `id="custom-card"`. From faec33416cec6a55f6f4f6dc16246624dfba25fd Mon Sep 17 00:00:00 2001 From: Antony Milne <49395058+antonymilne@users.noreply.github.com> Date: Fri, 29 Nov 2024 09:40:45 +0000 Subject: [PATCH 08/54] Update vizro-ai/docs/index.md --- vizro-ai/docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index 1fe4f93d2..e4ec04a48 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -14,6 +14,7 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- +FIXME: maybe use two new lines between each [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
- :fontawesome-solid-keyboard:{ .lg .middle } __Get hands-on__ From 3de8fee00672289bd8ddbdde6f118b229a820359 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 09:42:12 +0000 Subject: [PATCH 09/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- vizro-ai/docs/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index e4ec04a48..0d1f18f5a 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -14,8 +14,7 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- -FIXME: maybe use two new lines between each - [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
+FIXME: maybe use two new lines between each [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
- :fontawesome-solid-keyboard:{ .lg .middle } __Get hands-on__ From 692c05ec42397b1097fe3285793b82aeef0eb282 Mon Sep 17 00:00:00 2001 From: Antony Milne <49395058+antonymilne@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:04:43 +0000 Subject: [PATCH 10/54] Update vizro-core/CHANGELOG.md --- vizro-core/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-core/CHANGELOG.md b/vizro-core/CHANGELOG.md index 25cdb2a92..a515e182d 100644 --- a/vizro-core/CHANGELOG.md +++ b/vizro-core/CHANGELOG.md @@ -17,7 +17,7 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse ## Removed -- Removed all CSS variables from `variables.css` and `token_names.css`, replacing them with CSS variables from `vizro-bootstrap.min.css`. Refer to [\`vizro-bootstrap.min.css](https://github.com/mckinsey/vizro/blob/main/vizro-core/src/vizro/static/css/vizro-bootstrap.min.css) for the updated CSS variables. ([#886](https://github.com/mckinsey/vizro/pull/886)) +- Removed all CSS variables from `variables.css` and `token_names.css`, replacing them with CSS variables from `vizro-bootstrap.min.css`. Refer to [`vizro-bootstrap.min.css`](https://github.com/mckinsey/vizro/blob/main/vizro-core/src/vizro/static/css/vizro-bootstrap.min.css) for the updated CSS variables. ([#886](https://github.com/mckinsey/vizro/pull/886)) ## Added From 3ec75d3d7c0e1a6d143c7eba8321e6fda973f89a Mon Sep 17 00:00:00 2001 From: Antony Milne <49395058+antonymilne@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:04:52 +0000 Subject: [PATCH 11/54] Update vizro-core/docs/index.md --- vizro-core/docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index a30d663f5..e18e710aa 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -8,6 +8,7 @@ Vizro is a toolkit for creating modular data visualization applications. --- +FIXME: maybe use two new lines between each [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) - :fontawesome-solid-keyboard:{ .lg .middle } __Vizro features__ From f64452d870cc3a754785e03b32be162fdb23754b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:05:21 +0000 Subject: [PATCH 12/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- vizro-core/docs/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index e18e710aa..9ebfd181a 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -8,8 +8,7 @@ Vizro is a toolkit for creating modular data visualization applications. --- -FIXME: maybe use two new lines between each - [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) +FIXME: maybe use two new lines between each [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) - :fontawesome-solid-keyboard:{ .lg .middle } __Vizro features__ From 13d1732ff977e20987839d16df9a3fd07a21352e Mon Sep 17 00:00:00 2001 From: Antony Milne <49395058+antonymilne@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:07:20 +0000 Subject: [PATCH 13/54] Update .pre-commit-config.yaml --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3b6c066b5..3ace1e43c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -93,7 +93,7 @@ repos: --wrap=no, --align-semantic-breaks-in-lists, ] - exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference + exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md additional_dependencies: - mdformat-mkdocs[recommended]==3.1.1 From 243cfc46849915dec3b5da4cc888ed2884d5ceb7 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 10:52:58 +0000 Subject: [PATCH 14/54] Update run-vizro-ai-dashboard.md --- .../docs/pages/user-guides/run-vizro-ai-dashboard.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md index 2ae3018ac..05111f5f9 100644 --- a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md +++ b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md @@ -8,7 +8,7 @@ This guide offers insights into different ways of running `VizroAI.dashboard` to ## Run Vizro-AI dashboard !!! example "Generated dashboard" - === "Code" + === "Prompt" ```py import vizro.plotly.express as px from vizro_ai import VizroAI @@ -34,11 +34,8 @@ This guide offers insights into different ways of running `VizroAI.dashboard` to ``` === "Result" - \[!\[VizroAIDashboardPage1\]\]\[VizroAIDashboardPage1\] + ![VizroAIDashboardPage1](../../assets/user_guides/dashboard/dashboard2_page1.png) -``` -[VizroAIDashboardPage1]: ../../assets/user_guides/dashboard/dashboard2_page1.png -``` This triggers the dashboard building process. Once Vizro-AI finishes the dashboard generation process, you can now launch the dashboard. @@ -54,7 +51,7 @@ Like the `VizroAI.plot` method, in order to produce more comprehensive output we - If set to `True`, it returns a class (a Pydantic model) containing both the dashboard object and the code string used to generate it. !!! example "View dashboard code" - === "Code" + === "Prompt" ```py import vizro.plotly.express as px from vizro_ai import VizroAI @@ -80,7 +77,7 @@ Like the `VizroAI.plot` method, in order to produce more comprehensive output we print(result.code) ``` - === "Result" + === "Resulting code" ```py ######## Module Imports ########## from vizro import Vizro From 173b5e55e9d154c891c5b72b09d2a2e3714e59b7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:53:28 +0000 Subject: [PATCH 15/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md index 05111f5f9..c47ee303d 100644 --- a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md +++ b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md @@ -34,8 +34,8 @@ This guide offers insights into different ways of running `VizroAI.dashboard` to ``` === "Result" - ![VizroAIDashboardPage1](../../assets/user_guides/dashboard/dashboard2_page1.png) + ![VizroAIDashboardPage1](../../assets/user_guides/dashboard/dashboard2_page1.png) This triggers the dashboard building process. Once Vizro-AI finishes the dashboard generation process, you can now launch the dashboard. From c241d08640f35cc72f0dd7b216a6a82c063bd1d3 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 10:57:58 +0000 Subject: [PATCH 16/54] Update safeguard.md --- vizro-ai/docs/pages/explanation/safeguard.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vizro-ai/docs/pages/explanation/safeguard.md b/vizro-ai/docs/pages/explanation/safeguard.md index 7b2857fb9..6375451a9 100644 --- a/vizro-ai/docs/pages/explanation/safeguard.md +++ b/vizro-ai/docs/pages/explanation/safeguard.md @@ -24,6 +24,7 @@ To help to mitigate these risks, we limit the execution of certain modules and f The lists below are a reflection of the security and functionality we have implemented with Vizro-AI: ??? success "Whitelisted Packages" + - `pandas` - `numpy` - `vizro` @@ -35,6 +36,7 @@ The lists below are a reflection of the security and functionality we have imple - `sklearn` ??? success "Whitelisted Builtins" + - abs - len - max @@ -54,10 +56,12 @@ The lists below are a reflection of the security and functionality we have imple - tuple ??? failure "Redlisted Class Methods" + - subclasses - builtins ??? failure "Redlisted Data Handling Methods and Formats" + - Various data file formats (such as .csv, .tsv, .xlsx, .json, and so on) - Specific methods related to data input/output operations (such as .to_csv, .read_excel, .loadtxt) From b95bed2bf3186554692302dd170b0f5252255c6d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:58:23 +0000 Subject: [PATCH 17/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- vizro-ai/docs/pages/explanation/safeguard.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vizro-ai/docs/pages/explanation/safeguard.md b/vizro-ai/docs/pages/explanation/safeguard.md index 6375451a9..7b2857fb9 100644 --- a/vizro-ai/docs/pages/explanation/safeguard.md +++ b/vizro-ai/docs/pages/explanation/safeguard.md @@ -24,7 +24,6 @@ To help to mitigate these risks, we limit the execution of certain modules and f The lists below are a reflection of the security and functionality we have implemented with Vizro-AI: ??? success "Whitelisted Packages" - - `pandas` - `numpy` - `vizro` @@ -36,7 +35,6 @@ The lists below are a reflection of the security and functionality we have imple - `sklearn` ??? success "Whitelisted Builtins" - - abs - len - max @@ -56,12 +54,10 @@ The lists below are a reflection of the security and functionality we have imple - tuple ??? failure "Redlisted Class Methods" - - subclasses - builtins ??? failure "Redlisted Data Handling Methods and Formats" - - Various data file formats (such as .csv, .tsv, .xlsx, .json, and so on) - Specific methods related to data input/output operations (such as .to_csv, .read_excel, .loadtxt) From 51fb9b5feb6c96b23aafdc0a8ed5f0e6d9ede976 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 11:35:30 +0000 Subject: [PATCH 18/54] Update safeguard.md --- vizro-ai/docs/pages/explanation/safeguard.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vizro-ai/docs/pages/explanation/safeguard.md b/vizro-ai/docs/pages/explanation/safeguard.md index 6375451a9..6f4b213d4 100644 --- a/vizro-ai/docs/pages/explanation/safeguard.md +++ b/vizro-ai/docs/pages/explanation/safeguard.md @@ -23,6 +23,7 @@ To help to mitigate these risks, we limit the execution of certain modules and f The lists below are a reflection of the security and functionality we have implemented with Vizro-AI: + ??? success "Whitelisted Packages" - `pandas` @@ -65,6 +66,8 @@ The lists below are a reflection of the security and functionality we have imple - Various data file formats (such as .csv, .tsv, .xlsx, .json, and so on) - Specific methods related to data input/output operations (such as .to_csv, .read_excel, .loadtxt) + + ### Safeguard for user environment and input - **Isolated environment**: Always run code in an isolated or contained environment, such as a virtual environment, virtual machine or container, to minimize potential harm to the primary system. From a89c3971d2c43b3a96be7893b580c2570faa0385 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 11:36:32 +0000 Subject: [PATCH 19/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- vizro-ai/docs/pages/explanation/safeguard.md | 1 + 1 file changed, 1 insertion(+) diff --git a/vizro-ai/docs/pages/explanation/safeguard.md b/vizro-ai/docs/pages/explanation/safeguard.md index f28ce0a47..aacd2c503 100644 --- a/vizro-ai/docs/pages/explanation/safeguard.md +++ b/vizro-ai/docs/pages/explanation/safeguard.md @@ -24,6 +24,7 @@ To help to mitigate these risks, we limit the execution of certain modules and f The lists below are a reflection of the security and functionality we have implemented with Vizro-AI: + ??? success "Whitelisted Packages" - `pandas` - `numpy` From 0b0e3b20f54c5245793576a880febc76a2758568 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 11:46:34 +0000 Subject: [PATCH 20/54] Remove FIXME in readmes and index --- README.md | 11 ++++++++++- vizro-ai/README.md | 10 +++++++++- vizro-ai/docs/index.md | 32 ++++++++++++++++++++++++++++---- vizro-core/README.md | 11 ++++++++++- vizro-core/docs/index.md | 34 +++++++++++++++++++++++++++++----- 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6c77b4ae8..a7775965a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,16 @@
-FIXME: maybe use two new lines between each [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) + + +[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) + + +[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) + + +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
diff --git a/vizro-ai/README.md b/vizro-ai/README.md index fdca6d99d..f7106bf47 100644 --- a/vizro-ai/README.md +++ b/vizro-ai/README.md @@ -2,7 +2,15 @@
-FIXME: maybe use two new lines between each [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) + +[![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) + +[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) + +[![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) + +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) Gif to demonstrate vizro-ai diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index 0d1f18f5a..4fe549868 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -14,25 +14,49 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- -FIXME: maybe use two new lines between each [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
+[:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
+ + +[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
+ + +[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
- :fontawesome-solid-keyboard:{ .lg .middle } __Get hands-on__ --- - [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
[:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
[:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
[:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
[:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) +[:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
+ + +[:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
+ + +[:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
+ + +[:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
+ + +[:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) - :material-format-font:{ .lg .middle } __Find out more__ --- - [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
[:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
[:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) +[:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
+ + +[:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
+ + +[:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro__ --- - [:octicons-arrow-right-24: Vizro documentation](https://vizro.readthedocs.io/) +[:octicons-arrow-right-24: Vizro documentation](https://vizro.readthedocs.io/)
diff --git a/vizro-core/README.md b/vizro-core/README.md index a8bb03617..c0f87bafa 100644 --- a/vizro-core/README.md +++ b/vizro-core/README.md @@ -11,7 +11,16 @@
-FIXME: maybe use two new lines between each [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) + + +[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) + + +[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) + + +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index 9ebfd181a..98ef5c082 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -8,31 +8,55 @@ Vizro is a toolkit for creating modular data visualization applications. --- -FIXME: maybe use two new lines between each [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) +[:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
+ + +[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) - :fontawesome-solid-keyboard:{ .lg .middle } __Vizro features__ --- - [:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
[:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
[:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
[:octicons-arrow-right-24: Visual formatting](pages/user-guides/visual-formatting.md) +[:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
+ + +[:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
+ + +[:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
+ + +[:octicons-arrow-right-24: Visual formatting](pages/user-guides/visual-formatting.md) - :fontawesome-solid-microscope:{ .lg .middle } __Hands-on code__ --- - [:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
[:octicons-arrow-right-24: Examples](https://vizro.mckinsey.com) +[:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
+ + +[:octicons-arrow-right-24: Examples](https://vizro.mckinsey.com) - :material-scale-balance:{ .lg .middle } __FAQs__ --- - [:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
[:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
[:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
+[:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
+ + +[:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
+ + +[:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
- :fontawesome-solid-hands-holding-circle:{ .lg .middle } __Get involved__ --- - [:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md)
[:octicons-arrow-right-24: Contribute to our docs](pages/explanation/documentation-style-guide.md) +[:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md)
+ + +[:octicons-arrow-right-24: Contribute to our docs](pages/explanation/documentation-style-guide.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro-AI__ From 59fc9dc6f3b6d6311d4036d66faf4b2e08d257e6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 11:49:29 +0000 Subject: [PATCH 21/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- README.md | 3 --- vizro-ai/README.md | 8 ++++---- vizro-ai/docs/index.md | 14 +++----------- vizro-core/README.md | 9 +++------ vizro-core/docs/index.md | 26 +++++++++----------------- 5 files changed, 19 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index a7775965a..b32875b81 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,10 @@ [![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) - [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) - [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) - [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
diff --git a/vizro-ai/README.md b/vizro-ai/README.md index f7106bf47..8734c3ad8 100644 --- a/vizro-ai/README.md +++ b/vizro-ai/README.md @@ -2,13 +2,13 @@
-[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/vizro/) -[![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) +[![PyPI version](https://badge.fury.io/py/vizro_ai.svg)](https://badge.fury.io/py/vizro_ai) -[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) +[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) -[![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) +[![Documentation](https://readthedocs.org/projects/vizro-ai/badge/?version=latest)](https://vizro-ai.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index 4fe549868..335bbca37 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -14,11 +14,9 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- -[:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
- - -[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
+[:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
+[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
@@ -27,17 +25,13 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
- - -[:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
+[:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
[:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
- [:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
- [:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) - :material-format-font:{ .lg .middle } __Find out more__ @@ -46,10 +40,8 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
- [:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
- [:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro__ diff --git a/vizro-core/README.md b/vizro-core/README.md index c0f87bafa..826f708ee 100644 --- a/vizro-core/README.md +++ b/vizro-core/README.md @@ -11,14 +11,11 @@
-[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) +[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) -[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) - - -[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) - +[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index 98ef5c082..1f456f0da 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -8,8 +8,7 @@ Vizro is a toolkit for creating modular data visualization applications. --- -[:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
- +[:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) @@ -17,14 +16,11 @@ Vizro is a toolkit for creating modular data visualization applications. --- -[:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
- - -[:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
- +[:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
-[:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
+[:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
+[:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
[:octicons-arrow-right-24: Visual formatting](pages/user-guides/visual-formatting.md) @@ -32,20 +28,17 @@ Vizro is a toolkit for creating modular data visualization applications. --- -[:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
- - +[:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
+ [:octicons-arrow-right-24: Examples](https://vizro.mckinsey.com) - :material-scale-balance:{ .lg .middle } __FAQs__ --- -[:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
- - -[:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
+[:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
+[:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
[:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
@@ -54,8 +47,7 @@ Vizro is a toolkit for creating modular data visualization applications. --- [:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md)
- - + [:octicons-arrow-right-24: Contribute to our docs](pages/explanation/documentation-style-guide.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro-AI__ From 767f70d247139c62bec6ce94a103c9defab15da4 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 11:53:43 +0000 Subject: [PATCH 22/54] Update index pages --- vizro-ai/docs/index.md | 24 ++++++++++++------------ vizro-core/docs/index.md | 26 +++++++++++++------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index 335bbca37..4c9f4a2f3 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -14,41 +14,41 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- -[:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
+ [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
-[:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
+ [:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
-[:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
+ [:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
- :fontawesome-solid-keyboard:{ .lg .middle } __Get hands-on__ --- -[:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
+ [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
-[:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
+ [:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
-[:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
+ [:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
-[:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
+ [:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
-[:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) + [:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) - :material-format-font:{ .lg .middle } __Find out more__ --- -[:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
+ [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
-[:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
+ [:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
-[:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) + [:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro__ --- -[:octicons-arrow-right-24: Vizro documentation](https://vizro.readthedocs.io/) + [:octicons-arrow-right-24: Vizro documentation](https://vizro.readthedocs.io/)
diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index 1f456f0da..9a07e2d03 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -8,47 +8,47 @@ Vizro is a toolkit for creating modular data visualization applications. --- -[:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
+ [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
-[:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) + [:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) - :fontawesome-solid-keyboard:{ .lg .middle } __Vizro features__ --- -[:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
+ [:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
-[:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
+ [:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
-[:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
+ [:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
-[:octicons-arrow-right-24: Visual formatting](pages/user-guides/visual-formatting.md) + [:octicons-arrow-right-24: Visual formatting](pages/user-guides/visual-formatting.md) - :fontawesome-solid-microscope:{ .lg .middle } __Hands-on code__ --- -[:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
+ [:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
-[:octicons-arrow-right-24: Examples](https://vizro.mckinsey.com) + [:octicons-arrow-right-24: Examples](https://vizro.mckinsey.com) - :material-scale-balance:{ .lg .middle } __FAQs__ --- -[:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
+ [:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
-[:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
+ [:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
-[:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
+ [:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
- :fontawesome-solid-hands-holding-circle:{ .lg .middle } __Get involved__ --- -[:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md)
+ [:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md)
-[:octicons-arrow-right-24: Contribute to our docs](pages/explanation/documentation-style-guide.md) + [:octicons-arrow-right-24: Contribute to our docs](pages/explanation/documentation-style-guide.md) - :fontawesome-solid-chart-column:{ .lg .middle } __Vizro-AI__ From a7940d02953a0f9d0a87afc2b763edc449cd51ed Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 12:00:17 +0000 Subject: [PATCH 23/54] Update index.md --- vizro-core/docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index 9a07e2d03..11346d4f8 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -38,7 +38,7 @@ Vizro is a toolkit for creating modular data visualization applications. [:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
- [:octicons-arrow-right-24: Where can I ask a question about Vizo?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
+ [:octicons-arrow-right-24: Where can I ask a question?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
[:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
From 231bb573d9e7925ac5d26de474f3feed0e44f869 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 14:09:26 +0000 Subject: [PATCH 24/54] Fix a bunch of Vale issues in admonitions --- .../pages/user-guides/customize-vizro-ai.md | 16 +- vizro-ai/docs/pages/user-guides/install.md | 2 +- .../docs/pages/user-guides/run-vizro-ai.md | 2 +- .../user-guides/vizro-ai-langchain-guide.md | 144 +++++------ .../docs/pages/explanation/contributing.md | 4 +- .../pages/tutorials/explore-components.md | 6 +- vizro-core/docs/pages/user-guides/actions.md | 117 ++++----- .../docs/pages/user-guides/card-button.md | 142 +++++------ .../docs/pages/user-guides/custom-actions.md | 2 +- vizro-core/docs/pages/user-guides/data.md | 2 +- vizro-core/docs/pages/user-guides/figure.md | 240 +++++++++--------- vizro-core/docs/pages/user-guides/graph.md | 6 +- .../pages/user-guides/kedro-data-catalog.md | 7 +- vizro-core/docs/pages/user-guides/layouts.md | 2 +- vizro-core/docs/pages/user-guides/run.md | 4 +- .../docs/pages/user-guides/selectors.md | 4 +- vizro-core/docs/pages/user-guides/themes.md | 2 +- 17 files changed, 352 insertions(+), 350 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index e20a3e56f..e1ee74a98 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -18,16 +18,16 @@ vizro_ai = VizroAI(model="") For the string settings to work, you must supply your API key via environment variables. The relevant variable names to be set are noted in each vendor tab. === "OpenAI" - | Env variable | Name(s) | - | ------------ | ----------------- | - | API key | `OPENAI_API_KEY` | - | Base API URL | `OPENAI_API_BASE` | +| Environment variable | Name(s) | +| -------------------- | ----------------- | +| API key | `OPENAI_API_KEY` | +| Base API URL | `OPENAI_API_BASE` | - To use OpenAI with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the OpenAI models and pricing on their website](https://platform.openai.com/docs/models). Before using a model, please review OpenAI's guidelines on risk mitigation to understand potential model limitations and best practices. [See the OpenAI site for more details on responsible usage](https://platform.openai.com/docs/guides/safety-best-practices). +To use OpenAI with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the OpenAI models and pricing on their website](https://platform.openai.com/docs/models). Before using a model, please review OpenAI's guidelines on risk mitigation to understand potential model limitations and best practices. [See the OpenAI site for more details on responsible usage](https://platform.openai.com/docs/guides/safety-best-practices). - - `gpt-4o-mini` **default** - - `gpt-4-turbo` - - `gpt-4o` +- `gpt-4o-mini` **default** +- `gpt-4-turbo` +- `gpt-4o` === "Anthropic" _Currently works only for `VizroAI.plot` - we are working on making it available for `VizroAI.dashboard`_ diff --git a/vizro-ai/docs/pages/user-guides/install.md b/vizro-ai/docs/pages/user-guides/install.md index 7db393e51..76ed1108c 100644 --- a/vizro-ai/docs/pages/user-guides/install.md +++ b/vizro-ai/docs/pages/user-guides/install.md @@ -85,7 +85,7 @@ By default, `vizro-ai` automatically loads the `.env` file, by searching the cur If you would like to customize the `.env` file location and name, you can manually customize the search to override the default and specify the path and name of a custom `.env` file. ??? example "How to override the default location of the .`env` file:" - ```py + ```python from dotenv import load_dotenv, find_dotenv from pathlib import Path diff --git a/vizro-ai/docs/pages/user-guides/run-vizro-ai.md b/vizro-ai/docs/pages/user-guides/run-vizro-ai.md index 9d375a504..0c392dbed 100644 --- a/vizro-ai/docs/pages/user-guides/run-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/run-vizro-ai.md @@ -11,7 +11,7 @@ This guide offers insights into different ways of running `VizroAI.plot` to gene To run Vizro-AI code in a Jupyter Notebook, create a new cell and execute the code below to render the described visualization as output. ??? note "Note: API key" - Make sure you have followed the [LLM setup guide](../user-guides/install.md#set-up-access-to-a-large-language-model) and thatyour api key is set up in a `.env` file in the same folder as your Notebook file (`.ipynb`). + Make sure you have followed the [LLM setup guide](../user-guides/install.md#set-up-access-to-a-large-language-model) and that your api key is set up in a `.env` file in the same folder as your Notebook file (`.ipynb`). !!! example "Ask Vizro-AI to generate a bar chart" === "Code for the cell" diff --git a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md index 97aecc97a..ca24371a6 100644 --- a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md +++ b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md @@ -117,86 +117,86 @@ Now you can use the chain to generate charts or dashboards based on natural lang !!! example "Generate chart code" === "Code" - ```py - # Load sample data - df = px.data.gapminder() + ```python + # Load sample data + df = px.data.gapminder() - plot_response = chain.invoke("Plot GDP per capita for each continent") - print(plot_response[0].content) - ``` + plot_response = chain.invoke("Plot GDP per capita for each continent") + print(plot_response[0].content) + ``` === "Vizro-AI Generated Code" - ```py - import plotly.graph_objects as go - from vizro.models.types import capture - - @capture("graph") - def custom_chart(data_frame): - continent_gdp = data_frame.groupby("continent")["gdpPercap"].mean().reset_index() - fig = go.Figure( - data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])] - ) - fig.update_layout( - title="GDP per Capita by Continent", - xaxis_title="Continent", - yaxis_title="GDP per Capita", - ) - return fig - ``` + ```python + import plotly.graph_objects as go + from vizro.models.types import capture + + @capture("graph") + def custom_chart(data_frame): + continent_gdp = data_frame.groupby("continent")["gdpPercap"].mean().reset_index() + fig = go.Figure( + data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])] + ) + fig.update_layout( + title="GDP per Capita by Continent", + xaxis_title="Continent", + yaxis_title="GDP per Capita", + ) + return fig + ``` !!! example "Generate dashboard code" === "Code" - ```py - dfs = [px.data.gapminder()] + ```python + dfs = [px.data.gapminder()] - dashboard_response = chain.invoke("Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp.") - print(dashboard_response[0].content) - ``` + dashboard_response = chain.invoke("Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp.") + print(dashboard_response[0].content) + ``` === "Vizro-AI Generated Code" - ```py - ############ Imports ############## - import vizro.models as vm - from vizro.models.types import capture - import plotly.graph_objects as go - - - ####### Function definitions ###### - @capture("graph") - def gdp_life_exp_graph(data_frame): - fig = go.Figure() - fig.add_trace( - go.Scatter(x=data_frame["gdpPercap"], y=data_frame["lifeExp"], mode="markers") - ) - fig.update_layout( - title="GDP per Capita vs Life Expectancy", - xaxis_title="GDP per Capita", - yaxis_title="Life Expectancy", - ) - return fig - - - ####### Data Manager Settings ##### - #######!!! UNCOMMENT BELOW !!!##### - # from vizro.managers import data_manager - # data_manager["gdp_life_exp"] = ===> Fill in here <=== - - - ########### Model code ############ - model = vm.Dashboard( - pages=[ - vm.Page( - components=[ - vm.Graph( - id="gdp_life_exp_graph", - figure=gdp_life_exp_graph(data_frame="gdp_life_exp"), - ) - ], - title="GDP vs Life Expectancy Correlation", - layout=vm.Layout(grid=[[0]]), - controls=[], - ) - ], + ```py + ############ Imports ############## + import vizro.models as vm + from vizro.models.types import capture + import plotly.graph_objects as go + + + ####### Function definitions ###### + @capture("graph") + def gdp_life_exp_graph(data_frame): + fig = go.Figure() + fig.add_trace( + go.Scatter(x=data_frame["gdpPercap"], y=data_frame["lifeExp"], mode="markers") + ) + fig.update_layout( title="GDP per Capita vs Life Expectancy", + xaxis_title="GDP per Capita", + yaxis_title="Life Expectancy", ) - ``` + return fig + + + ####### Data Manager Settings ##### + #######!!! UNCOMMENT BELOW !!!##### + # from vizro.managers import data_manager + # data_manager["gdp_life_exp"] = ===> Fill in here <=== + + + ########### Model code ############ + model = vm.Dashboard( + pages=[ + vm.Page( + components=[ + vm.Graph( + id="gdp_life_exp_graph", + figure=gdp_life_exp_graph(data_frame="gdp_life_exp"), + ) + ], + title="GDP vs Life Expectancy Correlation", + layout=vm.Layout(grid=[[0]]), + controls=[], + ) + ], + title="GDP per Capita vs Life Expectancy", + ) + ``` diff --git a/vizro-core/docs/pages/explanation/contributing.md b/vizro-core/docs/pages/explanation/contributing.md index 44e39ecf0..bf71bfb39 100644 --- a/vizro-core/docs/pages/explanation/contributing.md +++ b/vizro-core/docs/pages/explanation/contributing.md @@ -90,7 +90,7 @@ Examples are run with the following settings: `hatch run lint` checks and fixes code quality and formatting. This is included in CI checks. All linting and associated dependencies are controlled by [pre-commit](https://pre-commit.com/) hooks. We use the [pre-commit.ci](https://pre-commit.ci/) to automatically fix all the linting checks that we can when a PR is pushed. Other linting failures (such as `mypy`) need manual intervention from the developer. !!! note - The first time you run `hatch run lint` it may take a couple of minutes, since pre-commit needs to setup linting environments. Subsequent runs reuse these environments and are much faster. + The first time you run `hatch run lint` it may take a couple of minutes, since pre-commit needs to setup linting environments. Further runs reuse these environments and are much faster. `hatch run lint` runs the pre-commit hooks on all (not only staged) files. You can run an individual hook, for example `mypy`, on all files by running `hatch run lint mypy`. @@ -105,7 +105,7 @@ The format of our changelog is based on [Keep a Changelog](https://keepachangelo Run `hatch run changelog:add` to create a changelog fragment and then uncomment the relevant section(s). If you are uncertain about what to add or whether to add anything at all, refer to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The rule of thumb is that if Vizro users would be affected in any way then the changes should be described in the changelog. !!! note - Changes that do not affect source code do not need a changelog fragment. This facilitates simple modifications to documentation [made directly on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files) or with the [github.dev](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor), where no terminal is available to run `hatch changelog:add`. Any changes to source code require a changelog fragment to be generated. If your changes do not require a changelog entry then you still need to generate the fragment but can leave it all commented out. + Changes that do not affect source code do not need a changelog fragment. This simplifies modifications to documentation [made directly on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files) or within the [github.dev](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor), where no terminal is available to run `hatch changelog:add`. Any changes to source code require a changelog fragment to be generated. If your changes do not require a changelog entry then you still need to generate the fragment but can leave it all commented out. ### `hatch run test-unit` diff --git a/vizro-core/docs/pages/tutorials/explore-components.md b/vizro-core/docs/pages/tutorials/explore-components.md index 1ed53d464..12899b3f9 100644 --- a/vizro-core/docs/pages/tutorials/explore-components.md +++ b/vizro-core/docs/pages/tutorials/explore-components.md @@ -470,7 +470,7 @@ The code below illustrates a functional dashboard where you can navigate from th !!! example "Final dashboard" === "Code" - ```py + ```python home_page = vm.Page( title="Homepage", components=[ @@ -498,7 +498,7 @@ The code below illustrates a functional dashboard where you can navigate from th ) ``` - ```py + ```python dashboard = vm.Dashboard(pages=[home_page, first_page, second_page]) ``` @@ -622,7 +622,7 @@ Congratulations on completing this tutorial! You have acquired the knowledge to After completing the tutorial you now have a solid understanding of the main elements of Vizro and how to bring them together to create dynamic and interactive data visualizations. -You can find out more about the Vizro by reading the [components overview page](../user-guides/components.md). To gain more in-depth knowledge about the usage and configuration details of individual controls, check out the guides dedicated to [Filters](../user-guides/filters.md), [Parameters](../user-guides/parameters.md) and [Selectors](../user-guides/selectors.md). If you'd like to understand more about different ways to configure the navigation of your dashboard, head to [Navigation](../user-guides/navigation.md). +You can find out more about the Vizro by reading the [components overview page](../user-guides/components.md). To gain more in-depth knowledge about the usage and configuration details of individual controls, check out the guides dedicated to [Filters](../user-guides/filters.md), [Parameters](../user-guides/parameters.md), and [Selectors](../user-guides/selectors.md). If you'd like to understand more about different ways to configure the navigation of your dashboard, head to [Navigation](../user-guides/navigation.md). Vizro doesn't end here, and we only covered the key features, but there is still much more to explore! You can learn: diff --git a/vizro-core/docs/pages/user-guides/actions.md b/vizro-core/docs/pages/user-guides/actions.md index 6a41ee25d..f2dae6448 100644 --- a/vizro-core/docs/pages/user-guides/actions.md +++ b/vizro-core/docs/pages/user-guides/actions.md @@ -22,68 +22,69 @@ The below sections are guides on how to use pre-defined action functions. To enable downloading data, you can add the [`export_data`][vizro.actions.export_data] action function to the [`Button`][vizro.models.Button] component. Hence, as a result, when a dashboard user now clicks the button, all data on the page will be downloaded. + !!! example "`export_data`" === "app.py" - ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.actions import export_data - - iris = px.data.iris() - - page = vm.Page( - title="Using actions", - components=[ - vm.Graph( - figure=px.scatter(iris, x="petal_length", y="sepal_length", color="sepal_width"), - ), - vm.Graph( - figure=px.histogram(iris, x="petal_length", color="species"), - ), - vm.Button( - text="Export data", - actions=[ - vm.Action( - function=export_data() - ), - ], - ), - ], - ) - - dashboard = vm.Dashboard(pages=[page]) - - Vizro().build(dashboard).run() - ``` + ```{.python pycafe-link} + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.actions import export_data + + iris = px.data.iris() + + page = vm.Page( + title="Using actions", + components=[ + vm.Graph( + figure=px.scatter(iris, x="petal_length", y="sepal_length", color="sepal_width"), + ), + vm.Graph( + figure=px.histogram(iris, x="petal_length", color="species"), + ), + vm.Button( + text="Export data", + actions=[ + vm.Action( + function=export_data() + ), + ], + ), + ], + ) + + dashboard = vm.Dashboard(pages=[page]) + + Vizro().build(dashboard).run() + ``` === "app.yaml" - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See yaml_version example - pages: - - components: - - type: graph - figure: - _target_: scatter - data_frame: iris - color: sepal_width - x: petal_length - y: sepal_length - - type: graph - figure: - _target_: histogram - data_frame: iris - color: species - x: petal_length - - type: button - text: Export data - id: export_data_button - actions: - - function: - _target_: export_data - title: Exporting - ``` + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See yaml_version example + pages: + - components: + - type: graph + figure: + _target_: scatter + data_frame: iris + color: sepal_width + x: petal_length + y: sepal_length + - type: graph + figure: + _target_: histogram + data_frame: iris + color: species + x: petal_length + - type: button + text: Export data + id: export_data_button + actions: + - function: + _target_: export_data + title: Exporting + ``` === "Result" [![Graph]][graph] diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index 0cc51009b..947702254 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -246,7 +246,7 @@ An image ALT text offers a description to your image and serves as a text placeh [![CardImageDefault]][cardimagedefault] !!! note - Note that inserting images using html is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. + Note that inserting images using HTML is by default turned off by the `dcc.Markdown` to prevent users being exposed to cross-site scripting attacks. If you need to turn it on, a custom component would have to be created. You might notice that the image is quite large. You'll find out how to style images in terms of their position and size in the next section. @@ -626,79 +626,79 @@ The example below demonstrates how to configure a button to export the filtered !!! example "Button with action" === "app.py" - ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.actions import export_data - - df = px.data.iris() - - page = vm.Page( - title="My first page", - layout=vm.Layout(grid=[[0], [0], [0], [0], [1]]), - components=[ - vm.Graph( - id="scatter_chart", - figure=px.scatter( - df, - x="sepal_width", - y="sepal_length", - color="species", - size="petal_length", - ), - ), - vm.Button( - text="Export data", - actions=[vm.Action(function=export_data(targets=["scatter_chart"]))], + ```{.python pycafe-link} + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.actions import export_data + + df = px.data.iris() + + page = vm.Page( + title="My first page", + layout=vm.Layout(grid=[[0], [0], [0], [0], [1]]), + components=[ + vm.Graph( + id="scatter_chart", + figure=px.scatter( + df, + x="sepal_width", + y="sepal_length", + color="species", + size="petal_length", ), - ], - controls=[vm.Filter(column="species")], - ) - - dashboard = vm.Dashboard(pages=[page]) - - Vizro().build(dashboard).run() - ``` + ), + vm.Button( + text="Export data", + actions=[vm.Action(function=export_data(targets=["scatter_chart"]))], + ), + ], + controls=[vm.Filter(column="species")], + ) + + dashboard = vm.Dashboard(pages=[page]) + + Vizro().build(dashboard).run() + ``` === "app.yaml" - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See from_yaml example - pages: - - components: - - figure: - _target_: scatter - x: sepal_width - y: sepal_length - color: species - size: petal_length - data_frame: iris - id: scatter_chart - type: graph - - type: button - text: Export data - id: export_data - actions: - - function: - _target_: export_data - targets: - - scatter_chart - controls: - - column: species - selector: - title: Species - type: dropdown - type: filter - layout: - grid: - - [0] - - [0] - - [0] - - [0] - - [1] - title: My first page - ``` + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See from_yaml example + pages: + - components: + - figure: + _target_: scatter + x: sepal_width + y: sepal_length + color: species + size: petal_length + data_frame: iris + id: scatter_chart + type: graph + - type: button + text: Export data + id: export_data + actions: + - function: + _target_: export_data + targets: + - scatter_chart + controls: + - column: species + selector: + title: Species + type: dropdown + type: filter + layout: + grid: + - [0] + - [0] + - [0] + - [0] + - [1] + title: My first page + ``` === "Result" [![Button]][button] diff --git a/vizro-core/docs/pages/user-guides/custom-actions.md b/vizro-core/docs/pages/user-guides/custom-actions.md index 379a85b23..2fb66cd2c 100644 --- a/vizro-core/docs/pages/user-guides/custom-actions.md +++ b/vizro-core/docs/pages/user-guides/custom-actions.md @@ -243,7 +243,7 @@ The return value of the custom action function is propagated to the dashboard co [![CustomAction2]][customaction2] !!! warning - Note that users of this package are responsible for the content of any custom action function that they write - especially with regard to leaking any sensitive information or exposing to any security threat during implementation. You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). + Note that users of this package are responsible for the content of any custom action function that they write. Take care to avoid leaking any sensitive information or exposing to any security threat during implementation. You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). [customaction]: ../../assets/user_guides/custom_actions/clickdata_as_input.png [customaction2]: ../../assets/user_guides/custom_actions/custom_action_multiple_return_values.png diff --git a/vizro-core/docs/pages/user-guides/data.md b/vizro-core/docs/pages/user-guides/data.md index 2161486c6..bd59096c9 100644 --- a/vizro-core/docs/pages/user-guides/data.md +++ b/vizro-core/docs/pages/user-guides/data.md @@ -323,7 +323,7 @@ For example, let us extend the [dynamic data example](#dynamic-data) above to sh Parametrized data loading is compatible with [caching](#configure-cache). The cache uses [memoization](https://flask-caching.readthedocs.io/en/latest/#memoization), so that the dynamic data function's arguments are included in the cache key. This means that `load_iris_data(number_of_points=10)` is cached independently of `load_iris_data(number_of_points=20)`. !!! warning - You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). For example, you should not expose a filepath to load without passing it through a function like [`werkzeug.utils.secure_filename`](https://werkzeug.palletsprojects.com/en/3.0.x/utils/#werkzeug.utils.secure_filename), or you might enable arbitrary access to files on your server. + You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). For example, you should not expose a file path to load without passing it through a function like [`werkzeug.utils.secure_filename`](https://werkzeug.palletsprojects.com/en/3.0.x/utils/#werkzeug.utils.secure_filename), or you might enable arbitrary access to files on your server. You cannot pass [nested parameters](parameters.md#nested-parameters) to dynamic data. You can only target the top-level arguments of the data loading function, not the nested keys in a dictionary. diff --git a/vizro-core/docs/pages/user-guides/figure.md b/vizro-core/docs/pages/user-guides/figure.md index 32a93d8d3..89761b3ab 100644 --- a/vizro-core/docs/pages/user-guides/figure.md +++ b/vizro-core/docs/pages/user-guides/figure.md @@ -40,60 +40,60 @@ To add a `Figure` to your page: !!! example "Use existing figure functions" === "app.py" - ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.figures import kpi_card - - tips = px.data.tips - - # Create a layout with five rows and four columns. The KPI card is positioned in the first cell, while the remaining cells are empty. - page = vm.Page( - title="KPI card", - layout=vm.Layout(grid=[[0, -1, -1, -1]] + [[-1, -1, -1, -1]] * 4), - components=[ - vm.Figure( - figure=kpi_card( # For more information, refer to the API reference for kpi_card - data_frame=tips, - value_column="tip", - value_format="${value:.2f}", - icon="shopping_cart", - title="KPI card I", - ) + ```{.python pycafe-link} + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.figures import kpi_card + + tips = px.data.tips + + # Create a layout with five rows and four columns. The KPI card is positioned in the first cell, while the remaining cells are empty. + page = vm.Page( + title="KPI card", + layout=vm.Layout(grid=[[0, -1, -1, -1]] + [[-1, -1, -1, -1]] * 4), + components=[ + vm.Figure( + figure=kpi_card( # For more information, refer to the API reference for kpi_card + data_frame=tips, + value_column="tip", + value_format="${value:.2f}", + icon="shopping_cart", + title="KPI card I", ) - ], - controls=[vm.Filter(column="day", selector=vm.RadioItems())], - ) + ) + ], + controls=[vm.Filter(column="day", selector=vm.RadioItems())], + ) - dashboard = vm.Dashboard(pages=[page]) - Vizro().build(dashboard).run() - ``` + dashboard = vm.Dashboard(pages=[page]) + Vizro().build(dashboard).run() + ``` === "app.yaml" - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See from_yaml example - pages: - - components: - - figure: - _target_: kpi_card - data_frame: tips - value_column: tip - value_format: ${value:.2f} - icon: shopping_cart - title: KPI card I - type: figure - controls: - - column: day - type: filter - selector: - type: radio_items - layout: - grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], - [-1, -1, -1, -1]] - title: KPI card - ``` + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See from_yaml example + pages: + - components: + - figure: + _target_: kpi_card + data_frame: tips + value_column: tip + value_format: ${value:.2f} + icon: shopping_cart + title: KPI card I + type: figure + controls: + - column: day + type: filter + selector: + type: radio_items + layout: + grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], + [-1, -1, -1, -1]] + title: KPI card + ``` === "Result" [![Figure]][figure] @@ -106,79 +106,79 @@ A KPI card is a dynamic card that can display a single value, but optionally, ca - [`kpi_card_with_reference`](../API-reference/figure-callables.md#vizro.figures.kpi_card_reference): A KPI card that shows a single value and a delta comparison to a reference value found by performing an aggregation function (by default, `sum`) over the specified columns. Required arguments are `data_frame`, `value_column` and `reference_column`. -As described in the [API reference](../API-reference/figure-callables.md) and illustrated in the below example, these functions have several arguments to customize your KPI cards. If you require a level of customization that is not possible with the built-in functions then you can create a [custom figure](custom-figures.md). +As described in the [API reference](../API-reference/figure-callables.md) and illustrated in the below example, these functions have several arguments to customize your KPI cards. If you require a level of customization that cannot be done with the built-in functions then you can create a [custom figure](custom-figures.md). !!! example "KPI card variations" === "app.py" - ```{.python pycafe-link} - import pandas as pd - import vizro.models as vm - from vizro import Vizro - # For more information, refer to the API reference for kpi_card and kpi_card_reference - from vizro.figures import kpi_card, kpi_card_reference - - df_kpi = pd.DataFrame({"Actual": [100, 200, 700], "Reference": [100, 300, 500], "Category": ["A", "B", "C"]}) - - example_cards = [ - kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with value"), - kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with aggregation", agg_func="median"), - kpi_card( - data_frame=df_kpi, - value_column="Actual", - title="KPI with formatting", - value_format="${value:.2f}", - ), - kpi_card( - data_frame=df_kpi, - value_column="Actual", - title="KPI with icon", - icon="shopping_cart", - ), - ] - - example_reference_cards = [ - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - title="KPI reference (pos)", - ), - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - agg_func="median", - title="KPI reference (neg)", - ), - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - title="KPI reference with formatting", - value_format="{value:.2f}€", - reference_format="{delta:+.2f}€ vs. last year ({reference:.2f}€)", - ), - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - title="KPI reference with icon", - icon="shopping_cart", - ), - ] - - # Create a layout with four rows and columns. The KPI cards are positioned in the first eight cells, while the remaining cells are empty. - page = vm.Page( - title="KPI cards", - layout=vm.Layout(grid=[[0, 1, 2, 3], [4, 5, 6, 7], [-1, -1, -1, -1], [-1, -1, -1, -1]]), - - components=[vm.Figure(figure=figure) for figure in example_cards + example_reference_cards], - controls=[vm.Filter(column="Category")], - ) - - dashboard = vm.Dashboard(pages=[page]) - Vizro().build(dashboard).run() - ``` + ```{.python pycafe-link} + import pandas as pd + import vizro.models as vm + from vizro import Vizro + # For more information, refer to the API reference for kpi_card and kpi_card_reference + from vizro.figures import kpi_card, kpi_card_reference + + df_kpi = pd.DataFrame({"Actual": [100, 200, 700], "Reference": [100, 300, 500], "Category": ["A", "B", "C"]}) + + example_cards = [ + kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with value"), + kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with aggregation", agg_func="median"), + kpi_card( + data_frame=df_kpi, + value_column="Actual", + title="KPI with formatting", + value_format="${value:.2f}", + ), + kpi_card( + data_frame=df_kpi, + value_column="Actual", + title="KPI with icon", + icon="shopping_cart", + ), + ] + + example_reference_cards = [ + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + title="KPI reference (pos)", + ), + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + agg_func="median", + title="KPI reference (neg)", + ), + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + title="KPI reference with formatting", + value_format="{value:.2f}€", + reference_format="{delta:+.2f}€ vs. last year ({reference:.2f}€)", + ), + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + title="KPI reference with icon", + icon="shopping_cart", + ), + ] + + # Create a layout with four rows and columns. The KPI cards are positioned in the first eight cells, while the remaining cells are empty. + page = vm.Page( + title="KPI cards", + layout=vm.Layout(grid=[[0, 1, 2, 3], [4, 5, 6, 7], [-1, -1, -1, -1], [-1, -1, -1, -1]]), + + components=[vm.Figure(figure=figure) for figure in example_cards + example_reference_cards], + controls=[vm.Filter(column="Category")], + ) + + dashboard = vm.Dashboard(pages=[page]) + Vizro().build(dashboard).run() + ``` === "app.yaml" ```yaml diff --git a/vizro-core/docs/pages/user-guides/graph.md b/vizro-core/docs/pages/user-guides/graph.md index b0fedebb7..1c3ffc8bc 100755 --- a/vizro-core/docs/pages/user-guides/graph.md +++ b/vizro-core/docs/pages/user-guides/graph.md @@ -10,7 +10,7 @@ To add a [`Graph`][vizro.models.Graph] to your page, do the following: 1. enter any of the currently available charts of the open source library [`plotly.express`](https://plotly.com/python/plotly-express/) into the `figure` argument !!! note - In order to use the [`plotly.express`](https://plotly.com/python/plotly-express/) chart in a Vizro dashboard, you need to import it as `import vizro.plotly.express as px`. This leaves any of the [`plotly.express`](https://plotly.com/python/plotly-express/) functionality untouched, but allows _direct insertion_ into the [`Graph`][vizro.models.Graph] model _as is_. + To use the [`plotly.express`](https://plotly.com/python/plotly-express/) chart in a Vizro dashboard, you need to import it as `import vizro.plotly.express as px`. This leaves any of the [`plotly.express`](https://plotly.com/python/plotly-express/) functionality untouched yet enables _direct insertion_ into the [`Graph`][vizro.models.Graph] model _as is_. Note also that the `plotly.express` chart needs to have a `data_frame` argument. In case you require a chart without a `data_frame` argument (for example, the [`imshow` chart](https://plotly.com/python/imshow/)), refer to our [guide on custom charts](custom-charts.md). @@ -72,14 +72,14 @@ For more details, refer to our [user guide on custom chart](custom-charts.md) an ## Add title, header, and footer -The [`Graph`][vizro.models.Graph] accepts a `title`, `header` and `footer` argument. This is useful for providing context to the data being displayed, or for adding a description of the data. +The [`Graph`][vizro.models.Graph] accepts a `title`, `header` and `footer` argument. This is useful for context on the data being displayed, or for adding a description of the data. - **title**: Displayed as an [H3 header](https://dash.plotly.com/dash-html-components/h3), useful for summarizing the main topic or insight of the component. - **header**: Accepts markdown text, ideal for extra descriptions, subtitles, or detailed data insights. - **footer**: Accepts markdown text, commonly used for citing data sources, providing information on the last update, or adding disclaimers. !!! note - Although you can directly provide a `title` to the Plotly Express chart, we recommend using `Graph.title` for proper alignment with other components on the screen. + Although you can directly give a `title` to the Plotly Express chart, we recommend using `Graph.title` for proper alignment with other components on the screen. !!! example "Formatted Graph" === "app.py" diff --git a/vizro-core/docs/pages/user-guides/kedro-data-catalog.md b/vizro-core/docs/pages/user-guides/kedro-data-catalog.md index cda94d477..2129b7051 100644 --- a/vizro-core/docs/pages/user-guides/kedro-data-catalog.md +++ b/vizro-core/docs/pages/user-guides/kedro-data-catalog.md @@ -34,8 +34,9 @@ The `catalog` variable may have been created in a number of different ways: The full code for these different cases is given below. !!! example "Import a Kedro Data Catalog into the Vizro data manager" + === "app.py (Kedro project path)" - ```py + ```python from vizro.integrations import kedro as kedro_integration from vizro.managers import data_manager @@ -47,7 +48,7 @@ The full code for these different cases is given below. ``` === "app.ipynb (Kedro Jupyter session)" - ```py + ```python from vizro.managers import data_manager @@ -56,7 +57,7 @@ The full code for these different cases is given below. ``` === "app.py (Data Catalog configuration file)" - ```py + ```python from kedro.io import DataCatalog import yaml diff --git a/vizro-core/docs/pages/user-guides/layouts.md b/vizro-core/docs/pages/user-guides/layouts.md index b2fe500c1..af66ec301 100644 --- a/vizro-core/docs/pages/user-guides/layouts.md +++ b/vizro-core/docs/pages/user-guides/layouts.md @@ -412,7 +412,7 @@ For further customization, such as changing the gap between row and column, refe In general, any arbitrarily granular layout can already be achieved using [`Page.layout`](layouts.md) alone and is our recommended approach if you want to arrange components on a page with consistent row and/or column spacing. !!! note "Alternative layout approaches: `Tabs` and `Containers`" - [`Tabs`][vizro.models.Tabs] and [`Containers`][vizro.models.Container] provide an alternative approach to customize your page layout. For example, if you want to have more granular control and break the overall page grid into subgrids, see our [user guide on Containers](container.md). + [`Tabs`][vizro.models.Tabs] and [`Containers`][vizro.models.Container] offer an alternative approach to customize your page layout. For example, if you want to have more granular control and break the overall page grid into subgrids, see our [user guide on Containers](container.md). If you want to display multiple containers on one page by putting them into the same screen space, and letting the user switch between them, see our [user guide on Tabs](tabs.md). diff --git a/vizro-core/docs/pages/user-guides/run.md b/vizro-core/docs/pages/user-guides/run.md index df2ed6bd4..a86a7d17a 100644 --- a/vizro-core/docs/pages/user-guides/run.md +++ b/vizro-core/docs/pages/user-guides/run.md @@ -51,7 +51,7 @@ INFO:werkzeug:WARNING: This is a development server. Do not use it in a producti ``` !!! warning "In production" - As per the above warning message, which is [further explained in the Flask documentation](https://flask.palletsprojects.com/en/3.0.x/deploying/), the Flask development server is intended for use only during local development and **should not** be used when deploying to production. Instead, you should instead use a production-ready solution such as [Gunicorn](#gunicorn). + The above warning message is [further explained in the Flask documentation](https://flask.palletsprojects.com/en/3.0.x/deploying/). The Flask development server is intended for use only during local development and **should not** be used when deploying to production. Instead, you should instead use a production-ready solution such as [Gunicorn](#gunicorn). ### Automatic reloading and debugging @@ -136,7 +136,7 @@ gunicorn app:app --workers 4 in the command line. For more Gunicorn configuration options, refer to [Gunicorn documentation](https://docs.gunicorn.org/). !!! warning "In production" - If your dashboard uses [dynamic data](data.md#dynamic-data) that can be refreshed while the dashboard is running then you should [configure your data manager cache](data.md#configure-cache) to use a backend that supports multiple processes. + If your dashboard uses [dynamic data](data.md#dynamic-data) that can be refreshed while the dashboard is running then you should [configure your data manager cache](data.md#configure-cache) to use a back end that supports multiple processes. ## Deployment diff --git a/vizro-core/docs/pages/user-guides/selectors.md b/vizro-core/docs/pages/user-guides/selectors.md index 8b81b6fb7..f9a3653a3 100644 --- a/vizro-core/docs/pages/user-guides/selectors.md +++ b/vizro-core/docs/pages/user-guides/selectors.md @@ -15,7 +15,7 @@ For more information, refer to the API reference of the selector, or the documen - [`RadioItems`][vizro.models.RadioItems] based on [`dcc.RadioItems`](https://dash.plotly.com/dash-core-components/radioitems) !!! note - When configuring the `options` of the categorical selectors, you can either provide: + When configuring the `options` of the categorical selectors, you can either give: - a list of values `options = ['Value A', 'Value B', 'Value C']` - or a dictionary of label-value mappings `options=[{'label': 'True', 'value': True}, {'label': 'False', 'value': False}]` @@ -30,7 +30,7 @@ For more information, refer to the API reference of the selector, or the documen - [`RangeSlider`][vizro.models.RangeSlider] based on [`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider) !!! note - When configuring the [`Slider`][vizro.models.Slider] and the [`RangeSlider`][vizro.models.RangeSlider] with float values, and using `step` with an integer value, you may notice unexpected behavior, such as the drag value being outside its indicated marks. To our knowledge, this is a current bug in the underlying [`dcc.Slider`](https://dash.plotly.com/dash-core-components/slider) and [`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider) component, which you can circumvent by adapting the `step` size accordingly. + When configuring the [`Slider`][vizro.models.Slider] and the [`RangeSlider`][vizro.models.RangeSlider] with float values, and using `step` with an integer value, you may notice unexpected behavior, such as the drag value being outside its indicated marks. To our knowledge, this is a current bug in the underlying [`dcc.Slider`](https://dash.plotly.com/dash-core-components/slider) and [`dcc.RangeSlider`](https://dash.plotly.com/dash-core-components/rangeslider) component, which you can circumvent by adapting the `step` size as needed. ## Temporal selectors diff --git a/vizro-core/docs/pages/user-guides/themes.md b/vizro-core/docs/pages/user-guides/themes.md index 8a78752a4..ac1d6fc7b 100644 --- a/vizro-core/docs/pages/user-guides/themes.md +++ b/vizro-core/docs/pages/user-guides/themes.md @@ -61,7 +61,7 @@ You can also use our templates for plotly charts outside the dashboard. This is - Rapid development of charts for eventual use in a Vizro dashboard, for example in a Jupyter Notebook. !!! note - Using `import vizro.plotly.express as px` is equivalent to using `import plotly.express as px`, but with the added benefit of being able to integrate the resulting chart code into a Vizro dashboard. Vizro offers a minimal layer on top of Plotly's existing charting library, allowing you to seamlessly use all the existing charts and functionalities provided by plotly.express without any modifications. + Using `import vizro.plotly.express as px` is equal to using `import plotly.express as px`, but with the added benefit of being able to integrate the resulting chart code into a Vizro dashboard. Vizro offers a minimal layer on top of Plotly's existing charting library, allowing you to seamlessly use all the existing charts and functionalities provided by plotly.express without any modifications. Our `vizro_dark` and `vizro_light` themes are automatically registered to `plotly.io.templates` when importing Vizro. Consult the plotly documentation for [more details on how templates work in plotly](https://plotly.com/python/templates/#theming-and-templates). From 06ee31d895d7ae440b48bcf8652a1293ea5a447a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 14:11:30 +0000 Subject: [PATCH 25/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../docs/pages/user-guides/customize-vizro-ai.md | 1 + .../pages/user-guides/vizro-ai-langchain-guide.md | 13 +++++++++---- vizro-core/docs/pages/user-guides/actions.md | 3 ++- vizro-core/docs/pages/user-guides/card-button.md | 2 ++ vizro-core/docs/pages/user-guides/figure.md | 3 +++ .../docs/pages/user-guides/kedro-data-catalog.md | 1 - 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index e1ee74a98..4ae23abad 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -18,6 +18,7 @@ vizro_ai = VizroAI(model="") For the string settings to work, you must supply your API key via environment variables. The relevant variable names to be set are noted in each vendor tab. === "OpenAI" + | Environment variable | Name(s) | | -------------------- | ----------------- | | API key | `OPENAI_API_KEY` | diff --git a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md index ca24371a6..75a67dd07 100644 --- a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md +++ b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md @@ -117,6 +117,7 @@ Now you can use the chain to generate charts or dashboards based on natural lang !!! example "Generate chart code" === "Code" + ```python # Load sample data df = px.data.gapminder() @@ -126,16 +127,16 @@ Now you can use the chain to generate charts or dashboards based on natural lang ``` === "Vizro-AI Generated Code" + ```python import plotly.graph_objects as go from vizro.models.types import capture + @capture("graph") def custom_chart(data_frame): continent_gdp = data_frame.groupby("continent")["gdpPercap"].mean().reset_index() - fig = go.Figure( - data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])] - ) + fig = go.Figure(data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])]) fig.update_layout( title="GDP per Capita by Continent", xaxis_title="Continent", @@ -146,14 +147,18 @@ Now you can use the chain to generate charts or dashboards based on natural lang !!! example "Generate dashboard code" === "Code" + ```python dfs = [px.data.gapminder()] - dashboard_response = chain.invoke("Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp.") + dashboard_response = chain.invoke( + "Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp." + ) print(dashboard_response[0].content) ``` === "Vizro-AI Generated Code" + ```py ############ Imports ############## import vizro.models as vm diff --git a/vizro-core/docs/pages/user-guides/actions.md b/vizro-core/docs/pages/user-guides/actions.md index f2dae6448..84c69067e 100644 --- a/vizro-core/docs/pages/user-guides/actions.md +++ b/vizro-core/docs/pages/user-guides/actions.md @@ -22,9 +22,9 @@ The below sections are guides on how to use pre-defined action functions. To enable downloading data, you can add the [`export_data`][vizro.actions.export_data] action function to the [`Button`][vizro.models.Button] component. Hence, as a result, when a dashboard user now clicks the button, all data on the page will be downloaded. - !!! example "`export_data`" === "app.py" + ```{.python pycafe-link} import vizro.models as vm import vizro.plotly.express as px @@ -59,6 +59,7 @@ To enable downloading data, you can add the [`export_data`][vizro.actions.export ``` === "app.yaml" + ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See yaml_version example diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index 947702254..0158d72d8 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -626,6 +626,7 @@ The example below demonstrates how to configure a button to export the filtered !!! example "Button with action" === "app.py" + ```{.python pycafe-link} import vizro.models as vm import vizro.plotly.express as px @@ -662,6 +663,7 @@ The example below demonstrates how to configure a button to export the filtered ``` === "app.yaml" + ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example diff --git a/vizro-core/docs/pages/user-guides/figure.md b/vizro-core/docs/pages/user-guides/figure.md index 89761b3ab..d274bbee1 100644 --- a/vizro-core/docs/pages/user-guides/figure.md +++ b/vizro-core/docs/pages/user-guides/figure.md @@ -40,6 +40,7 @@ To add a `Figure` to your page: !!! example "Use existing figure functions" === "app.py" + ```{.python pycafe-link} import vizro.models as vm import vizro.plotly.express as px @@ -71,6 +72,7 @@ To add a `Figure` to your page: ``` === "app.yaml" + ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration # See from_yaml example @@ -110,6 +112,7 @@ As described in the [API reference](../API-reference/figure-callables.md) and il !!! example "KPI card variations" === "app.py" + ```{.python pycafe-link} import pandas as pd import vizro.models as vm diff --git a/vizro-core/docs/pages/user-guides/kedro-data-catalog.md b/vizro-core/docs/pages/user-guides/kedro-data-catalog.md index 2129b7051..ce4b060fa 100644 --- a/vizro-core/docs/pages/user-guides/kedro-data-catalog.md +++ b/vizro-core/docs/pages/user-guides/kedro-data-catalog.md @@ -34,7 +34,6 @@ The `catalog` variable may have been created in a number of different ways: The full code for these different cases is given below. !!! example "Import a Kedro Data Catalog into the Vizro data manager" - === "app.py (Kedro project path)" ```python from vizro.integrations import kedro as kedro_integration From f457d4e635884b3250379517b7ac2b62432b5c4c Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 14:19:17 +0000 Subject: [PATCH 26/54] Update add-generated-chart-usecase.md --- .../add-generated-chart-usecase.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index 9ab422cb2..5cbbcec83 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -10,28 +10,28 @@ This guide explains the different ways in which you can add a chart generated by !!! example "Vizro-AI chart" === "Code for the cell" - ```py - import vizro_ai - from vizro_ai import VizroAI - import vizro.plotly.express as px - from dotenv import load_dotenv - - load_dotenv() - - df = px.data.gapminder() - vizro_ai = VizroAI(model="gpt-4o") - - result = vizro_ai.plot(df, - """Plot a bubble chart to show the changes in life expectancy - and GDP per capita for each country over time. - Color the bubbles by continent. - Add animation on yearly basis, and do not use facets. - Put the legend on top""", return_elements=True) - - print(f"Insight:\n{result.chart_insights}\n" ) - print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n" ) - result.get_fig_object(df).show() - ``` + ```python + import vizro_ai + from vizro_ai import VizroAI + import vizro.plotly.express as px + from dotenv import load_dotenv + + load_dotenv() + + df = px.data.gapminder() + vizro_ai = VizroAI(model="gpt-4o") + + result = vizro_ai.plot(df, + """Plot a bubble chart to show the changes in life expectancy + and GDP per capita for each country over time. + Color the bubbles by continent. + Add animation on yearly basis, and do not use facets. + Put the legend on top""", return_elements=True) + + print(f"Insight:\n{result.chart_insights}\n" ) + print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n" ) + result.get_fig_object(df).show() + ``` === "Result" [![VizroAIChart]][vizroaichart] From aa65b5a67d6b0988a1c20c6d8f96dd788aede541 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 14:21:41 +0000 Subject: [PATCH 27/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../user-guides/add-generated-chart-usecase.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index 5cbbcec83..deb3e9559 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -10,6 +10,7 @@ This guide explains the different ways in which you can add a chart generated by !!! example "Vizro-AI chart" === "Code for the cell" + ```python import vizro_ai from vizro_ai import VizroAI @@ -21,15 +22,18 @@ This guide explains the different ways in which you can add a chart generated by df = px.data.gapminder() vizro_ai = VizroAI(model="gpt-4o") - result = vizro_ai.plot(df, - """Plot a bubble chart to show the changes in life expectancy + result = vizro_ai.plot( + df, + """Plot a bubble chart to show the changes in life expectancy and GDP per capita for each country over time. Color the bubbles by continent. Add animation on yearly basis, and do not use facets. - Put the legend on top""", return_elements=True) + Put the legend on top""", + return_elements=True, + ) - print(f"Insight:\n{result.chart_insights}\n" ) - print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n" ) + print(f"Insight:\n{result.chart_insights}\n") + print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n") result.get_fig_object(df).show() ``` From 8db5eff548fb8c97c4d43a48732e08d3b22066c8 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Fri, 29 Nov 2024 14:38:14 +0000 Subject: [PATCH 28/54] Remove Vale from automated linting --- .pre-commit-config.yaml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3ace1e43c..5996e20ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -96,18 +96,7 @@ repos: exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md additional_dependencies: - mdformat-mkdocs[recommended]==3.1.1 - - - repo: https://github.com/errata-ai/vale - rev: v3.8.0 - hooks: - - id: vale - args: [--config=.vale/.vale.ini] - # There's no way to automatically convert vale suggestions/warnings to errors, and so they won't appear at all unless - # there's an error raised. - # pre-commit's verbose mode means that suggestions and warnings are always shown even if there's no error raised. - # See https://github.com/errata-ai/vale/issues/575. - verbose: true - + # Configuration for https://pre-commit.ci/. ci: autoupdate_schedule: monthly From 3c3e6879300314ddc8c009696aaec8de50064b93 Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Mon, 2 Dec 2024 13:01:21 +0100 Subject: [PATCH 29/54] Revert "Automatically lint" This reverts commit 7692bb3316ead27ebf046a66397d4d859c02f8e5, reversing changes made to ac031783578eb5f39daf19443c3f197dfc0b344b. --- .github/pull_request_template.md | 10 ++++---- .pre-commit-config.yaml | 4 ++-- vizro-core/CHANGELOG.md | 40 ++++++++++++++++---------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 44e958f1c..ea40a09f2 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,8 +6,8 @@ - [ ] I acknowledge and agree that, by checking this box and clicking "Submit Pull Request": - - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. - - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. - - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. - - I have not referenced individuals, products or companies in any commits, directly or indirectly. - - I have not added data or restricted code in any commits, directly or indirectly. + - I submit this contribution under the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable. + - I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees. + - I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else. + - I have not referenced individuals, products or companies in any commits, directly or indirectly. + - I have not added data or restricted code in any commits, directly or indirectly. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6aa25e97b..5996e20ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -89,7 +89,6 @@ repos: - id: mdformat args: [ - --help, --ignore-missing-references, --wrap=no, --align-semantic-breaks-in-lists, @@ -97,7 +96,7 @@ repos: exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md additional_dependencies: - mdformat-mkdocs[recommended]==3.1.1 - + # Configuration for https://pre-commit.ci/. ci: autoupdate_schedule: monthly @@ -112,3 +111,4 @@ ci: - codespell - bandit - mypy + - vale diff --git a/vizro-core/CHANGELOG.md b/vizro-core/CHANGELOG.md index d58a93859..a515e182d 100644 --- a/vizro-core/CHANGELOG.md +++ b/vizro-core/CHANGELOG.md @@ -548,10 +548,10 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse - Optimize the client-server communication ([#34](https://github.com/mckinsey/vizro/pull/34)) - - Eliminate most server side callbacks in favor of client-side callbacks - - Add tests for client-side callbacks written in Node.js framework called `jest`. - - Add hatch command `hatch run test-js` that runs unit tests written in `jest`. - - Logging information now only displayed for action function carried out (no trigger or finished information) + - Eliminate most server side callbacks in favor of client-side callbacks + - Add tests for client-side callbacks written in Node.js framework called `jest`. + - Add hatch command `hatch run test-js` that runs unit tests written in `jest`. + - Logging information now only displayed for action function carried out (no trigger or finished information) - Replaced all screenshots in the docs to reflect new navigation designs ([#48](https://github.com/mckinsey/vizro/pull/48)) @@ -595,21 +595,21 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse - Add the following pydantic models: - - Action - - Button - - Card - - Checklist - - Dashboard - - Dropdown - - Filter - - Graph - - Layout - - Navigation - - Page - - Parameter - - RadioItems - - RangeSlider - - Slider - - VizroBaseModel + - Action + - Button + - Card + - Checklist + - Dashboard + - Dropdown + - Filter + - Graph + - Layout + - Navigation + - Page + - Parameter + - RadioItems + - RangeSlider + - Slider + - VizroBaseModel - Enable the addition and usage of custom components and custom charts From 93bf71f5a6eca989b03c784e3b9a616f8e47f4e6 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Mon, 2 Dec 2024 12:45:41 +0000 Subject: [PATCH 30/54] Update 20241129_095703_huong_li_nguyen_replace_switch.md --- .../20241129_095703_huong_li_nguyen_replace_switch.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vizro-core/changelog.d/20241129_095703_huong_li_nguyen_replace_switch.md b/vizro-core/changelog.d/20241129_095703_huong_li_nguyen_replace_switch.md index 1e33f72e1..e29793406 100644 --- a/vizro-core/changelog.d/20241129_095703_huong_li_nguyen_replace_switch.md +++ b/vizro-core/changelog.d/20241129_095703_huong_li_nguyen_replace_switch.md @@ -10,12 +10,14 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + + + + {% endfor -%} diff --git a/vizro-ai/docs/index.md b/vizro-ai/docs/index.md index 4c9f4a2f3..9d6b190fb 100644 --- a/vizro-ai/docs/index.md +++ b/vizro-ai/docs/index.md @@ -14,23 +14,23 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- - [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md)
+ [:octicons-arrow-right-24: Install Vizro-AI](pages/user-guides/install.md) - [:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md)
+ [:octicons-arrow-right-24: Quickstart chart generation](pages/tutorials/quickstart.md) - [:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md)
+ [:octicons-arrow-right-24: Quickstart dashboard generation](pages/tutorials/quickstart-dashboard.md) - :fontawesome-solid-keyboard:{ .lg .middle } __Get hands-on__ --- - [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md)
+ [:octicons-arrow-right-24: How to run Vizro-AI](pages/user-guides/run-vizro-ai.md) - [:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md)
+ [:octicons-arrow-right-24: Model usage](pages/user-guides/customize-vizro-ai.md) - [:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md)
+ [:octicons-arrow-right-24: Create advanced charts](pages/user-guides/create-advanced-charts.md) - [:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md)
+ [:octicons-arrow-right-24: Add charts to a dashboard](pages/user-guides/add-generated-chart-usecase.md) [:octicons-arrow-right-24: Retrieve code for a generated dashboard](pages/user-guides/run-vizro-ai-dashboard.md) @@ -38,9 +38,9 @@ Even if you are an experienced data practitioner, Vizro-AI optimizes how you cre --- - [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md)
+ [:octicons-arrow-right-24: FAQs](pages/explanation/faq.md) - [:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md)
+ [:octicons-arrow-right-24: Safeguard dynamic code execution](pages/explanation/safeguard.md) [:octicons-arrow-right-24: Guidelines for use of LLMs](pages/explanation/safety-in-vizro-ai.md) diff --git a/vizro-core/CHANGELOG.md b/vizro-core/CHANGELOG.md index d58a93859..a515e182d 100644 --- a/vizro-core/CHANGELOG.md +++ b/vizro-core/CHANGELOG.md @@ -548,10 +548,10 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse - Optimize the client-server communication ([#34](https://github.com/mckinsey/vizro/pull/34)) - - Eliminate most server side callbacks in favor of client-side callbacks - - Add tests for client-side callbacks written in Node.js framework called `jest`. - - Add hatch command `hatch run test-js` that runs unit tests written in `jest`. - - Logging information now only displayed for action function carried out (no trigger or finished information) + - Eliminate most server side callbacks in favor of client-side callbacks + - Add tests for client-side callbacks written in Node.js framework called `jest`. + - Add hatch command `hatch run test-js` that runs unit tests written in `jest`. + - Logging information now only displayed for action function carried out (no trigger or finished information) - Replaced all screenshots in the docs to reflect new navigation designs ([#48](https://github.com/mckinsey/vizro/pull/48)) @@ -595,21 +595,21 @@ See the fragment files in the [changelog.d directory](https://github.com/mckinse - Add the following pydantic models: - - Action - - Button - - Card - - Checklist - - Dashboard - - Dropdown - - Filter - - Graph - - Layout - - Navigation - - Page - - Parameter - - RadioItems - - RangeSlider - - Slider - - VizroBaseModel + - Action + - Button + - Card + - Checklist + - Dashboard + - Dropdown + - Filter + - Graph + - Layout + - Navigation + - Page + - Parameter + - RadioItems + - RangeSlider + - Slider + - VizroBaseModel - Enable the addition and usage of custom components and custom charts diff --git a/vizro-core/README.md b/vizro-core/README.md index 826f708ee..283717094 100644 --- a/vizro-core/README.md +++ b/vizro-core/README.md @@ -11,13 +11,7 @@
-[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) - -[![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) - -[![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) - -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858) +[![Python version](https://img.shields.io/badge/python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://pypi.org/project/vizro/) [![PyPI version](https://badge.fury.io/py/vizro.svg)](https://badge.fury.io/py/vizro) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/mckinsey/vizro/blob/main/LICENSE.md) [![Documentation](https://readthedocs.org/projects/vizro/badge/?version=stable)](https://vizro.readthedocs.io/) [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7858/badge)](https://www.bestpractices.dev/projects/7858)
diff --git a/vizro-core/docs/index.md b/vizro-core/docs/index.md index 11346d4f8..e9886376b 100644 --- a/vizro-core/docs/index.md +++ b/vizro-core/docs/index.md @@ -8,7 +8,7 @@ Vizro is a toolkit for creating modular data visualization applications. --- - [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md)
+ [:octicons-arrow-right-24: Quickstart tutorial](pages/tutorials/first-dashboard.md) [:octicons-arrow-right-24: Install Vizro](pages/user-guides/install.md) @@ -16,11 +16,11 @@ Vizro is a toolkit for creating modular data visualization applications. --- - [:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md)
+ [:octicons-arrow-right-24: Fundamentals](pages/user-guides/dashboard.md) - [:octicons-arrow-right-24: Components overview](pages/user-guides/components.md)
+ [:octicons-arrow-right-24: Components overview](pages/user-guides/components.md) - [:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md)
+ [:octicons-arrow-right-24: Filters, parameters and selectors](pages/user-guides/filters.md) [:octicons-arrow-right-24: Visual formatting](pages/user-guides/visual-formatting.md) @@ -28,7 +28,7 @@ Vizro is a toolkit for creating modular data visualization applications. --- - [:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md)
+ [:octicons-arrow-right-24: Tutorials](pages/tutorials/explore-components.md) [:octicons-arrow-right-24: Examples](https://vizro.mckinsey.com) @@ -36,17 +36,17 @@ Vizro is a toolkit for creating modular data visualization applications. --- - [:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit)
+ [:octicons-arrow-right-24: How is Vizro different to Streamlit?](pages/explanation/faq.md/#how-does-vizro-differ-from-dash-or-streamlit) - [:octicons-arrow-right-24: Where can I ask a question?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it)
+ [:octicons-arrow-right-24: Where can I ask a question?](pages/explanation/faq.md/#i-still-have-a-question-where-can-i-ask-it) - [:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md)
+ [:octicons-arrow-right-24: Other FAQs](pages/explanation/faq.md) - :fontawesome-solid-hands-holding-circle:{ .lg .middle } __Get involved__ --- - [:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md)
+ [:octicons-arrow-right-24: Contribute code](pages/explanation/contributing.md) [:octicons-arrow-right-24: Contribute to our docs](pages/explanation/documentation-style-guide.md) From 612a58d14ef1682e3079818e6c5ad580909c2c80 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 14:48:31 +0000 Subject: [PATCH 35/54] Fix merge --- .pre-commit-config.yaml | 1 - ...655_huong_li_nguyen_refactor_bs_example.md | 6 ++ vizro-core/docs/pages/user-guides/data.md | 81 +++++++++---------- vizro-core/docs/pages/user-guides/filters.md | 47 ++++++----- 4 files changed, 68 insertions(+), 67 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 21bc464cf..e85739768 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -112,4 +112,3 @@ ci: - codespell - bandit - mypy - diff --git a/vizro-core/changelog.d/20241202_150655_huong_li_nguyen_refactor_bs_example.md b/vizro-core/changelog.d/20241202_150655_huong_li_nguyen_refactor_bs_example.md index 7c0d58d4f..4abc0f11e 100644 --- a/vizro-core/changelog.d/20241202_150655_huong_li_nguyen_refactor_bs_example.md +++ b/vizro-core/changelog.d/20241202_150655_huong_li_nguyen_refactor_bs_example.md @@ -10,36 +10,42 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + + + + + + + In a development environment the easiest way to enable caching is to use a [simple memory cache](https://cachelib.readthedocs.io/en/stable/simple/) with the default configuration options. This is achieved by adding one line to the above example to set `data_manager.cache`: !!! example "Simple cache with default timeout of 5 minutes" - ```py hl_lines="13" from flask_caching import Cache from vizro import Vizro @@ -225,7 +222,6 @@ data_manager.cache = Cache(config={"CACHE_TYPE": "SimpleCache", "CACHE_DEFAULT_T ``` !!! warning - Simple cache exists purely for single-process development purposes and is not intended to be used in production. If you deploy with multiple workers, [for example with Gunicorn](run.md/#gunicorn), then you should use a production-ready cache backend. All of Flask-Caching's [built-in backends](https://flask-caching.readthedocs.io/en/latest/#built-in-cache-backends) other than `SimpleCache` are suitable for production. In particular, you might like to use [`FileSystemCache`](https://cachelib.readthedocs.io/en/stable/file/) or [`RedisCache`](https://cachelib.readthedocs.io/en/stable/redis/): ```py title="Production-ready caches" @@ -239,7 +235,9 @@ data_manager.cache = Cache(config={"CACHE_TYPE": "SimpleCache", "CACHE_DEFAULT_T Since Flask-Caching relies on [`pickle`](https://docs.python.org/3/library/pickle.html), which can execute arbitrary code during unpickling, you should not cache data from untrusted sources. Doing so [could be unsafe](https://github.com/pallets-eco/flask-caching/pull/209). Note that when a production-ready cache backend is used, the cache is persisted beyond the Vizro process and is not cleared by restarting your server. To clear the cache then you must do so manually, for example, if you use `FileSystemCache` then you would delete your `cache` directory. Persisting the cache can also be useful for development purposes when handling data that takes a long time to load: even if you do not need the data to refresh while your dashboard is running, it can speed up your development loop to use dynamic data with a cache that is persisted between repeated runs of Vizro. + + #### Set timeouts You can change the timeout of the cache independently for each dynamic data source in the data manager using the `timeout` setting (measured in seconds). A `timeout` of 0 indicates that the cache does not expire. This is effectively the same as using [static data](#static-data). @@ -278,8 +276,8 @@ In general, a parametrized dynamic data source should always return a pandas Dat To add a parameter to control a dynamic data source, do the following: 1. add the appropriate argument to your dynamic data function and specify a default value for the argument. -2. give an `id` to all components that have the data source you wish to alter through a parameter. -3. [add a parameter](parameters.md) with `targets` of the form `.data_frame.` and a suitable [selector](selectors.md). +1. give an `id` to all components that have the data source you wish to alter through a parameter. +1. [add a parameter](parameters.md) with `targets` of the form `.data_frame.` and a suitable [selector](selectors.md). For example, let us extend the [dynamic data example](#dynamic-data) above into an example of how parametrized dynamic data works. The `load_iris_data` can take an argument `number_of_points` controlled from the dashboard with a [`Slider`][vizro.models.Slider]. @@ -318,21 +316,18 @@ For example, let us extend the [dynamic data example](#dynamic-data) above into ``` 1. `load_iris_data` takes a single argument, `number_of_points`, with a default value of 10. - 2. `iris` is a pandas DataFrame created by reading from the CSV file `iris.csv`. - 3. Sample points at random, where `number_of_points` gives the number of points selected. - 4. To use `load_iris_data` as dynamic data it must be added to the data manager. You should **not** actually call the function as `load_iris_data()` or `load_iris_data(number_of_points=...)`; doing so would result in static data that cannot be reloaded. - 5. Give the `vm.Graph` component `id="graph"` so that the `vm.Parameter` can target it. Dynamic data is referenced by the name of the data source `"iris"`. - 6. Create a `vm.Parameter` to target the `number_of_points` argument for the `data_frame` used in `graph`. + 1. `iris` is a pandas DataFrame created by reading from the CSV file `iris.csv`. + 1. Sample points at random, where `number_of_points` gives the number of points selected. + 1. To use `load_iris_data` as dynamic data it must be added to the data manager. You should **not** actually call the function as `load_iris_data()` or `load_iris_data(number_of_points=...)`; doing so would result in static data that cannot be reloaded. + 1. Give the `vm.Graph` component `id="graph"` so that the `vm.Parameter` can target it. Dynamic data is referenced by the name of the data source `"iris"`. + 1. Create a `vm.Parameter` to target the `number_of_points` argument for the `data_frame` used in `graph`. === "Result" - [![ParametrizedDynamicData]][ParametrizedDynamicData] - - [ParametrizedDynamicData]: ../../assets/user_guides/data/parametrized_dynamic_data.gif + [![ParametrizedDynamicData]][parametrizeddynamicdata] Parametrized data loading is compatible with [caching](#configure-cache). The cache uses [memoization](https://flask-caching.readthedocs.io/en/latest/#memoization), so that the dynamic data function's arguments are included in the cache key. This means that `load_iris_data(number_of_points=10)` is cached independently of `load_iris_data(number_of_points=20)`. !!! warning - You should always [treat the content of user input as untrusted](https://community.plotly.com/t/writing-secure-dash-apps-community-thread/54619). For example, you should not expose a filepath to load without passing it through a function like [`werkzeug.utils.secure_filename`](https://werkzeug.palletsprojects.com/en/3.0.x/utils/#werkzeug.utils.secure_filename), or you might enable arbitrary access to files on your server. You cannot pass [nested parameters](parameters.md#nested-parameters) to dynamic data. You can only target the top-level arguments of the data loading function, not the nested keys in a dictionary. @@ -354,7 +349,6 @@ When the page is refreshed, the behavior of a dynamic filter is as follows: For example, let us add two filters to the [dynamic data example](#dynamic-data) above: !!! example "Dynamic filters" - ```py hl_lines="10 20 21" from vizro import Vizro import pandas as pd @@ -386,8 +380,8 @@ For example, let us add two filters to the [dynamic data example](#dynamic-data) ``` 1. We sample only 5 rather than 50 points so that changes to the available values in the filtered columns are more apparent when the page is refreshed. - 2. This filter implicitly controls the dynamic data source `"iris"`, which supplies the `data_frame` to the targeted `vm.Graph`. On page refresh, Vizro reloads this data, finds all the unique values in the `"species"` column and sets the categorical selector's `options` accordingly. - 3. Similarly, on page refresh, Vizro finds the minimum and maximum values of the `"sepal_length"` column in the reloaded data and sets new `min` and `max` values for the numerical selector accordingly. + 1. This filter implicitly controls the dynamic data source `"iris"`, which supplies the `data_frame` to the targeted `vm.Graph`. On page refresh, Vizro reloads this data, finds all the unique values in the `"species"` column and sets the categorical selector's `options` accordingly. + 1. Similarly, on page refresh, Vizro finds the minimum and maximum values of the `"sepal_length"` column in the reloaded data and sets new `min` and `max` values for the numerical selector accordingly. Consider a filter that depends on dynamic data, where you do **not** want the available values to change when the dynamic data changes. You should manually specify the `selector`'s `options` field (categorical selector) or `min` and `max` fields (numerical selector). In the above example, this could be achieved as follows: @@ -409,10 +403,13 @@ controls = [ When Vizro initially builds a filter that depends on parametrized dynamic data loading, data is loaded using the default argument values. This data is used to: -* perform initial validation -* check which data sources contain the specified `column` (unless `targets` is explicitly specified) and -* find the type of selector to use (unless `selector` is explicitly specified). +- perform initial validation +- check which data sources contain the specified `column` (unless `targets` is explicitly specified) and +- find the type of selector to use (unless `selector` is explicitly specified). !!! note - When the value of a dynamic data parameter is changed by a dashboard user, the data underlying a dynamic filter can change. Currently this change affects page components such as `vm.Graph` but does not affect the available values shown in a dynamic filter, which only update on page refresh. This functionality will be coming soon! + +[databasic]: ../../assets/user_guides/data/data_pandas_dataframe.png +[dynamicdata]: ../../assets/user_guides/data/dynamic_data.gif +[parametrizeddynamicdata]: ../../assets/user_guides/data/parametrized_dynamic_data.gif diff --git a/vizro-core/docs/pages/user-guides/filters.md b/vizro-core/docs/pages/user-guides/filters.md index bc3649178..8228ecbe7 100644 --- a/vizro-core/docs/pages/user-guides/filters.md +++ b/vizro-core/docs/pages/user-guides/filters.md @@ -2,8 +2,7 @@ This guide shows you how to add filters to your dashboard. One main way to interact with the charts/components on your page is by filtering the underlying data. A filter selects a subset of rows of a component's underlying DataFrame which alters the appearance of that component on the page. -The [`Page`][vizro.models.Page] model accepts the `controls` argument, where you can enter a [`Filter`][vizro.models.Filter] model. -This model enables the automatic creation of [selectors](selectors.md) (for example, `Dropdown` or `RangeSlider`) that operate on the charts/components on the screen. +The [`Page`][vizro.models.Page] model accepts the `controls` argument, where you can enter a [`Filter`][vizro.models.Filter] model. This model enables the automatic creation of [selectors](selectors.md) (for example, `Dropdown` or `RangeSlider`) that operate on the charts/components on the screen. By default, filters that control components with [dynamic data](data.md#dynamic-data) are [dynamically updated](data.md#filters) when the underlying data changes while the dashboard is running. @@ -12,7 +11,7 @@ By default, filters that control components with [dynamic data](data.md#dynamic- To add a filter to your page, do the following: 1. add the [`Filter`][vizro.models.Filter] model into the `controls` argument of the [`Page`][vizro.models.Page] model -2. configure the `column` argument, which denotes the target column to be filtered +1. configure the `column` argument, which denotes the target column to be filtered You can also set `targets` to specify which components on the page the filter should apply to. If this is not explicitly set then `targets` defaults to all components on the page whose data source includes `column`. @@ -39,6 +38,7 @@ You can also set `targets` to specify which components on the page the filter sh Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -57,17 +57,15 @@ You can also set `targets` to specify which components on the page the filter sh type: filter title: My first page ``` - === "Result" - [![Filter]][Filter] - - [Filter]: ../../assets/user_guides/control/control1.png + === "Result" + [![Filter]][filter] The selector is configured automatically based on the target column type data as follows: - - Categorical data uses [`vm.Dropdown(multi=True)`][vizro.models.Dropdown] where `options` is the set of unique values found in `column` across all the data sources of components in `targets`. - - [Numerical data](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_numeric_dtype.html) uses [`vm.RangeSlider`][vizro.models.RangeSlider] where `min` and `max` are the overall minimum and maximum values found in `column` across all the data sources of components in `targets`. - - [Temporal data](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_datetime64_any_dtype.html) uses [`vm.DatePicker(range=True)`][vizro.models.DatePicker] where `min` and `max` are the overall minimum and maximum values found in `column` across all the data sources of components in `targets`. A column can be converted to this type with [pandas.to_datetime](https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html). +- Categorical data uses [`vm.Dropdown(multi=True)`][vizro.models.Dropdown] where `options` is the set of unique values found in `column` across all the data sources of components in `targets`. +- [Numerical data](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_numeric_dtype.html) uses [`vm.RangeSlider`][vizro.models.RangeSlider] where `min` and `max` are the overall minimum and maximum values found in `column` across all the data sources of components in `targets`. +- [Temporal data](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_datetime64_any_dtype.html) uses [`vm.DatePicker(range=True)`][vizro.models.DatePicker] where `min` and `max` are the overall minimum and maximum values found in `column` across all the data sources of components in `targets`. A column can be converted to this type with [pandas.to_datetime](https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html). The following example demonstrates these default selector types. @@ -107,6 +105,7 @@ The following example demonstrates these default selector types. Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -129,15 +128,13 @@ The following example demonstrates these default selector types. type: filter title: My first page ``` - === "Result" - [![Filter]][Filter] - [Filter]: ../../assets/user_guides/selectors/default_filter_selectors.png + === "Result" + [![Filter]][filter] ## Change selector -If you want to have a different selector for your filter, you can give the `selector` argument of the [`Filter`][vizro.models.Filter] a different selector model. -Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropdown`][vizro.models.Dropdown], [`RadioItems`][vizro.models.RadioItems], [`RangeSlider`][vizro.models.RangeSlider], [`Slider`][vizro.models.Slider], and [`DatePicker`][vizro.models.DatePicker]. +If you want to have a different selector for your filter, you can give the `selector` argument of the [`Filter`][vizro.models.Filter] a different selector model. Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropdown`][vizro.models.Dropdown], [`RadioItems`][vizro.models.RadioItems], [`RangeSlider`][vizro.models.RangeSlider], [`Slider`][vizro.models.Slider], and [`DatePicker`][vizro.models.DatePicker]. !!! example "Filter with different selector" === "app.py" @@ -162,6 +159,7 @@ Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropd Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -181,11 +179,9 @@ Currently available selectors are [`Checklist`][vizro.models.Checklist], [`Dropd type: filter title: My first page ``` - === "Result" - - [![Selector]][Selector] - [Selector]: ../../assets/user_guides/control/control2.png + === "Result" + [![Selector]][selector] ## Further customization @@ -220,6 +216,7 @@ Below is an advanced example where we only target one page component, and where Vizro().build(dashboard).run() ``` + === "app.yaml" ```yaml # Still requires a .py to add data to the data manager and parse YAML configuration @@ -244,17 +241,19 @@ Below is an advanced example where we only target one page component, and where controls: - column: petal_length targets: - - scatter_chart + - scatter_chart selector: step: 1 type: range_slider type: filter title: My first page ``` - === "Result" - - [![Advanced]][Advanced] - [Advanced]: ../../assets/user_guides/control/control3.png + === "Result" + [![Advanced]][advanced] To further customize selectors, see our [how-to-guide on creating custom components](custom-components.md). + +[advanced]: ../../assets/user_guides/control/control3.png +[filter]: ../../assets/user_guides/control/control1.png +[selector]: ../../assets/user_guides/control/control2.png From bfe1548c2e10a8060bfc677a6c05cf61490248d0 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Tue, 3 Dec 2024 15:02:31 +0000 Subject: [PATCH 36/54] Fix code font on URL --- vizro-core/docs/pages/user-guides/run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-core/docs/pages/user-guides/run.md b/vizro-core/docs/pages/user-guides/run.md index a86a7d17a..028eb5027 100644 --- a/vizro-core/docs/pages/user-guides/run.md +++ b/vizro-core/docs/pages/user-guides/run.md @@ -149,6 +149,6 @@ Internally, `app = Vizro()` contains a Flask app in `app.dash.server`. However, [`Vizro`][vizro.Vizro] accepts `**kwargs` that are passed through to `Dash`. This enables you to configure the underlying Dash app using the same [arguments that are available](https://dash.plotly.com/reference#dash.dash) in `Dash`. For example, in a deployment context, these arguments may be useful: -- `url_base_pathname`: serve your Vizro app at a specific path rather than at the domain root. For example, if you host your dashboard at http://www.example.com/my_dashboard/ then you would set `url_base_pathname="/my_dashboard/"` or an environment variable `DASH_URL_BASE_PATHNAME="/my_dashboard/"`. +- `url_base_pathname`: serve your Vizro app at a specific path rather than at the domain root. For example, if you host your dashboard at `http://www.example.com/my_dashboard/` then you would set `url_base_pathname="/my_dashboard/"` or an environment variable `DASH_URL_BASE_PATHNAME="/my_dashboard/"`. - `serve_locally`: set to `False` to [serve Dash component libraries from a Content Delivery Network (CDN)](https://dash.plotly.com/external-resources#serving-dash's-component-libraries-locally-or-from-a-cdn), which reduces load on the server and can improve performance. Vizro uses [jsDeliver](https://www.jsdelivr.com/) as a CDN for CSS and JavaScript sources. - `assets_external_path`: when `serve_locally=False`, you can also set `assets_external_path` or an environment variable `DASH_ASSETS_EXTERNAL_PATH` to [serve your own assets from a CDN](https://dash.plotly.com/external-resources#load-assets-from-a-folder-hosted-on-a-cdn). From 66eeb0e5a2dc136383a283711f0ffa58c969989e Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Tue, 3 Dec 2024 15:02:41 +0000 Subject: [PATCH 37/54] Fix layout of admonition --- vizro-core/docs/pages/user-guides/figure.md | 106 ++++++++++---------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/vizro-core/docs/pages/user-guides/figure.md b/vizro-core/docs/pages/user-guides/figure.md index d274bbee1..af423d5ec 100644 --- a/vizro-core/docs/pages/user-guides/figure.md +++ b/vizro-core/docs/pages/user-guides/figure.md @@ -40,62 +40,60 @@ To add a `Figure` to your page: !!! example "Use existing figure functions" === "app.py" - - ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.figures import kpi_card - - tips = px.data.tips - - # Create a layout with five rows and four columns. The KPI card is positioned in the first cell, while the remaining cells are empty. - page = vm.Page( - title="KPI card", - layout=vm.Layout(grid=[[0, -1, -1, -1]] + [[-1, -1, -1, -1]] * 4), - components=[ - vm.Figure( - figure=kpi_card( # For more information, refer to the API reference for kpi_card - data_frame=tips, - value_column="tip", - value_format="${value:.2f}", - icon="shopping_cart", - title="KPI card I", - ) - ) - ], - controls=[vm.Filter(column="day", selector=vm.RadioItems())], - ) - - dashboard = vm.Dashboard(pages=[page]) - Vizro().build(dashboard).run() - ``` - + ```{.python pycafe-link} + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.figures import kpi_card + + tips = px.data.tips + + # Create a layout with five rows and four columns. The KPI card is positioned in the first cell, while the remaining cells are empty. + page = vm.Page( + title="KPI card", + layout=vm.Layout(grid=[[0, -1, -1, -1]] + [[-1, -1, -1, -1]] * 4), + components=[ + vm.Figure( + figure=kpi_card( # For more information, refer to the API reference for kpi_card + data_frame=tips, + value_column="tip", + value_format="${value:.2f}", + icon="shopping_cart", + title="KPI card I", + ) + ) + ], + controls=[vm.Filter(column="day", selector=vm.RadioItems())], + ) + + dashboard = vm.Dashboard(pages=[page]) + Vizro().build(dashboard).run() + ``` === "app.yaml" - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See from_yaml example - pages: - - components: - - figure: - _target_: kpi_card - data_frame: tips - value_column: tip - value_format: ${value:.2f} - icon: shopping_cart - title: KPI card I - type: figure - controls: - - column: day - type: filter - selector: - type: radio_items - layout: - grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], - [-1, -1, -1, -1]] - title: KPI card - ``` + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See from_yaml example + pages: + - components: + - figure: + _target_: kpi_card + data_frame: tips + value_column: tip + value_format: ${value:.2f} + icon: shopping_cart + title: KPI card I + type: figure + controls: + - column: day + type: filter + selector: + type: radio_items + layout: + grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], + [-1, -1, -1, -1]] + title: KPI card + ``` === "Result" [![Figure]][figure] From e9905aa7a8261675c394c115d0bc4d0da191dbbb Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Tue, 3 Dec 2024 15:03:50 +0000 Subject: [PATCH 38/54] Update figure.md --- vizro-core/docs/pages/user-guides/figure.md | 100 ++++++++++---------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/vizro-core/docs/pages/user-guides/figure.md b/vizro-core/docs/pages/user-guides/figure.md index af423d5ec..67acf9ce4 100644 --- a/vizro-core/docs/pages/user-guides/figure.md +++ b/vizro-core/docs/pages/user-guides/figure.md @@ -41,58 +41,58 @@ To add a `Figure` to your page: !!! example "Use existing figure functions" === "app.py" ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.figures import kpi_card - - tips = px.data.tips - - # Create a layout with five rows and four columns. The KPI card is positioned in the first cell, while the remaining cells are empty. - page = vm.Page( - title="KPI card", - layout=vm.Layout(grid=[[0, -1, -1, -1]] + [[-1, -1, -1, -1]] * 4), - components=[ - vm.Figure( - figure=kpi_card( # For more information, refer to the API reference for kpi_card - data_frame=tips, - value_column="tip", - value_format="${value:.2f}", - icon="shopping_cart", - title="KPI card I", - ) - ) - ], - controls=[vm.Filter(column="day", selector=vm.RadioItems())], - ) - - dashboard = vm.Dashboard(pages=[page]) - Vizro().build(dashboard).run() - ``` - === "app.yaml" + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.figures import kpi_card + + tips = px.data.tips + + # Create a layout with five rows and four columns. The KPI card is positioned in the first cell, while the remaining cells are empty. + page = vm.Page( + title="KPI card", + layout=vm.Layout(grid=[[0, -1, -1, -1]] + [[-1, -1, -1, -1]] * 4), + components=[ + vm.Figure( + figure=kpi_card( # For more information, refer to the API reference for kpi_card + data_frame=tips, + value_column="tip", + value_format="${value:.2f}", + icon="shopping_cart", + title="KPI card I", + ) + ) + ], + controls=[vm.Filter(column="day", selector=vm.RadioItems())], + ) + + dashboard = vm.Dashboard(pages=[page]) + Vizro().build(dashboard).run() + ``` + === "app.yaml" ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See from_yaml example - pages: - - components: - - figure: - _target_: kpi_card - data_frame: tips - value_column: tip - value_format: ${value:.2f} - icon: shopping_cart - title: KPI card I - type: figure - controls: - - column: day - type: filter - selector: - type: radio_items - layout: - grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], - [-1, -1, -1, -1]] - title: KPI card + # Still requires a .py to add data to the data manager and parse YAML configuration + # See from_yaml example + pages: + - components: + - figure: + _target_: kpi_card + data_frame: tips + value_column: tip + value_format: ${value:.2f} + icon: shopping_cart + title: KPI card I + type: figure + controls: + - column: day + type: filter + selector: + type: radio_items + layout: + grid: [[0, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], + [-1, -1, -1, -1]] + title: KPI card ``` === "Result" From 8436fa9e1290c1a55ab2eefe13360af23c542ba3 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 14:50:47 +0000 Subject: [PATCH 39/54] Changelog --- .../20241203_145037_antony.milne_mdformat.md | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md diff --git a/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md b/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md new file mode 100644 index 000000000..7c0d58d4f --- /dev/null +++ b/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md @@ -0,0 +1,48 @@ + + + + + + + + + From 54a71b6a25bd95d55c42e2acde729f8bae29e347 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 14:52:47 +0000 Subject: [PATCH 40/54] Changelog --- .../20241203_145037_antony.milne_mdformat.md | 6 ++ .../20241203_145221_antony.milne_mdformat.md | 55 +++++++++++++++++++ vizro-core/changelog.d/new_fragment.md.j2 | 1 + 3 files changed, 62 insertions(+) create mode 100644 vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md diff --git a/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md b/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md index 7c0d58d4f..4abc0f11e 100644 --- a/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md +++ b/vizro-core/changelog.d/20241203_145037_antony.milne_mdformat.md @@ -10,36 +10,42 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + + + + + + + + + + + + + + + + + + + + + diff --git a/vizro-core/changelog.d/new_fragment.md.j2 b/vizro-core/changelog.d/new_fragment.md.j2 index a09907bc6..70b626a87 100644 --- a/vizro-core/changelog.d/new_fragment.md.j2 +++ b/vizro-core/changelog.d/new_fragment.md.j2 @@ -11,4 +11,5 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the {{ cat }} category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> + {% endfor -%} From bc381fd98422c966927dd2ea31142713a8c355ed Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 15:00:25 +0000 Subject: [PATCH 41/54] Changelog --- .pre-commit-config.yaml | 1 + vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md | 1 - vizro-core/changelog.d/new_fragment.md.j2 | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e85739768..61db4cebf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,7 @@ repos: exclude: "devcontainer.json" # Contains comments. - id: trailing-whitespace - id: end-of-file-fixer + exclude: "new_fragment.md.j2" # Incompatible whitespace with mdformat in changelog snippet. - repo: local hooks: diff --git a/vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md b/vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md index 1d8073589..4abc0f11e 100644 --- a/vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md +++ b/vizro-core/changelog.d/20241203_145221_antony.milne_mdformat.md @@ -52,4 +52,3 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> - diff --git a/vizro-core/changelog.d/new_fragment.md.j2 b/vizro-core/changelog.d/new_fragment.md.j2 index 70b626a87..cd78816f8 100644 --- a/vizro-core/changelog.d/new_fragment.md.j2 +++ b/vizro-core/changelog.d/new_fragment.md.j2 @@ -12,4 +12,4 @@ Uncomment the section that is right (remove the HTML comment wrapper). --> -{% endfor -%} +{% endfor -%} \ No newline at end of file From fca1eeb16562d9b1b3e581063b047005bb21fac5 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 15:01:39 +0000 Subject: [PATCH 42/54] Changelog --- .../20241203_150134_antony.milne_mdformat.md | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md diff --git a/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md b/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md new file mode 100644 index 000000000..1d8073589 --- /dev/null +++ b/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + From 5c116e5e8274f1c321242fb033084f48113d87a0 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 15:06:36 +0000 Subject: [PATCH 43/54] Ignore changelogs --- .pre-commit-config.yaml | 3 +-- .../changelog.d/20241203_150134_antony.milne_mdformat.md | 1 - vizro-core/changelog.d/new_fragment.md.j2 | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 61db4cebf..d0596372c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,6 @@ repos: exclude: "devcontainer.json" # Contains comments. - id: trailing-whitespace - id: end-of-file-fixer - exclude: "new_fragment.md.j2" # Incompatible whitespace with mdformat in changelog snippet. - repo: local hooks: @@ -95,7 +94,7 @@ repos: --wrap=no, --align-semantic-breaks-in-lists, ] - exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md + exclude: ^vizro-core/docs/pages/API-reference|^vizro-ai/docs/pages/API-reference|vizro-core/docs/pages/user-guides/custom-components.md|^vizro-core/changelog.d|^vizro-ai/changelog.d additional_dependencies: - mdformat-mkdocs[recommended]==3.1.1 diff --git a/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md b/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md index 1d8073589..4abc0f11e 100644 --- a/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md +++ b/vizro-core/changelog.d/20241203_150134_antony.milne_mdformat.md @@ -52,4 +52,3 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> - diff --git a/vizro-core/changelog.d/new_fragment.md.j2 b/vizro-core/changelog.d/new_fragment.md.j2 index cd78816f8..a09907bc6 100644 --- a/vizro-core/changelog.d/new_fragment.md.j2 +++ b/vizro-core/changelog.d/new_fragment.md.j2 @@ -11,5 +11,4 @@ Uncomment the section that is right (remove the HTML comment wrapper). - A bullet item for the {{ cat }} category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX. ([#1](https://github.com/mckinsey/vizro/pull/1)) --> - -{% endfor -%} \ No newline at end of file +{% endfor -%} From cdb75211bc0faba2ef43e95c7e4f1cecf0d38198 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Tue, 3 Dec 2024 15:06:46 +0000 Subject: [PATCH 44/54] Update figure.md --- vizro-core/docs/pages/user-guides/figure.md | 137 ++++++++++---------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/vizro-core/docs/pages/user-guides/figure.md b/vizro-core/docs/pages/user-guides/figure.md index 67acf9ce4..03bfa412a 100644 --- a/vizro-core/docs/pages/user-guides/figure.md +++ b/vizro-core/docs/pages/user-guides/figure.md @@ -110,76 +110,75 @@ As described in the [API reference](../API-reference/figure-callables.md) and il !!! example "KPI card variations" === "app.py" + ```{.python pycafe-link} + import pandas as pd + import vizro.models as vm + from vizro import Vizro + # For more information, refer to the API reference for kpi_card and kpi_card_reference + from vizro.figures import kpi_card, kpi_card_reference + + df_kpi = pd.DataFrame({"Actual": [100, 200, 700], "Reference": [100, 300, 500], "Category": ["A", "B", "C"]}) + + example_cards = [ + kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with value"), + kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with aggregation", agg_func="median"), + kpi_card( + data_frame=df_kpi, + value_column="Actual", + title="KPI with formatting", + value_format="${value:.2f}", + ), + kpi_card( + data_frame=df_kpi, + value_column="Actual", + title="KPI with icon", + icon="shopping_cart", + ), + ] + + example_reference_cards = [ + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + title="KPI reference (pos)", + ), + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + agg_func="median", + title="KPI reference (neg)", + ), + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + title="KPI reference with formatting", + value_format="{value:.2f}€", + reference_format="{delta:+.2f}€ vs. last year ({reference:.2f}€)", + ), + kpi_card_reference( + data_frame=df_kpi, + value_column="Actual", + reference_column="Reference", + title="KPI reference with icon", + icon="shopping_cart", + ), + ] + + # Create a layout with four rows and columns. The KPI cards are positioned in the first eight cells, while the remaining cells are empty. + page = vm.Page( + title="KPI cards", + layout=vm.Layout(grid=[[0, 1, 2, 3], [4, 5, 6, 7], [-1, -1, -1, -1], [-1, -1, -1, -1]]), - ```{.python pycafe-link} - import pandas as pd - import vizro.models as vm - from vizro import Vizro - # For more information, refer to the API reference for kpi_card and kpi_card_reference - from vizro.figures import kpi_card, kpi_card_reference - - df_kpi = pd.DataFrame({"Actual": [100, 200, 700], "Reference": [100, 300, 500], "Category": ["A", "B", "C"]}) - - example_cards = [ - kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with value"), - kpi_card(data_frame=df_kpi, value_column="Actual", title="KPI with aggregation", agg_func="median"), - kpi_card( - data_frame=df_kpi, - value_column="Actual", - title="KPI with formatting", - value_format="${value:.2f}", - ), - kpi_card( - data_frame=df_kpi, - value_column="Actual", - title="KPI with icon", - icon="shopping_cart", - ), - ] - - example_reference_cards = [ - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - title="KPI reference (pos)", - ), - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - agg_func="median", - title="KPI reference (neg)", - ), - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - title="KPI reference with formatting", - value_format="{value:.2f}€", - reference_format="{delta:+.2f}€ vs. last year ({reference:.2f}€)", - ), - kpi_card_reference( - data_frame=df_kpi, - value_column="Actual", - reference_column="Reference", - title="KPI reference with icon", - icon="shopping_cart", - ), - ] - - # Create a layout with four rows and columns. The KPI cards are positioned in the first eight cells, while the remaining cells are empty. - page = vm.Page( - title="KPI cards", - layout=vm.Layout(grid=[[0, 1, 2, 3], [4, 5, 6, 7], [-1, -1, -1, -1], [-1, -1, -1, -1]]), - - components=[vm.Figure(figure=figure) for figure in example_cards + example_reference_cards], - controls=[vm.Filter(column="Category")], - ) - - dashboard = vm.Dashboard(pages=[page]) - Vizro().build(dashboard).run() - ``` + components=[vm.Figure(figure=figure) for figure in example_cards + example_reference_cards], + controls=[vm.Filter(column="Category")], + ) + + dashboard = vm.Dashboard(pages=[page]) + Vizro().build(dashboard).run() + ``` === "app.yaml" ```yaml From 96a714747fa808e19bf50457e9617eef2784615b Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 15:11:16 +0000 Subject: [PATCH 45/54] Align src with main --- vizro-core/src/vizro/__init__.py | 2 +- .../src/vizro/actions/_actions_utils.py | 56 +++++++++++++------ .../src/vizro/actions/_filter_action.py | 2 +- .../src/vizro/actions/_on_page_load_action.py | 2 +- .../src/vizro/actions/_parameter_action.py | 2 +- .../actions/filter_interaction_action.py | 2 +- .../models/_components/form/_form_utils.py | 3 + .../models/_components/form/checklist.py | 17 +++++- .../vizro/models/_components/form/dropdown.py | 38 +++++++++++-- .../models/_components/form/radio_items.py | 17 +++++- .../models/_components/form/range_slider.py | 41 +++++++++----- .../vizro/models/_components/form/slider.py | 35 ++++++++---- .../src/vizro/models/_controls/parameter.py | 1 + vizro-core/src/vizro/models/_dashboard.py | 31 +++++++--- vizro-core/src/vizro/static/css/layout.css | 25 +++++++++ .../vizro/static/js/models/range_slider.js | 43 +++++++++----- .../src/vizro/static/js/models/slider.js | 27 ++++++--- 17 files changed, 254 insertions(+), 90 deletions(-) diff --git a/vizro-core/src/vizro/__init__.py b/vizro-core/src/vizro/__init__.py index 6a77ff59c..cf2b583d7 100644 --- a/vizro-core/src/vizro/__init__.py +++ b/vizro-core/src/vizro/__init__.py @@ -14,7 +14,7 @@ __all__ = ["Vizro"] -__version__ = "0.1.30.dev0" +__version__ = "0.1.29.dev0" # For the below _css_dist and _js_dist to be used by Dash, they must be retrieved by dash.resources.Css.get_all_css(). diff --git a/vizro-core/src/vizro/actions/_actions_utils.py b/vizro-core/src/vizro/actions/_actions_utils.py index 984359fc9..1873b6620 100644 --- a/vizro-core/src/vizro/actions/_actions_utils.py +++ b/vizro-core/src/vizro/actions/_actions_utils.py @@ -49,18 +49,18 @@ def _get_component_actions(component) -> list[Action]: def _apply_filter_controls( - data_frame: pd.DataFrame, ctds_filters: list[CallbackTriggerDict], target: ModelID + data_frame: pd.DataFrame, ctds_filter: list[CallbackTriggerDict], target: ModelID ) -> pd.DataFrame: """Applies filters from a vm.Filter model in the controls. Args: data_frame: unfiltered DataFrame. - ctds_filters: list of CallbackTriggerDict for filters. + ctds_filter: list of CallbackTriggerDict for filters. target: id of targeted Figure. Returns: filtered DataFrame. """ - for ctd in ctds_filters: + for ctd in ctds_filter: selector_value = ctd["value"] selector_value = selector_value if isinstance(selector_value, list) else [selector_value] selector_actions = _get_component_actions(model_manager[ctd["id"]]) @@ -162,12 +162,12 @@ def _update_nested_figure_properties( def _get_parametrized_config( - ctd_parameters: list[CallbackTriggerDict], target: ModelID, data_frame: bool + ctds_parameter: list[CallbackTriggerDict], target: ModelID, data_frame: bool ) -> dict[str, Any]: """Convert parameters into a keyword-argument dictionary. Args: - ctd_parameters: list of CallbackTriggerDicts for vm.Parameter. + ctds_parameter: list of CallbackTriggerDicts for vm.Parameter. target: id of targeted figure. data_frame: whether to return only DataFrame parameters starting "data_frame." or only non-DataFrame parameters. @@ -185,7 +185,7 @@ def _get_parametrized_config( config = deepcopy(model_manager[target].figure._arguments) del config["data_frame"] - for ctd in ctd_parameters: + for ctd in ctds_parameter: # TODO: needs to be refactored so that it is independent of implementation details parameter_value = ctd["value"] @@ -221,7 +221,7 @@ def _apply_filters( # Takes in just one target, so dataframe is filtered repeatedly for every target that uses it. # Potentially this could be de-duplicated but it's not so important since filtering is a relatively fast # operation (compared to data loading). - filtered_data = _apply_filter_controls(data_frame=data, ctds_filters=ctds_filter, target=target) + filtered_data = _apply_filter_controls(data_frame=data, ctds_filter=ctds_filter, target=target) filtered_data = _apply_filter_interaction( data_frame=filtered_data, ctds_filter_interaction=ctds_filter_interaction, target=target ) @@ -229,17 +229,17 @@ def _apply_filters( def _get_unfiltered_data( - ctds_parameters: list[CallbackTriggerDict], targets: list[ModelID] + ctds_parameter: list[CallbackTriggerDict], targets: list[ModelID] ) -> dict[ModelID, pd.DataFrame]: # Takes in multiple targets to ensure that data can be loaded efficiently using _multi_load and not repeated for # every single target. - # Getting unfiltered data requires data frame parameters. We pass in all ctd_parameters and then find the + # Getting unfiltered data requires data frame parameters. We pass in all ctds_parameter and then find the # data_frame ones by passing data_frame=True in the call to _get_paramaterized_config. Static data is also # handled here and will just have empty dictionary for its kwargs. multi_data_source_name_load_kwargs: list[tuple[DataSourceName, dict[str, Any]]] = [] for target in targets: dynamic_data_load_params = _get_parametrized_config( - ctd_parameters=ctds_parameters, target=target, data_frame=True + ctds_parameter=ctds_parameter, target=target, data_frame=True ) data_source_name = model_manager[target]["data_frame"] multi_data_source_name_load_kwargs.append((data_source_name, dynamic_data_load_params["data_frame"])) @@ -250,25 +250,45 @@ def _get_unfiltered_data( def _get_modified_page_figures( ctds_filter: list[CallbackTriggerDict], ctds_filter_interaction: list[dict[str, CallbackTriggerDict]], - ctds_parameters: list[CallbackTriggerDict], + ctds_parameter: list[CallbackTriggerDict], targets: list[ModelID], ) -> dict[ModelID, Any]: + from vizro.models import Filter + outputs: dict[ModelID, Any] = {} + control_targets = [] + figure_targets = [] + for target in targets: + if isinstance(model_manager[target], Filter): + control_targets.append(target) + else: + figure_targets.append(target) + + # TODO-NEXT: Add fetching unfiltered data for the Filter.targets as well, once dynamic filters become "targetable" + # from other actions too. For example, in future, if Parameter is targeting only a single Filter. + # Currently, it only works for the on_page_load because Filter.targets are indeed the part of the actions' targets. + # More about the limitation: https://github.com/mckinsey/vizro/pull/879/files#r1863535516 + target_to_data_frame = _get_unfiltered_data(ctds_parameter=ctds_parameter, targets=figure_targets) + # TODO: the structure here would be nicer if we could get just the ctds for a single target at one time, # so you could do apply_filters on a target a pass only the ctds relevant for that target. # Consider restructuring ctds to a more convenient form to make this possible. - - for target, unfiltered_data in _get_unfiltered_data(ctds_parameters, targets).items(): + for target, unfiltered_data in target_to_data_frame.items(): filtered_data = _apply_filters(unfiltered_data, ctds_filter, ctds_filter_interaction, target) outputs[target] = model_manager[target]( data_frame=filtered_data, - **_get_parametrized_config(ctd_parameters=ctds_parameters, target=target, data_frame=False), + **_get_parametrized_config(ctds_parameter=ctds_parameter, target=target, data_frame=False), ) - # TODO NEXT: will need to pass unfiltered_data into Filter.__call__. - # This dictionary is filtered for correct targets already selected in Filter.__call__ or that could be done here - # instead. - # {target: data_frame for target, data_frame in unfiltered_data.items() if target in self.targets} + for target in control_targets: + ctd_filter = [item for item in ctds_filter if item["id"] == model_manager[target].selector.id] + + # This only covers the case of cross-page actions when Filter in an output, but is not an input of the action. + current_value = ctd_filter[0]["value"] if ctd_filter else None + + # target_to_data_frame contains all targets, including some which might not be relevant for the filter in + # question. We filter to use just the relevant targets in Filter.__call__. + outputs[target] = model_manager[target](target_to_data_frame=target_to_data_frame, current_value=current_value) return outputs diff --git a/vizro-core/src/vizro/actions/_filter_action.py b/vizro-core/src/vizro/actions/_filter_action.py index f3ec21b37..d50f0125c 100644 --- a/vizro-core/src/vizro/actions/_filter_action.py +++ b/vizro-core/src/vizro/actions/_filter_action.py @@ -32,6 +32,6 @@ def _filter( return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=targets, ) diff --git a/vizro-core/src/vizro/actions/_on_page_load_action.py b/vizro-core/src/vizro/actions/_on_page_load_action.py index 306ed9b5e..c6611fbd5 100644 --- a/vizro-core/src/vizro/actions/_on_page_load_action.py +++ b/vizro-core/src/vizro/actions/_on_page_load_action.py @@ -25,6 +25,6 @@ def _on_page_load(targets: list[ModelID], **inputs: dict[str, Any]) -> dict[Mode return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=targets, ) diff --git a/vizro-core/src/vizro/actions/_parameter_action.py b/vizro-core/src/vizro/actions/_parameter_action.py index 6284481ec..bfc58014f 100644 --- a/vizro-core/src/vizro/actions/_parameter_action.py +++ b/vizro-core/src/vizro/actions/_parameter_action.py @@ -27,6 +27,6 @@ def _parameter(targets: list[str], **inputs: dict[str, Any]) -> dict[ModelID, An return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=target_ids, ) diff --git a/vizro-core/src/vizro/actions/filter_interaction_action.py b/vizro-core/src/vizro/actions/filter_interaction_action.py index bc6659ab9..9618d265f 100644 --- a/vizro-core/src/vizro/actions/filter_interaction_action.py +++ b/vizro-core/src/vizro/actions/filter_interaction_action.py @@ -31,6 +31,6 @@ def filter_interaction(targets: Optional[list[ModelID]] = None, **inputs: dict[s return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=targets or [], ) diff --git a/vizro-core/src/vizro/models/_components/form/_form_utils.py b/vizro-core/src/vizro/models/_components/form/_form_utils.py index 18e666882..14a20a169 100644 --- a/vizro-core/src/vizro/models/_components/form/_form_utils.py +++ b/vizro-core/src/vizro/models/_components/form/_form_utils.py @@ -54,6 +54,9 @@ def validate_value(cls, value, values): [entry["value"] for entry in values["options"]] if isinstance(values["options"][0], dict) else values["options"] ) + if hasattr(value, "__iter__") and ALL_OPTION in value: + return value + if value and not is_value_contained(value, possible_values): raise ValueError("Please provide a valid value from `options`.") diff --git a/vizro-core/src/vizro/models/_components/form/checklist.py b/vizro-core/src/vizro/models/_components/form/checklist.py index 68cb26ad1..ed746dec3 100644 --- a/vizro-core/src/vizro/models/_components/form/checklist.py +++ b/vizro-core/src/vizro/models/_components/form/checklist.py @@ -38,6 +38,8 @@ class Checklist(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -46,9 +48,8 @@ class Checklist(VizroBaseModel): _validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict) _validate_value = validator("value", allow_reuse=True, always=True)(validate_value) - @_log_call - def build(self): - full_options, default_value = get_options_and_default(options=self.options, multi=True) + def __call__(self, options): + full_options, default_value = get_options_and_default(options=options, multi=True) return html.Fieldset( children=[ @@ -62,3 +63,13 @@ def build(self): ), ] ) + + def _build_dynamic_placeholder(self): + if self.value is None: + self.value = [get_options_and_default(self.options, multi=True)[1]] + + return self.__call__(self.options) + + @_log_call + def build(self): + return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/dropdown.py b/vizro-core/src/vizro/models/_components/form/dropdown.py index d0fa24444..a56c13c47 100755 --- a/vizro-core/src/vizro/models/_components/form/dropdown.py +++ b/vizro-core/src/vizro/models/_components/form/dropdown.py @@ -10,6 +10,7 @@ from pydantic import Field, PrivateAttr, StrictBool, root_validator, validator import dash_bootstrap_components as dbc +import dash_mantine_components as dmc from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory @@ -65,6 +66,10 @@ class Dropdown(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] + # Consider making the _dynamic public later. The same property could also be used for all other components. + # For example: vm.Graph could have a dynamic that is by default set on True. + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -82,9 +87,8 @@ def validate_multi(cls, multi, values): raise ValueError("Please set multi=True if providing a list of default values.") return multi - @_log_call - def build(self): - full_options, default_value = get_options_and_default(options=self.options, multi=self.multi) + def __call__(self, options): + full_options, default_value = get_options_and_default(options=options, multi=self.multi) option_height = _calculate_option_height(full_options) return html.Div( @@ -95,9 +99,35 @@ def build(self): options=full_options, value=self.value if self.value is not None else default_value, multi=self.multi, - persistence=True, optionHeight=option_height, + persistence=True, + persistence_type="session", + ), + ] + ) + + def _build_dynamic_placeholder(self): + # Setting self.value is kind of Dropdown pre_build method. It sets self.value only the first time if it's None. + # We cannot create pre_build for the Dropdown because it has to be called after vm.Filter.pre_build, but nothing + # guarantees that. We can call Filter.selector.pre_build() from the Filter.pre_build() method if we decide that. + # TODO: move this to pre_build once we have better control of the ordering. + if self.value is None: + _, default_value = get_options_and_default(self.options, self.multi) + self.value = default_value + + # TODO-NEXT: Replace this with the "universal Vizro placeholder" component. + return html.Div( + children=[ + html.Legend(children=self.title, className="form-label") if self.title else None, + dmc.DateRangePicker( + id=self.id, + value=self.value, + persistence=True, persistence_type="session", ), ] ) + + @_log_call + def build(self): + return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/radio_items.py b/vizro-core/src/vizro/models/_components/form/radio_items.py index dfa282126..48b8bc6bc 100644 --- a/vizro-core/src/vizro/models/_components/form/radio_items.py +++ b/vizro-core/src/vizro/models/_components/form/radio_items.py @@ -39,6 +39,8 @@ class RadioItems(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -47,9 +49,8 @@ class RadioItems(VizroBaseModel): _validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict) _validate_value = validator("value", allow_reuse=True, always=True)(validate_value) - @_log_call - def build(self): - full_options, default_value = get_options_and_default(options=self.options, multi=False) + def __call__(self, options): + full_options, default_value = get_options_and_default(options=options, multi=False) return html.Fieldset( children=[ @@ -63,3 +64,13 @@ def build(self): ), ] ) + + def _build_dynamic_placeholder(self): + if self.value is None: + self.value = get_options_and_default(self.options, multi=False)[1] + + return self.__call__(self.options) + + @_log_call + def build(self): + return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/range_slider.py b/vizro-core/src/vizro/models/_components/form/range_slider.py index 16f0cb8c9..a96521708 100644 --- a/vizro-core/src/vizro/models/_components/form/range_slider.py +++ b/vizro-core/src/vizro/models/_components/form/range_slider.py @@ -50,6 +50,8 @@ class RangeSlider(VizroBaseModel): title: str = Field("", description="Title to be displayed.") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -60,10 +62,7 @@ class RangeSlider(VizroBaseModel): _set_default_marks = validator("marks", allow_reuse=True, always=True)(set_default_marks) _set_actions = _action_validator_factory("value") - @_log_call - def build(self): - init_value = self.value or [self.min, self.max] # type: ignore[list-item] - + def __call__(self, min, max, current_value): output = [ Output(f"{self.id}_start_value", "value"), Output(f"{self.id}_end_value", "value"), @@ -86,7 +85,7 @@ def build(self): return html.Div( children=[ - dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": self.min, "max": self.max}), + dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": min, "max": max}), html.Div( children=[ dbc.Label(children=self.title, html_for=self.id) if self.title else None, @@ -96,10 +95,10 @@ def build(self): id=f"{self.id}_start_value", type="number", placeholder="min", - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, - value=init_value[0], + value=current_value[0], persistence=True, persistence_type="session", className="slider-text-input-field", @@ -109,15 +108,15 @@ def build(self): id=f"{self.id}_end_value", type="number", placeholder="max", - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, - value=init_value[1], + value=current_value[1], persistence=True, persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id=f"{self.id}_input_store", storage_type="session", data=init_value), + dcc.Store(id=f"{self.id}_input_store", storage_type="session"), ], className="slider-text-input-container", ), @@ -126,14 +125,26 @@ def build(self): ), dcc.RangeSlider( id=self.id, - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, marks=self.marks, - value=init_value, + value=current_value, persistence=True, persistence_type="session", className="slider-track-without-marks" if self.marks is None else "slider-track-with-marks", ), ] ) + + def _build_dynamic_placeholder(self, current_value): + return self.__call__(self.min, self.max, current_value) + + @_log_call + def build(self): + current_value = self.value or [self.min, self.max] # type: ignore[list-item] + return ( + self._build_dynamic_placeholder(current_value) + if self._dynamic + else self.__call__(self.min, self.max, current_value) + ) diff --git a/vizro-core/src/vizro/models/_components/form/slider.py b/vizro-core/src/vizro/models/_components/form/slider.py index 65b37fe9a..2ffdb9f6a 100644 --- a/vizro-core/src/vizro/models/_components/form/slider.py +++ b/vizro-core/src/vizro/models/_components/form/slider.py @@ -48,6 +48,8 @@ class Slider(VizroBaseModel): title: str = Field("", description="Title to be displayed.") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -58,10 +60,7 @@ class Slider(VizroBaseModel): _set_default_marks = validator("marks", allow_reuse=True, always=True)(set_default_marks) _set_actions = _action_validator_factory("value") - @_log_call - def build(self): - init_value = self.value or self.min - + def __call__(self, min, max, current_value): output = [ Output(f"{self.id}_end_value", "value"), Output(self.id, "value"), @@ -82,7 +81,7 @@ def build(self): return html.Div( children=[ - dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": self.min, "max": self.max}), + dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": min, "max": max}), html.Div( children=[ dbc.Label(children=self.title, html_for=self.id) if self.title else None, @@ -92,15 +91,15 @@ def build(self): id=f"{self.id}_end_value", type="number", placeholder="max", - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, - value=init_value, + value=current_value, persistence=True, persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id=f"{self.id}_input_store", storage_type="session", data=init_value), + dcc.Store(id=f"{self.id}_input_store", storage_type="session"), ], className="slider-text-input-container", ), @@ -109,11 +108,11 @@ def build(self): ), dcc.Slider( id=self.id, - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, marks=self.marks, - value=init_value, + value=current_value, included=False, persistence=True, persistence_type="session", @@ -121,3 +120,15 @@ def build(self): ), ] ) + + def _build_dynamic_placeholder(self, current_value): + return self.__call__(self.min, self.max, current_value) + + @_log_call + def build(self): + current_value = self.value if self.value is not None else self.min + return ( + self._build_dynamic_placeholder(current_value) + if self._dynamic + else self.__call__(self.min, self.max, current_value) + ) diff --git a/vizro-core/src/vizro/models/_controls/parameter.py b/vizro-core/src/vizro/models/_controls/parameter.py index c77c7c7bf..cdc76936c 100644 --- a/vizro-core/src/vizro/models/_controls/parameter.py +++ b/vizro-core/src/vizro/models/_controls/parameter.py @@ -56,6 +56,7 @@ def check_data_frame_as_target_argument(cls, target): f"Invalid target {target}. 'data_frame' target must be supplied in the form " ".data_frame." ) + # TODO: Add validation: Make sure the target data_frame is _DynamicData. return target @validator("targets") diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index b635b8e95..2fd7c7b00 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -308,18 +308,31 @@ def _make_page_404_layout(self): return html.Div( [ # Theme switch is added such that the 404 page has the same theme as the user-selected one. - dbc.Switch( - id="theme-selector", - value=self.theme == "vizro_light", - persistence=True, - persistence_type="session", + html.Div( + children=dbc.Switch( + id="theme-selector", + value=self.theme == "vizro_light", + persistence=True, + persistence_type="session", + ), + id="settings", ), html.Img(src=f"data:image/svg+xml;base64,{error_404_svg}"), - html.H3("This page could not be found."), - html.P("Make sure the URL you entered is correct."), - dbc.Button(children="Take me home", href=get_relative_path("/"), className="mt-4"), + html.Div( + [ + html.Div( + children=[ + html.H3("This page could not be found.", className="heading-3-600"), + html.P("Make sure the URL you entered is correct."), + ], + className="error-text-container", + ), + dbc.Button(children="Take me home", href=get_relative_path("/")), + ], + className="error-content-container", + ), ], - className="d-flex flex-column align-items-center justify-content-center min-vh-100", + className="page-error-container", ) @staticmethod diff --git a/vizro-core/src/vizro/static/css/layout.css b/vizro-core/src/vizro/static/css/layout.css index a7c66f864..996c1108c 100644 --- a/vizro-core/src/vizro/static/css/layout.css +++ b/vizro-core/src/vizro/static/css/layout.css @@ -85,6 +85,31 @@ border-bottom: 1px solid var(--border-subtleAlpha01); } +.page-error-container { + align-items: center; + display: flex; + flex-direction: column; + height: 100vh; + justify-content: center; + width: 100vw; +} + +.error-content-container { + align-items: center; + display: inline-flex; + flex-direction: column; + gap: 24px; + margin-top: -32px; +} + +.error-text-container { + display: flex; + flex-direction: column; + gap: 8px; + text-align: center; + width: 336px; +} + .dashboard_title { display: flex; flex-direction: column; diff --git a/vizro-core/src/vizro/static/js/models/range_slider.js b/vizro-core/src/vizro/static/js/models/range_slider.js index 5eb1892aa..8aafdde7f 100644 --- a/vizro-core/src/vizro/static/js/models/range_slider.js +++ b/vizro-core/src/vizro/static/js/models/range_slider.js @@ -17,6 +17,8 @@ function update_range_slider_values( trigger_id = dash_clientside.callback_context.triggered[0]["prop_id"].split(".")[0]; } + + // text form component is the trigger if ( trigger_id === `${self_data["id"]}_start_value` || trigger_id === `${self_data["id"]}_end_value` @@ -24,21 +26,36 @@ function update_range_slider_values( if (isNaN(start) || isNaN(end)) { return dash_clientside.no_update; } - [start_text_value, end_text_value] = [start, end]; + return [start, end, [start, end], [start, end]]; + + // slider component is the trigger } else if (trigger_id === self_data["id"]) { - [start_text_value, end_text_value] = [slider[0], slider[1]]; - } else { - [start_text_value, end_text_value] = - input_store !== null ? input_store : [slider[0], slider[1]]; + return [slider[0], slider[1], slider, slider]; } - - start_value = Math.min(start_text_value, end_text_value); - end_value = Math.max(start_text_value, end_text_value); - start_value = Math.max(self_data["min"], start_value); - end_value = Math.min(self_data["max"], end_value); - slider_value = [start_value, end_value]; - - return [start_value, end_value, slider_value, [start_value, end_value]]; + // on_page_load is the trigger + if (input_store === null) { + return [ + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + slider, + ]; + } + if ( + slider[0] === start && + input_store[0] === start && + slider[1] === end && + input_store[1] === end + ) { + // To prevent filter_action to be triggered after on_page_load + return [ + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + ]; + } + return [input_store[0], input_store[1], input_store, input_store]; } window.dash_clientside = { diff --git a/vizro-core/src/vizro/static/js/models/slider.js b/vizro-core/src/vizro/static/js/models/slider.js index bc572cffe..1b15d78ae 100644 --- a/vizro-core/src/vizro/static/js/models/slider.js +++ b/vizro-core/src/vizro/static/js/models/slider.js @@ -6,20 +6,31 @@ function update_slider_values(start, slider, input_store, self_data) { trigger_id = dash_clientside.callback_context.triggered[0]["prop_id"].split(".")[0]; } + + // text form component is the trigger if (trigger_id === `${self_data["id"]}_end_value`) { if (isNaN(start)) { return dash_clientside.no_update; } - end_value = start; + return [start, start, start]; + + // slider component is the trigger } else if (trigger_id === self_data["id"]) { - end_value = slider; - } else { - end_value = input_store !== null ? input_store : self_data["min"]; + return [slider, slider, slider]; } - - end_value = Math.min(Math.max(self_data["min"], end_value), self_data["max"]); - - return [end_value, end_value, end_value]; + // on_page_load is the trigger + if (input_store === null) { + return [dash_clientside.no_update, dash_clientside.no_update, slider]; + } + if (slider === start && start === input_store) { + // To prevent filter_action to be triggered after on_page_load + return [ + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + ]; + } + return [input_store, input_store, input_store]; } window.dash_clientside = { From add8a5a6c73819b20a6c525c2e0970663050b321 Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Tue, 3 Dec 2024 15:14:48 +0000 Subject: [PATCH 46/54] Fix some more code glitches --- .../docs/pages/user-guides/card-button.md | 162 +++++++++--------- .../docs/pages/user-guides/custom-css.md | 80 ++++----- 2 files changed, 117 insertions(+), 125 deletions(-) diff --git a/vizro-core/docs/pages/user-guides/card-button.md b/vizro-core/docs/pages/user-guides/card-button.md index 0158d72d8..3c5ad2d7d 100755 --- a/vizro-core/docs/pages/user-guides/card-button.md +++ b/vizro-core/docs/pages/user-guides/card-button.md @@ -260,13 +260,12 @@ Note the added URL hash `#my-image`. Now create a CSS file placed in your `asset !!! example "Card with styled image" === "images.css" - - ```css - img[src*="#my-image"] { - width: 120px; - height: 120px; - } - ``` + ```css + img[src*="#my-image"] { + width: 120px; + height: 120px; + } + ``` === "app.py" ```py @@ -331,13 +330,12 @@ Use the following pre-defined URL hashes in your image path to apply Vizro's def !!! example "Card with floating image" === "images.css" - - ```css - img[src*="#my-image"] { - width: 120px; - height: 120px; - } - ``` + ```css + img[src*="#my-image"] { + width: 120px; + height: 120px; + } + ``` === "app.py" ```py @@ -626,81 +624,79 @@ The example below demonstrates how to configure a button to export the filtered !!! example "Button with action" === "app.py" + ```{.python pycafe-link} + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.actions import export_data - ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.actions import export_data - - df = px.data.iris() - - page = vm.Page( - title="My first page", - layout=vm.Layout(grid=[[0], [0], [0], [0], [1]]), - components=[ - vm.Graph( - id="scatter_chart", - figure=px.scatter( - df, - x="sepal_width", - y="sepal_length", - color="species", - size="petal_length", + df = px.data.iris() + + page = vm.Page( + title="My first page", + layout=vm.Layout(grid=[[0], [0], [0], [0], [1]]), + components=[ + vm.Graph( + id="scatter_chart", + figure=px.scatter( + df, + x="sepal_width", + y="sepal_length", + color="species", + size="petal_length", + ), ), - ), - vm.Button( - text="Export data", - actions=[vm.Action(function=export_data(targets=["scatter_chart"]))], - ), - ], - controls=[vm.Filter(column="species")], - ) + vm.Button( + text="Export data", + actions=[vm.Action(function=export_data(targets=["scatter_chart"]))], + ), + ], + controls=[vm.Filter(column="species")], + ) - dashboard = vm.Dashboard(pages=[page]) + dashboard = vm.Dashboard(pages=[page]) - Vizro().build(dashboard).run() - ``` + Vizro().build(dashboard).run() + ``` === "app.yaml" - - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See from_yaml example - pages: - - components: - - figure: - _target_: scatter - x: sepal_width - y: sepal_length - color: species - size: petal_length - data_frame: iris - id: scatter_chart - type: graph - - type: button - text: Export data - id: export_data - actions: - - function: - _target_: export_data - targets: - - scatter_chart - controls: - - column: species - selector: - title: Species - type: dropdown - type: filter - layout: - grid: - - [0] - - [0] - - [0] - - [0] - - [1] - title: My first page - ``` + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See from_yaml example + pages: + - components: + - figure: + _target_: scatter + x: sepal_width + y: sepal_length + color: species + size: petal_length + data_frame: iris + id: scatter_chart + type: graph + - type: button + text: Export data + id: export_data + actions: + - function: + _target_: export_data + targets: + - scatter_chart + controls: + - column: species + selector: + title: Species + type: dropdown + type: filter + layout: + grid: + - [0] + - [0] + - [0] + - [0] + - [1] + title: My first page + ``` === "Result" [![Button]][button] diff --git a/vizro-core/docs/pages/user-guides/custom-css.md b/vizro-core/docs/pages/user-guides/custom-css.md index 1548417e8..d5bc5f7dc 100755 --- a/vizro-core/docs/pages/user-guides/custom-css.md +++ b/vizro-core/docs/pages/user-guides/custom-css.md @@ -84,13 +84,12 @@ To overwrite any global CSS property, you need to target the element selector an !!! example "Overwrite CSS globally" === "my_css_file.css" - - ```css - h1, - h2 { - color: hotpink; - } - ``` + ```css + h1, + h2 { + color: hotpink; + } + ``` === "app.py" ```py @@ -153,12 +152,11 @@ Suppose you want to hide the page title on one page only. Here's how you can ach !!! example "Hide page title on selected pages" === "my_css_file.css" - - ```css - #page-with-hidden-title #right-header { - display: none; - } - ``` + ```css + #page-with-hidden-title #right-header { + display: none; + } + ``` === "app.py" ```py @@ -237,18 +235,17 @@ It's essential to understand the relationship between the targeted CSS class or !!! example "Customizing CSS properties in selective components" === "my_css_file.css" - - ```css - /* Apply styling to parent */ - .card:has(#custom-card) { - background-color: white; - } - - /* Apply styling to child */ - #custom-card p { - color: black; - } - ``` + ```css + /* Apply styling to parent */ + .card:has(#custom-card) { + background-color: white; + } + + /* Apply styling to child */ + #custom-card p { + color: black; + } + ``` === "app.py" ```py @@ -362,23 +359,22 @@ To do this, you need to change the container's CSS class. Using the DevTool, as !!! example "Style a container" === "custom.css" - - ```css - /* Assign a variable to the dark and light theme */ - [data-bs-theme="dark"] { - --container-bg-color: #232632; - } - - [data-bs-theme="light"] { - --container-bg-color: #F5F6F6; - } - - /* Use the custom variable var(--container-bg-color) */ - .page-component-container { - background: var(--container-bg-color); - padding: 12px; - } - ``` + ```css + /* Assign a variable to the dark and light theme */ + [data-bs-theme="dark"] { + --container-bg-color: #232632; + } + + [data-bs-theme="light"] { + --container-bg-color: #F5F6F6; + } + + /* Use the custom variable var(--container-bg-color) */ + .page-component-container { + background: var(--container-bg-color); + padding: 12px; + } + ``` === "app.py" ```py From ca93624ce8f43f256a16c736223788ffaa8642cb Mon Sep 17 00:00:00 2001 From: Jo Stichbury Date: Tue, 3 Dec 2024 15:20:04 +0000 Subject: [PATCH 47/54] Update actions.md --- vizro-core/docs/pages/user-guides/actions.md | 116 +++++++++---------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/vizro-core/docs/pages/user-guides/actions.md b/vizro-core/docs/pages/user-guides/actions.md index 84c69067e..6a41ee25d 100644 --- a/vizro-core/docs/pages/user-guides/actions.md +++ b/vizro-core/docs/pages/user-guides/actions.md @@ -24,68 +24,66 @@ To enable downloading data, you can add the [`export_data`][vizro.actions.export !!! example "`export_data`" === "app.py" + ```{.python pycafe-link} + import vizro.models as vm + import vizro.plotly.express as px + from vizro import Vizro + from vizro.actions import export_data - ```{.python pycafe-link} - import vizro.models as vm - import vizro.plotly.express as px - from vizro import Vizro - from vizro.actions import export_data - - iris = px.data.iris() - - page = vm.Page( - title="Using actions", - components=[ - vm.Graph( - figure=px.scatter(iris, x="petal_length", y="sepal_length", color="sepal_width"), - ), - vm.Graph( - figure=px.histogram(iris, x="petal_length", color="species"), - ), - vm.Button( - text="Export data", - actions=[ - vm.Action( - function=export_data() - ), - ], - ), - ], - ) - - dashboard = vm.Dashboard(pages=[page]) - - Vizro().build(dashboard).run() - ``` + iris = px.data.iris() - === "app.yaml" + page = vm.Page( + title="Using actions", + components=[ + vm.Graph( + figure=px.scatter(iris, x="petal_length", y="sepal_length", color="sepal_width"), + ), + vm.Graph( + figure=px.histogram(iris, x="petal_length", color="species"), + ), + vm.Button( + text="Export data", + actions=[ + vm.Action( + function=export_data() + ), + ], + ), + ], + ) - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See yaml_version example - pages: - - components: - - type: graph - figure: - _target_: scatter - data_frame: iris - color: sepal_width - x: petal_length - y: sepal_length - - type: graph - figure: - _target_: histogram - data_frame: iris - color: species - x: petal_length - - type: button - text: Export data - id: export_data_button - actions: - - function: - _target_: export_data - title: Exporting - ``` + dashboard = vm.Dashboard(pages=[page]) + + Vizro().build(dashboard).run() + ``` + + === "app.yaml" + ```yaml + # Still requires a .py to add data to the data manager and parse YAML configuration + # See yaml_version example + pages: + - components: + - type: graph + figure: + _target_: scatter + data_frame: iris + color: sepal_width + x: petal_length + y: sepal_length + - type: graph + figure: + _target_: histogram + data_frame: iris + color: species + x: petal_length + - type: button + text: Export data + id: export_data_button + actions: + - function: + _target_: export_data + title: Exporting + ``` === "Result" [![Graph]][graph] From dd50d91cea5780861889f27f5a0aaae9f672b382 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 15:13:07 +0000 Subject: [PATCH 48/54] Revert "Align src with main" This reverts commit 96a714747fa808e19bf50457e9617eef2784615b. --- vizro-core/src/vizro/__init__.py | 2 +- .../src/vizro/actions/_actions_utils.py | 56 ++++++------------- .../src/vizro/actions/_filter_action.py | 2 +- .../src/vizro/actions/_on_page_load_action.py | 2 +- .../src/vizro/actions/_parameter_action.py | 2 +- .../actions/filter_interaction_action.py | 2 +- .../models/_components/form/_form_utils.py | 3 - .../models/_components/form/checklist.py | 17 +----- .../vizro/models/_components/form/dropdown.py | 38 ++----------- .../models/_components/form/radio_items.py | 17 +----- .../models/_components/form/range_slider.py | 41 +++++--------- .../vizro/models/_components/form/slider.py | 35 ++++-------- .../src/vizro/models/_controls/parameter.py | 1 - vizro-core/src/vizro/models/_dashboard.py | 31 +++------- vizro-core/src/vizro/static/css/layout.css | 25 --------- .../vizro/static/js/models/range_slider.js | 43 +++++--------- .../src/vizro/static/js/models/slider.js | 27 +++------ 17 files changed, 90 insertions(+), 254 deletions(-) diff --git a/vizro-core/src/vizro/__init__.py b/vizro-core/src/vizro/__init__.py index cf2b583d7..6a77ff59c 100644 --- a/vizro-core/src/vizro/__init__.py +++ b/vizro-core/src/vizro/__init__.py @@ -14,7 +14,7 @@ __all__ = ["Vizro"] -__version__ = "0.1.29.dev0" +__version__ = "0.1.30.dev0" # For the below _css_dist and _js_dist to be used by Dash, they must be retrieved by dash.resources.Css.get_all_css(). diff --git a/vizro-core/src/vizro/actions/_actions_utils.py b/vizro-core/src/vizro/actions/_actions_utils.py index 1873b6620..984359fc9 100644 --- a/vizro-core/src/vizro/actions/_actions_utils.py +++ b/vizro-core/src/vizro/actions/_actions_utils.py @@ -49,18 +49,18 @@ def _get_component_actions(component) -> list[Action]: def _apply_filter_controls( - data_frame: pd.DataFrame, ctds_filter: list[CallbackTriggerDict], target: ModelID + data_frame: pd.DataFrame, ctds_filters: list[CallbackTriggerDict], target: ModelID ) -> pd.DataFrame: """Applies filters from a vm.Filter model in the controls. Args: data_frame: unfiltered DataFrame. - ctds_filter: list of CallbackTriggerDict for filters. + ctds_filters: list of CallbackTriggerDict for filters. target: id of targeted Figure. Returns: filtered DataFrame. """ - for ctd in ctds_filter: + for ctd in ctds_filters: selector_value = ctd["value"] selector_value = selector_value if isinstance(selector_value, list) else [selector_value] selector_actions = _get_component_actions(model_manager[ctd["id"]]) @@ -162,12 +162,12 @@ def _update_nested_figure_properties( def _get_parametrized_config( - ctds_parameter: list[CallbackTriggerDict], target: ModelID, data_frame: bool + ctd_parameters: list[CallbackTriggerDict], target: ModelID, data_frame: bool ) -> dict[str, Any]: """Convert parameters into a keyword-argument dictionary. Args: - ctds_parameter: list of CallbackTriggerDicts for vm.Parameter. + ctd_parameters: list of CallbackTriggerDicts for vm.Parameter. target: id of targeted figure. data_frame: whether to return only DataFrame parameters starting "data_frame." or only non-DataFrame parameters. @@ -185,7 +185,7 @@ def _get_parametrized_config( config = deepcopy(model_manager[target].figure._arguments) del config["data_frame"] - for ctd in ctds_parameter: + for ctd in ctd_parameters: # TODO: needs to be refactored so that it is independent of implementation details parameter_value = ctd["value"] @@ -221,7 +221,7 @@ def _apply_filters( # Takes in just one target, so dataframe is filtered repeatedly for every target that uses it. # Potentially this could be de-duplicated but it's not so important since filtering is a relatively fast # operation (compared to data loading). - filtered_data = _apply_filter_controls(data_frame=data, ctds_filter=ctds_filter, target=target) + filtered_data = _apply_filter_controls(data_frame=data, ctds_filters=ctds_filter, target=target) filtered_data = _apply_filter_interaction( data_frame=filtered_data, ctds_filter_interaction=ctds_filter_interaction, target=target ) @@ -229,17 +229,17 @@ def _apply_filters( def _get_unfiltered_data( - ctds_parameter: list[CallbackTriggerDict], targets: list[ModelID] + ctds_parameters: list[CallbackTriggerDict], targets: list[ModelID] ) -> dict[ModelID, pd.DataFrame]: # Takes in multiple targets to ensure that data can be loaded efficiently using _multi_load and not repeated for # every single target. - # Getting unfiltered data requires data frame parameters. We pass in all ctds_parameter and then find the + # Getting unfiltered data requires data frame parameters. We pass in all ctd_parameters and then find the # data_frame ones by passing data_frame=True in the call to _get_paramaterized_config. Static data is also # handled here and will just have empty dictionary for its kwargs. multi_data_source_name_load_kwargs: list[tuple[DataSourceName, dict[str, Any]]] = [] for target in targets: dynamic_data_load_params = _get_parametrized_config( - ctds_parameter=ctds_parameter, target=target, data_frame=True + ctd_parameters=ctds_parameters, target=target, data_frame=True ) data_source_name = model_manager[target]["data_frame"] multi_data_source_name_load_kwargs.append((data_source_name, dynamic_data_load_params["data_frame"])) @@ -250,45 +250,25 @@ def _get_unfiltered_data( def _get_modified_page_figures( ctds_filter: list[CallbackTriggerDict], ctds_filter_interaction: list[dict[str, CallbackTriggerDict]], - ctds_parameter: list[CallbackTriggerDict], + ctds_parameters: list[CallbackTriggerDict], targets: list[ModelID], ) -> dict[ModelID, Any]: - from vizro.models import Filter - outputs: dict[ModelID, Any] = {} - control_targets = [] - figure_targets = [] - for target in targets: - if isinstance(model_manager[target], Filter): - control_targets.append(target) - else: - figure_targets.append(target) - - # TODO-NEXT: Add fetching unfiltered data for the Filter.targets as well, once dynamic filters become "targetable" - # from other actions too. For example, in future, if Parameter is targeting only a single Filter. - # Currently, it only works for the on_page_load because Filter.targets are indeed the part of the actions' targets. - # More about the limitation: https://github.com/mckinsey/vizro/pull/879/files#r1863535516 - target_to_data_frame = _get_unfiltered_data(ctds_parameter=ctds_parameter, targets=figure_targets) - # TODO: the structure here would be nicer if we could get just the ctds for a single target at one time, # so you could do apply_filters on a target a pass only the ctds relevant for that target. # Consider restructuring ctds to a more convenient form to make this possible. - for target, unfiltered_data in target_to_data_frame.items(): + + for target, unfiltered_data in _get_unfiltered_data(ctds_parameters, targets).items(): filtered_data = _apply_filters(unfiltered_data, ctds_filter, ctds_filter_interaction, target) outputs[target] = model_manager[target]( data_frame=filtered_data, - **_get_parametrized_config(ctds_parameter=ctds_parameter, target=target, data_frame=False), + **_get_parametrized_config(ctd_parameters=ctds_parameters, target=target, data_frame=False), ) - for target in control_targets: - ctd_filter = [item for item in ctds_filter if item["id"] == model_manager[target].selector.id] - - # This only covers the case of cross-page actions when Filter in an output, but is not an input of the action. - current_value = ctd_filter[0]["value"] if ctd_filter else None - - # target_to_data_frame contains all targets, including some which might not be relevant for the filter in - # question. We filter to use just the relevant targets in Filter.__call__. - outputs[target] = model_manager[target](target_to_data_frame=target_to_data_frame, current_value=current_value) + # TODO NEXT: will need to pass unfiltered_data into Filter.__call__. + # This dictionary is filtered for correct targets already selected in Filter.__call__ or that could be done here + # instead. + # {target: data_frame for target, data_frame in unfiltered_data.items() if target in self.targets} return outputs diff --git a/vizro-core/src/vizro/actions/_filter_action.py b/vizro-core/src/vizro/actions/_filter_action.py index d50f0125c..f3ec21b37 100644 --- a/vizro-core/src/vizro/actions/_filter_action.py +++ b/vizro-core/src/vizro/actions/_filter_action.py @@ -32,6 +32,6 @@ def _filter( return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameter=ctx.args_grouping["external"]["parameters"], + ctds_parameters=ctx.args_grouping["external"]["parameters"], targets=targets, ) diff --git a/vizro-core/src/vizro/actions/_on_page_load_action.py b/vizro-core/src/vizro/actions/_on_page_load_action.py index c6611fbd5..306ed9b5e 100644 --- a/vizro-core/src/vizro/actions/_on_page_load_action.py +++ b/vizro-core/src/vizro/actions/_on_page_load_action.py @@ -25,6 +25,6 @@ def _on_page_load(targets: list[ModelID], **inputs: dict[str, Any]) -> dict[Mode return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameter=ctx.args_grouping["external"]["parameters"], + ctds_parameters=ctx.args_grouping["external"]["parameters"], targets=targets, ) diff --git a/vizro-core/src/vizro/actions/_parameter_action.py b/vizro-core/src/vizro/actions/_parameter_action.py index bfc58014f..6284481ec 100644 --- a/vizro-core/src/vizro/actions/_parameter_action.py +++ b/vizro-core/src/vizro/actions/_parameter_action.py @@ -27,6 +27,6 @@ def _parameter(targets: list[str], **inputs: dict[str, Any]) -> dict[ModelID, An return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameter=ctx.args_grouping["external"]["parameters"], + ctds_parameters=ctx.args_grouping["external"]["parameters"], targets=target_ids, ) diff --git a/vizro-core/src/vizro/actions/filter_interaction_action.py b/vizro-core/src/vizro/actions/filter_interaction_action.py index 9618d265f..bc6659ab9 100644 --- a/vizro-core/src/vizro/actions/filter_interaction_action.py +++ b/vizro-core/src/vizro/actions/filter_interaction_action.py @@ -31,6 +31,6 @@ def filter_interaction(targets: Optional[list[ModelID]] = None, **inputs: dict[s return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameter=ctx.args_grouping["external"]["parameters"], + ctds_parameters=ctx.args_grouping["external"]["parameters"], targets=targets or [], ) diff --git a/vizro-core/src/vizro/models/_components/form/_form_utils.py b/vizro-core/src/vizro/models/_components/form/_form_utils.py index 14a20a169..18e666882 100644 --- a/vizro-core/src/vizro/models/_components/form/_form_utils.py +++ b/vizro-core/src/vizro/models/_components/form/_form_utils.py @@ -54,9 +54,6 @@ def validate_value(cls, value, values): [entry["value"] for entry in values["options"]] if isinstance(values["options"][0], dict) else values["options"] ) - if hasattr(value, "__iter__") and ALL_OPTION in value: - return value - if value and not is_value_contained(value, possible_values): raise ValueError("Please provide a valid value from `options`.") diff --git a/vizro-core/src/vizro/models/_components/form/checklist.py b/vizro-core/src/vizro/models/_components/form/checklist.py index ed746dec3..68cb26ad1 100644 --- a/vizro-core/src/vizro/models/_components/form/checklist.py +++ b/vizro-core/src/vizro/models/_components/form/checklist.py @@ -38,8 +38,6 @@ class Checklist(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] - _dynamic: bool = PrivateAttr(False) - # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -48,8 +46,9 @@ class Checklist(VizroBaseModel): _validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict) _validate_value = validator("value", allow_reuse=True, always=True)(validate_value) - def __call__(self, options): - full_options, default_value = get_options_and_default(options=options, multi=True) + @_log_call + def build(self): + full_options, default_value = get_options_and_default(options=self.options, multi=True) return html.Fieldset( children=[ @@ -63,13 +62,3 @@ def __call__(self, options): ), ] ) - - def _build_dynamic_placeholder(self): - if self.value is None: - self.value = [get_options_and_default(self.options, multi=True)[1]] - - return self.__call__(self.options) - - @_log_call - def build(self): - return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/dropdown.py b/vizro-core/src/vizro/models/_components/form/dropdown.py index a56c13c47..d0fa24444 100755 --- a/vizro-core/src/vizro/models/_components/form/dropdown.py +++ b/vizro-core/src/vizro/models/_components/form/dropdown.py @@ -10,7 +10,6 @@ from pydantic import Field, PrivateAttr, StrictBool, root_validator, validator import dash_bootstrap_components as dbc -import dash_mantine_components as dmc from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory @@ -66,10 +65,6 @@ class Dropdown(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] - # Consider making the _dynamic public later. The same property could also be used for all other components. - # For example: vm.Graph could have a dynamic that is by default set on True. - _dynamic: bool = PrivateAttr(False) - # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -87,8 +82,9 @@ def validate_multi(cls, multi, values): raise ValueError("Please set multi=True if providing a list of default values.") return multi - def __call__(self, options): - full_options, default_value = get_options_and_default(options=options, multi=self.multi) + @_log_call + def build(self): + full_options, default_value = get_options_and_default(options=self.options, multi=self.multi) option_height = _calculate_option_height(full_options) return html.Div( @@ -99,35 +95,9 @@ def __call__(self, options): options=full_options, value=self.value if self.value is not None else default_value, multi=self.multi, - optionHeight=option_height, - persistence=True, - persistence_type="session", - ), - ] - ) - - def _build_dynamic_placeholder(self): - # Setting self.value is kind of Dropdown pre_build method. It sets self.value only the first time if it's None. - # We cannot create pre_build for the Dropdown because it has to be called after vm.Filter.pre_build, but nothing - # guarantees that. We can call Filter.selector.pre_build() from the Filter.pre_build() method if we decide that. - # TODO: move this to pre_build once we have better control of the ordering. - if self.value is None: - _, default_value = get_options_and_default(self.options, self.multi) - self.value = default_value - - # TODO-NEXT: Replace this with the "universal Vizro placeholder" component. - return html.Div( - children=[ - html.Legend(children=self.title, className="form-label") if self.title else None, - dmc.DateRangePicker( - id=self.id, - value=self.value, persistence=True, + optionHeight=option_height, persistence_type="session", ), ] ) - - @_log_call - def build(self): - return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/radio_items.py b/vizro-core/src/vizro/models/_components/form/radio_items.py index 48b8bc6bc..dfa282126 100644 --- a/vizro-core/src/vizro/models/_components/form/radio_items.py +++ b/vizro-core/src/vizro/models/_components/form/radio_items.py @@ -39,8 +39,6 @@ class RadioItems(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] - _dynamic: bool = PrivateAttr(False) - # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -49,8 +47,9 @@ class RadioItems(VizroBaseModel): _validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict) _validate_value = validator("value", allow_reuse=True, always=True)(validate_value) - def __call__(self, options): - full_options, default_value = get_options_and_default(options=options, multi=False) + @_log_call + def build(self): + full_options, default_value = get_options_and_default(options=self.options, multi=False) return html.Fieldset( children=[ @@ -64,13 +63,3 @@ def __call__(self, options): ), ] ) - - def _build_dynamic_placeholder(self): - if self.value is None: - self.value = get_options_and_default(self.options, multi=False)[1] - - return self.__call__(self.options) - - @_log_call - def build(self): - return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/range_slider.py b/vizro-core/src/vizro/models/_components/form/range_slider.py index a96521708..16f0cb8c9 100644 --- a/vizro-core/src/vizro/models/_components/form/range_slider.py +++ b/vizro-core/src/vizro/models/_components/form/range_slider.py @@ -50,8 +50,6 @@ class RangeSlider(VizroBaseModel): title: str = Field("", description="Title to be displayed.") actions: list[Action] = [] - _dynamic: bool = PrivateAttr(False) - # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -62,7 +60,10 @@ class RangeSlider(VizroBaseModel): _set_default_marks = validator("marks", allow_reuse=True, always=True)(set_default_marks) _set_actions = _action_validator_factory("value") - def __call__(self, min, max, current_value): + @_log_call + def build(self): + init_value = self.value or [self.min, self.max] # type: ignore[list-item] + output = [ Output(f"{self.id}_start_value", "value"), Output(f"{self.id}_end_value", "value"), @@ -85,7 +86,7 @@ def __call__(self, min, max, current_value): return html.Div( children=[ - dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": min, "max": max}), + dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": self.min, "max": self.max}), html.Div( children=[ dbc.Label(children=self.title, html_for=self.id) if self.title else None, @@ -95,10 +96,10 @@ def __call__(self, min, max, current_value): id=f"{self.id}_start_value", type="number", placeholder="min", - min=min, - max=max, + min=self.min, + max=self.max, step=self.step, - value=current_value[0], + value=init_value[0], persistence=True, persistence_type="session", className="slider-text-input-field", @@ -108,15 +109,15 @@ def __call__(self, min, max, current_value): id=f"{self.id}_end_value", type="number", placeholder="max", - min=min, - max=max, + min=self.min, + max=self.max, step=self.step, - value=current_value[1], + value=init_value[1], persistence=True, persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id=f"{self.id}_input_store", storage_type="session"), + dcc.Store(id=f"{self.id}_input_store", storage_type="session", data=init_value), ], className="slider-text-input-container", ), @@ -125,26 +126,14 @@ def __call__(self, min, max, current_value): ), dcc.RangeSlider( id=self.id, - min=min, - max=max, + min=self.min, + max=self.max, step=self.step, marks=self.marks, - value=current_value, + value=init_value, persistence=True, persistence_type="session", className="slider-track-without-marks" if self.marks is None else "slider-track-with-marks", ), ] ) - - def _build_dynamic_placeholder(self, current_value): - return self.__call__(self.min, self.max, current_value) - - @_log_call - def build(self): - current_value = self.value or [self.min, self.max] # type: ignore[list-item] - return ( - self._build_dynamic_placeholder(current_value) - if self._dynamic - else self.__call__(self.min, self.max, current_value) - ) diff --git a/vizro-core/src/vizro/models/_components/form/slider.py b/vizro-core/src/vizro/models/_components/form/slider.py index 2ffdb9f6a..65b37fe9a 100644 --- a/vizro-core/src/vizro/models/_components/form/slider.py +++ b/vizro-core/src/vizro/models/_components/form/slider.py @@ -48,8 +48,6 @@ class Slider(VizroBaseModel): title: str = Field("", description="Title to be displayed.") actions: list[Action] = [] - _dynamic: bool = PrivateAttr(False) - # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -60,7 +58,10 @@ class Slider(VizroBaseModel): _set_default_marks = validator("marks", allow_reuse=True, always=True)(set_default_marks) _set_actions = _action_validator_factory("value") - def __call__(self, min, max, current_value): + @_log_call + def build(self): + init_value = self.value or self.min + output = [ Output(f"{self.id}_end_value", "value"), Output(self.id, "value"), @@ -81,7 +82,7 @@ def __call__(self, min, max, current_value): return html.Div( children=[ - dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": min, "max": max}), + dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": self.min, "max": self.max}), html.Div( children=[ dbc.Label(children=self.title, html_for=self.id) if self.title else None, @@ -91,15 +92,15 @@ def __call__(self, min, max, current_value): id=f"{self.id}_end_value", type="number", placeholder="max", - min=min, - max=max, + min=self.min, + max=self.max, step=self.step, - value=current_value, + value=init_value, persistence=True, persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id=f"{self.id}_input_store", storage_type="session"), + dcc.Store(id=f"{self.id}_input_store", storage_type="session", data=init_value), ], className="slider-text-input-container", ), @@ -108,11 +109,11 @@ def __call__(self, min, max, current_value): ), dcc.Slider( id=self.id, - min=min, - max=max, + min=self.min, + max=self.max, step=self.step, marks=self.marks, - value=current_value, + value=init_value, included=False, persistence=True, persistence_type="session", @@ -120,15 +121,3 @@ def __call__(self, min, max, current_value): ), ] ) - - def _build_dynamic_placeholder(self, current_value): - return self.__call__(self.min, self.max, current_value) - - @_log_call - def build(self): - current_value = self.value if self.value is not None else self.min - return ( - self._build_dynamic_placeholder(current_value) - if self._dynamic - else self.__call__(self.min, self.max, current_value) - ) diff --git a/vizro-core/src/vizro/models/_controls/parameter.py b/vizro-core/src/vizro/models/_controls/parameter.py index cdc76936c..c77c7c7bf 100644 --- a/vizro-core/src/vizro/models/_controls/parameter.py +++ b/vizro-core/src/vizro/models/_controls/parameter.py @@ -56,7 +56,6 @@ def check_data_frame_as_target_argument(cls, target): f"Invalid target {target}. 'data_frame' target must be supplied in the form " ".data_frame." ) - # TODO: Add validation: Make sure the target data_frame is _DynamicData. return target @validator("targets") diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index 2fd7c7b00..b635b8e95 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -308,31 +308,18 @@ def _make_page_404_layout(self): return html.Div( [ # Theme switch is added such that the 404 page has the same theme as the user-selected one. - html.Div( - children=dbc.Switch( - id="theme-selector", - value=self.theme == "vizro_light", - persistence=True, - persistence_type="session", - ), - id="settings", + dbc.Switch( + id="theme-selector", + value=self.theme == "vizro_light", + persistence=True, + persistence_type="session", ), html.Img(src=f"data:image/svg+xml;base64,{error_404_svg}"), - html.Div( - [ - html.Div( - children=[ - html.H3("This page could not be found.", className="heading-3-600"), - html.P("Make sure the URL you entered is correct."), - ], - className="error-text-container", - ), - dbc.Button(children="Take me home", href=get_relative_path("/")), - ], - className="error-content-container", - ), + html.H3("This page could not be found."), + html.P("Make sure the URL you entered is correct."), + dbc.Button(children="Take me home", href=get_relative_path("/"), className="mt-4"), ], - className="page-error-container", + className="d-flex flex-column align-items-center justify-content-center min-vh-100", ) @staticmethod diff --git a/vizro-core/src/vizro/static/css/layout.css b/vizro-core/src/vizro/static/css/layout.css index 996c1108c..a7c66f864 100644 --- a/vizro-core/src/vizro/static/css/layout.css +++ b/vizro-core/src/vizro/static/css/layout.css @@ -85,31 +85,6 @@ border-bottom: 1px solid var(--border-subtleAlpha01); } -.page-error-container { - align-items: center; - display: flex; - flex-direction: column; - height: 100vh; - justify-content: center; - width: 100vw; -} - -.error-content-container { - align-items: center; - display: inline-flex; - flex-direction: column; - gap: 24px; - margin-top: -32px; -} - -.error-text-container { - display: flex; - flex-direction: column; - gap: 8px; - text-align: center; - width: 336px; -} - .dashboard_title { display: flex; flex-direction: column; diff --git a/vizro-core/src/vizro/static/js/models/range_slider.js b/vizro-core/src/vizro/static/js/models/range_slider.js index 8aafdde7f..5eb1892aa 100644 --- a/vizro-core/src/vizro/static/js/models/range_slider.js +++ b/vizro-core/src/vizro/static/js/models/range_slider.js @@ -17,8 +17,6 @@ function update_range_slider_values( trigger_id = dash_clientside.callback_context.triggered[0]["prop_id"].split(".")[0]; } - - // text form component is the trigger if ( trigger_id === `${self_data["id"]}_start_value` || trigger_id === `${self_data["id"]}_end_value` @@ -26,36 +24,21 @@ function update_range_slider_values( if (isNaN(start) || isNaN(end)) { return dash_clientside.no_update; } - return [start, end, [start, end], [start, end]]; - - // slider component is the trigger + [start_text_value, end_text_value] = [start, end]; } else if (trigger_id === self_data["id"]) { - return [slider[0], slider[1], slider, slider]; - } - // on_page_load is the trigger - if (input_store === null) { - return [ - dash_clientside.no_update, - dash_clientside.no_update, - dash_clientside.no_update, - slider, - ]; - } - if ( - slider[0] === start && - input_store[0] === start && - slider[1] === end && - input_store[1] === end - ) { - // To prevent filter_action to be triggered after on_page_load - return [ - dash_clientside.no_update, - dash_clientside.no_update, - dash_clientside.no_update, - dash_clientside.no_update, - ]; + [start_text_value, end_text_value] = [slider[0], slider[1]]; + } else { + [start_text_value, end_text_value] = + input_store !== null ? input_store : [slider[0], slider[1]]; } - return [input_store[0], input_store[1], input_store, input_store]; + + start_value = Math.min(start_text_value, end_text_value); + end_value = Math.max(start_text_value, end_text_value); + start_value = Math.max(self_data["min"], start_value); + end_value = Math.min(self_data["max"], end_value); + slider_value = [start_value, end_value]; + + return [start_value, end_value, slider_value, [start_value, end_value]]; } window.dash_clientside = { diff --git a/vizro-core/src/vizro/static/js/models/slider.js b/vizro-core/src/vizro/static/js/models/slider.js index 1b15d78ae..bc572cffe 100644 --- a/vizro-core/src/vizro/static/js/models/slider.js +++ b/vizro-core/src/vizro/static/js/models/slider.js @@ -6,31 +6,20 @@ function update_slider_values(start, slider, input_store, self_data) { trigger_id = dash_clientside.callback_context.triggered[0]["prop_id"].split(".")[0]; } - - // text form component is the trigger if (trigger_id === `${self_data["id"]}_end_value`) { if (isNaN(start)) { return dash_clientside.no_update; } - return [start, start, start]; - - // slider component is the trigger + end_value = start; } else if (trigger_id === self_data["id"]) { - return [slider, slider, slider]; - } - // on_page_load is the trigger - if (input_store === null) { - return [dash_clientside.no_update, dash_clientside.no_update, slider]; + end_value = slider; + } else { + end_value = input_store !== null ? input_store : self_data["min"]; } - if (slider === start && start === input_store) { - // To prevent filter_action to be triggered after on_page_load - return [ - dash_clientside.no_update, - dash_clientside.no_update, - dash_clientside.no_update, - ]; - } - return [input_store, input_store, input_store]; + + end_value = Math.min(Math.max(self_data["min"], end_value), self_data["max"]); + + return [end_value, end_value, end_value]; } window.dash_clientside = { From 539884f324ce68ad0e7cc28b2dfc8b2354f25b76 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 15:55:31 +0000 Subject: [PATCH 49/54] Align src with main --- vizro-core/examples/scratch_dev/data.yaml | 12 + .../src/vizro/actions/_actions_utils.py | 56 ++- .../src/vizro/actions/_filter_action.py | 2 +- .../src/vizro/actions/_on_page_load_action.py | 2 +- .../src/vizro/actions/_parameter_action.py | 2 +- .../actions/filter_interaction_action.py | 2 +- .../models/_components/form/_form_utils.py | 3 + .../models/_components/form/checklist.py | 17 +- .../vizro/models/_components/form/dropdown.py | 38 +- .../models/_components/form/radio_items.py | 17 +- .../models/_components/form/range_slider.py | 41 +- .../vizro/models/_components/form/slider.py | 35 +- .../src/vizro/models/_controls/parameter.py | 1 + .../vizro/static/js/models/range_slider.js | 43 +- .../src/vizro/static/js/models/slider.js | 27 +- .../tests/unit/vizro/actions/conftest.py | 47 --- vizro-core/tests/unit/vizro/conftest.py | 47 +++ .../_components/form/test_range_slider.py | 4 +- .../models/_components/form/test_slider.py | 2 +- .../vizro/models/_controls/test_filter.py | 374 +++++++++++++++++- 20 files changed, 638 insertions(+), 134 deletions(-) create mode 100644 vizro-core/examples/scratch_dev/data.yaml diff --git a/vizro-core/examples/scratch_dev/data.yaml b/vizro-core/examples/scratch_dev/data.yaml new file mode 100644 index 000000000..d8b0aea90 --- /dev/null +++ b/vizro-core/examples/scratch_dev/data.yaml @@ -0,0 +1,12 @@ +# Choose between 0-50 +setosa: 5 +versicolor: 10 +virginica: 15 + +# Choose between: 4.3 to 7.4 +min: 5 +max: 7 + +# Choose between: 2020-01-01 to 2020-05-29 +date_min: 2024-01-01 +date_max: 2024-05-29 diff --git a/vizro-core/src/vizro/actions/_actions_utils.py b/vizro-core/src/vizro/actions/_actions_utils.py index 984359fc9..1873b6620 100644 --- a/vizro-core/src/vizro/actions/_actions_utils.py +++ b/vizro-core/src/vizro/actions/_actions_utils.py @@ -49,18 +49,18 @@ def _get_component_actions(component) -> list[Action]: def _apply_filter_controls( - data_frame: pd.DataFrame, ctds_filters: list[CallbackTriggerDict], target: ModelID + data_frame: pd.DataFrame, ctds_filter: list[CallbackTriggerDict], target: ModelID ) -> pd.DataFrame: """Applies filters from a vm.Filter model in the controls. Args: data_frame: unfiltered DataFrame. - ctds_filters: list of CallbackTriggerDict for filters. + ctds_filter: list of CallbackTriggerDict for filters. target: id of targeted Figure. Returns: filtered DataFrame. """ - for ctd in ctds_filters: + for ctd in ctds_filter: selector_value = ctd["value"] selector_value = selector_value if isinstance(selector_value, list) else [selector_value] selector_actions = _get_component_actions(model_manager[ctd["id"]]) @@ -162,12 +162,12 @@ def _update_nested_figure_properties( def _get_parametrized_config( - ctd_parameters: list[CallbackTriggerDict], target: ModelID, data_frame: bool + ctds_parameter: list[CallbackTriggerDict], target: ModelID, data_frame: bool ) -> dict[str, Any]: """Convert parameters into a keyword-argument dictionary. Args: - ctd_parameters: list of CallbackTriggerDicts for vm.Parameter. + ctds_parameter: list of CallbackTriggerDicts for vm.Parameter. target: id of targeted figure. data_frame: whether to return only DataFrame parameters starting "data_frame." or only non-DataFrame parameters. @@ -185,7 +185,7 @@ def _get_parametrized_config( config = deepcopy(model_manager[target].figure._arguments) del config["data_frame"] - for ctd in ctd_parameters: + for ctd in ctds_parameter: # TODO: needs to be refactored so that it is independent of implementation details parameter_value = ctd["value"] @@ -221,7 +221,7 @@ def _apply_filters( # Takes in just one target, so dataframe is filtered repeatedly for every target that uses it. # Potentially this could be de-duplicated but it's not so important since filtering is a relatively fast # operation (compared to data loading). - filtered_data = _apply_filter_controls(data_frame=data, ctds_filters=ctds_filter, target=target) + filtered_data = _apply_filter_controls(data_frame=data, ctds_filter=ctds_filter, target=target) filtered_data = _apply_filter_interaction( data_frame=filtered_data, ctds_filter_interaction=ctds_filter_interaction, target=target ) @@ -229,17 +229,17 @@ def _apply_filters( def _get_unfiltered_data( - ctds_parameters: list[CallbackTriggerDict], targets: list[ModelID] + ctds_parameter: list[CallbackTriggerDict], targets: list[ModelID] ) -> dict[ModelID, pd.DataFrame]: # Takes in multiple targets to ensure that data can be loaded efficiently using _multi_load and not repeated for # every single target. - # Getting unfiltered data requires data frame parameters. We pass in all ctd_parameters and then find the + # Getting unfiltered data requires data frame parameters. We pass in all ctds_parameter and then find the # data_frame ones by passing data_frame=True in the call to _get_paramaterized_config. Static data is also # handled here and will just have empty dictionary for its kwargs. multi_data_source_name_load_kwargs: list[tuple[DataSourceName, dict[str, Any]]] = [] for target in targets: dynamic_data_load_params = _get_parametrized_config( - ctd_parameters=ctds_parameters, target=target, data_frame=True + ctds_parameter=ctds_parameter, target=target, data_frame=True ) data_source_name = model_manager[target]["data_frame"] multi_data_source_name_load_kwargs.append((data_source_name, dynamic_data_load_params["data_frame"])) @@ -250,25 +250,45 @@ def _get_unfiltered_data( def _get_modified_page_figures( ctds_filter: list[CallbackTriggerDict], ctds_filter_interaction: list[dict[str, CallbackTriggerDict]], - ctds_parameters: list[CallbackTriggerDict], + ctds_parameter: list[CallbackTriggerDict], targets: list[ModelID], ) -> dict[ModelID, Any]: + from vizro.models import Filter + outputs: dict[ModelID, Any] = {} + control_targets = [] + figure_targets = [] + for target in targets: + if isinstance(model_manager[target], Filter): + control_targets.append(target) + else: + figure_targets.append(target) + + # TODO-NEXT: Add fetching unfiltered data for the Filter.targets as well, once dynamic filters become "targetable" + # from other actions too. For example, in future, if Parameter is targeting only a single Filter. + # Currently, it only works for the on_page_load because Filter.targets are indeed the part of the actions' targets. + # More about the limitation: https://github.com/mckinsey/vizro/pull/879/files#r1863535516 + target_to_data_frame = _get_unfiltered_data(ctds_parameter=ctds_parameter, targets=figure_targets) + # TODO: the structure here would be nicer if we could get just the ctds for a single target at one time, # so you could do apply_filters on a target a pass only the ctds relevant for that target. # Consider restructuring ctds to a more convenient form to make this possible. - - for target, unfiltered_data in _get_unfiltered_data(ctds_parameters, targets).items(): + for target, unfiltered_data in target_to_data_frame.items(): filtered_data = _apply_filters(unfiltered_data, ctds_filter, ctds_filter_interaction, target) outputs[target] = model_manager[target]( data_frame=filtered_data, - **_get_parametrized_config(ctd_parameters=ctds_parameters, target=target, data_frame=False), + **_get_parametrized_config(ctds_parameter=ctds_parameter, target=target, data_frame=False), ) - # TODO NEXT: will need to pass unfiltered_data into Filter.__call__. - # This dictionary is filtered for correct targets already selected in Filter.__call__ or that could be done here - # instead. - # {target: data_frame for target, data_frame in unfiltered_data.items() if target in self.targets} + for target in control_targets: + ctd_filter = [item for item in ctds_filter if item["id"] == model_manager[target].selector.id] + + # This only covers the case of cross-page actions when Filter in an output, but is not an input of the action. + current_value = ctd_filter[0]["value"] if ctd_filter else None + + # target_to_data_frame contains all targets, including some which might not be relevant for the filter in + # question. We filter to use just the relevant targets in Filter.__call__. + outputs[target] = model_manager[target](target_to_data_frame=target_to_data_frame, current_value=current_value) return outputs diff --git a/vizro-core/src/vizro/actions/_filter_action.py b/vizro-core/src/vizro/actions/_filter_action.py index f3ec21b37..d50f0125c 100644 --- a/vizro-core/src/vizro/actions/_filter_action.py +++ b/vizro-core/src/vizro/actions/_filter_action.py @@ -32,6 +32,6 @@ def _filter( return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=targets, ) diff --git a/vizro-core/src/vizro/actions/_on_page_load_action.py b/vizro-core/src/vizro/actions/_on_page_load_action.py index 306ed9b5e..c6611fbd5 100644 --- a/vizro-core/src/vizro/actions/_on_page_load_action.py +++ b/vizro-core/src/vizro/actions/_on_page_load_action.py @@ -25,6 +25,6 @@ def _on_page_load(targets: list[ModelID], **inputs: dict[str, Any]) -> dict[Mode return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=targets, ) diff --git a/vizro-core/src/vizro/actions/_parameter_action.py b/vizro-core/src/vizro/actions/_parameter_action.py index 6284481ec..bfc58014f 100644 --- a/vizro-core/src/vizro/actions/_parameter_action.py +++ b/vizro-core/src/vizro/actions/_parameter_action.py @@ -27,6 +27,6 @@ def _parameter(targets: list[str], **inputs: dict[str, Any]) -> dict[ModelID, An return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=target_ids, ) diff --git a/vizro-core/src/vizro/actions/filter_interaction_action.py b/vizro-core/src/vizro/actions/filter_interaction_action.py index bc6659ab9..9618d265f 100644 --- a/vizro-core/src/vizro/actions/filter_interaction_action.py +++ b/vizro-core/src/vizro/actions/filter_interaction_action.py @@ -31,6 +31,6 @@ def filter_interaction(targets: Optional[list[ModelID]] = None, **inputs: dict[s return _get_modified_page_figures( ctds_filter=ctx.args_grouping["external"]["filters"], ctds_filter_interaction=ctx.args_grouping["external"]["filter_interaction"], - ctds_parameters=ctx.args_grouping["external"]["parameters"], + ctds_parameter=ctx.args_grouping["external"]["parameters"], targets=targets or [], ) diff --git a/vizro-core/src/vizro/models/_components/form/_form_utils.py b/vizro-core/src/vizro/models/_components/form/_form_utils.py index 18e666882..14a20a169 100644 --- a/vizro-core/src/vizro/models/_components/form/_form_utils.py +++ b/vizro-core/src/vizro/models/_components/form/_form_utils.py @@ -54,6 +54,9 @@ def validate_value(cls, value, values): [entry["value"] for entry in values["options"]] if isinstance(values["options"][0], dict) else values["options"] ) + if hasattr(value, "__iter__") and ALL_OPTION in value: + return value + if value and not is_value_contained(value, possible_values): raise ValueError("Please provide a valid value from `options`.") diff --git a/vizro-core/src/vizro/models/_components/form/checklist.py b/vizro-core/src/vizro/models/_components/form/checklist.py index 68cb26ad1..ed746dec3 100644 --- a/vizro-core/src/vizro/models/_components/form/checklist.py +++ b/vizro-core/src/vizro/models/_components/form/checklist.py @@ -38,6 +38,8 @@ class Checklist(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -46,9 +48,8 @@ class Checklist(VizroBaseModel): _validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict) _validate_value = validator("value", allow_reuse=True, always=True)(validate_value) - @_log_call - def build(self): - full_options, default_value = get_options_and_default(options=self.options, multi=True) + def __call__(self, options): + full_options, default_value = get_options_and_default(options=options, multi=True) return html.Fieldset( children=[ @@ -62,3 +63,13 @@ def build(self): ), ] ) + + def _build_dynamic_placeholder(self): + if self.value is None: + self.value = [get_options_and_default(self.options, multi=True)[1]] + + return self.__call__(self.options) + + @_log_call + def build(self): + return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/dropdown.py b/vizro-core/src/vizro/models/_components/form/dropdown.py index d0fa24444..a56c13c47 100755 --- a/vizro-core/src/vizro/models/_components/form/dropdown.py +++ b/vizro-core/src/vizro/models/_components/form/dropdown.py @@ -10,6 +10,7 @@ from pydantic import Field, PrivateAttr, StrictBool, root_validator, validator import dash_bootstrap_components as dbc +import dash_mantine_components as dmc from vizro.models import Action, VizroBaseModel from vizro.models._action._actions_chain import _action_validator_factory @@ -65,6 +66,10 @@ class Dropdown(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] + # Consider making the _dynamic public later. The same property could also be used for all other components. + # For example: vm.Graph could have a dynamic that is by default set on True. + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -82,9 +87,8 @@ def validate_multi(cls, multi, values): raise ValueError("Please set multi=True if providing a list of default values.") return multi - @_log_call - def build(self): - full_options, default_value = get_options_and_default(options=self.options, multi=self.multi) + def __call__(self, options): + full_options, default_value = get_options_and_default(options=options, multi=self.multi) option_height = _calculate_option_height(full_options) return html.Div( @@ -95,9 +99,35 @@ def build(self): options=full_options, value=self.value if self.value is not None else default_value, multi=self.multi, - persistence=True, optionHeight=option_height, + persistence=True, + persistence_type="session", + ), + ] + ) + + def _build_dynamic_placeholder(self): + # Setting self.value is kind of Dropdown pre_build method. It sets self.value only the first time if it's None. + # We cannot create pre_build for the Dropdown because it has to be called after vm.Filter.pre_build, but nothing + # guarantees that. We can call Filter.selector.pre_build() from the Filter.pre_build() method if we decide that. + # TODO: move this to pre_build once we have better control of the ordering. + if self.value is None: + _, default_value = get_options_and_default(self.options, self.multi) + self.value = default_value + + # TODO-NEXT: Replace this with the "universal Vizro placeholder" component. + return html.Div( + children=[ + html.Legend(children=self.title, className="form-label") if self.title else None, + dmc.DateRangePicker( + id=self.id, + value=self.value, + persistence=True, persistence_type="session", ), ] ) + + @_log_call + def build(self): + return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/radio_items.py b/vizro-core/src/vizro/models/_components/form/radio_items.py index dfa282126..48b8bc6bc 100644 --- a/vizro-core/src/vizro/models/_components/form/radio_items.py +++ b/vizro-core/src/vizro/models/_components/form/radio_items.py @@ -39,6 +39,8 @@ class RadioItems(VizroBaseModel): title: str = Field("", description="Title to be displayed") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -47,9 +49,8 @@ class RadioItems(VizroBaseModel): _validate_options = root_validator(allow_reuse=True, pre=True)(validate_options_dict) _validate_value = validator("value", allow_reuse=True, always=True)(validate_value) - @_log_call - def build(self): - full_options, default_value = get_options_and_default(options=self.options, multi=False) + def __call__(self, options): + full_options, default_value = get_options_and_default(options=options, multi=False) return html.Fieldset( children=[ @@ -63,3 +64,13 @@ def build(self): ), ] ) + + def _build_dynamic_placeholder(self): + if self.value is None: + self.value = get_options_and_default(self.options, multi=False)[1] + + return self.__call__(self.options) + + @_log_call + def build(self): + return self._build_dynamic_placeholder() if self._dynamic else self.__call__(self.options) diff --git a/vizro-core/src/vizro/models/_components/form/range_slider.py b/vizro-core/src/vizro/models/_components/form/range_slider.py index 16f0cb8c9..a96521708 100644 --- a/vizro-core/src/vizro/models/_components/form/range_slider.py +++ b/vizro-core/src/vizro/models/_components/form/range_slider.py @@ -50,6 +50,8 @@ class RangeSlider(VizroBaseModel): title: str = Field("", description="Title to be displayed.") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -60,10 +62,7 @@ class RangeSlider(VizroBaseModel): _set_default_marks = validator("marks", allow_reuse=True, always=True)(set_default_marks) _set_actions = _action_validator_factory("value") - @_log_call - def build(self): - init_value = self.value or [self.min, self.max] # type: ignore[list-item] - + def __call__(self, min, max, current_value): output = [ Output(f"{self.id}_start_value", "value"), Output(f"{self.id}_end_value", "value"), @@ -86,7 +85,7 @@ def build(self): return html.Div( children=[ - dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": self.min, "max": self.max}), + dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": min, "max": max}), html.Div( children=[ dbc.Label(children=self.title, html_for=self.id) if self.title else None, @@ -96,10 +95,10 @@ def build(self): id=f"{self.id}_start_value", type="number", placeholder="min", - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, - value=init_value[0], + value=current_value[0], persistence=True, persistence_type="session", className="slider-text-input-field", @@ -109,15 +108,15 @@ def build(self): id=f"{self.id}_end_value", type="number", placeholder="max", - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, - value=init_value[1], + value=current_value[1], persistence=True, persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id=f"{self.id}_input_store", storage_type="session", data=init_value), + dcc.Store(id=f"{self.id}_input_store", storage_type="session"), ], className="slider-text-input-container", ), @@ -126,14 +125,26 @@ def build(self): ), dcc.RangeSlider( id=self.id, - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, marks=self.marks, - value=init_value, + value=current_value, persistence=True, persistence_type="session", className="slider-track-without-marks" if self.marks is None else "slider-track-with-marks", ), ] ) + + def _build_dynamic_placeholder(self, current_value): + return self.__call__(self.min, self.max, current_value) + + @_log_call + def build(self): + current_value = self.value or [self.min, self.max] # type: ignore[list-item] + return ( + self._build_dynamic_placeholder(current_value) + if self._dynamic + else self.__call__(self.min, self.max, current_value) + ) diff --git a/vizro-core/src/vizro/models/_components/form/slider.py b/vizro-core/src/vizro/models/_components/form/slider.py index 65b37fe9a..2ffdb9f6a 100644 --- a/vizro-core/src/vizro/models/_components/form/slider.py +++ b/vizro-core/src/vizro/models/_components/form/slider.py @@ -48,6 +48,8 @@ class Slider(VizroBaseModel): title: str = Field("", description="Title to be displayed.") actions: list[Action] = [] + _dynamic: bool = PrivateAttr(False) + # Component properties for actions and interactions _input_property: str = PrivateAttr("value") @@ -58,10 +60,7 @@ class Slider(VizroBaseModel): _set_default_marks = validator("marks", allow_reuse=True, always=True)(set_default_marks) _set_actions = _action_validator_factory("value") - @_log_call - def build(self): - init_value = self.value or self.min - + def __call__(self, min, max, current_value): output = [ Output(f"{self.id}_end_value", "value"), Output(self.id, "value"), @@ -82,7 +81,7 @@ def build(self): return html.Div( children=[ - dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": self.min, "max": self.max}), + dcc.Store(f"{self.id}_callback_data", data={"id": self.id, "min": min, "max": max}), html.Div( children=[ dbc.Label(children=self.title, html_for=self.id) if self.title else None, @@ -92,15 +91,15 @@ def build(self): id=f"{self.id}_end_value", type="number", placeholder="max", - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, - value=init_value, + value=current_value, persistence=True, persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id=f"{self.id}_input_store", storage_type="session", data=init_value), + dcc.Store(id=f"{self.id}_input_store", storage_type="session"), ], className="slider-text-input-container", ), @@ -109,11 +108,11 @@ def build(self): ), dcc.Slider( id=self.id, - min=self.min, - max=self.max, + min=min, + max=max, step=self.step, marks=self.marks, - value=init_value, + value=current_value, included=False, persistence=True, persistence_type="session", @@ -121,3 +120,15 @@ def build(self): ), ] ) + + def _build_dynamic_placeholder(self, current_value): + return self.__call__(self.min, self.max, current_value) + + @_log_call + def build(self): + current_value = self.value if self.value is not None else self.min + return ( + self._build_dynamic_placeholder(current_value) + if self._dynamic + else self.__call__(self.min, self.max, current_value) + ) diff --git a/vizro-core/src/vizro/models/_controls/parameter.py b/vizro-core/src/vizro/models/_controls/parameter.py index c77c7c7bf..cdc76936c 100644 --- a/vizro-core/src/vizro/models/_controls/parameter.py +++ b/vizro-core/src/vizro/models/_controls/parameter.py @@ -56,6 +56,7 @@ def check_data_frame_as_target_argument(cls, target): f"Invalid target {target}. 'data_frame' target must be supplied in the form " ".data_frame." ) + # TODO: Add validation: Make sure the target data_frame is _DynamicData. return target @validator("targets") diff --git a/vizro-core/src/vizro/static/js/models/range_slider.js b/vizro-core/src/vizro/static/js/models/range_slider.js index 5eb1892aa..8aafdde7f 100644 --- a/vizro-core/src/vizro/static/js/models/range_slider.js +++ b/vizro-core/src/vizro/static/js/models/range_slider.js @@ -17,6 +17,8 @@ function update_range_slider_values( trigger_id = dash_clientside.callback_context.triggered[0]["prop_id"].split(".")[0]; } + + // text form component is the trigger if ( trigger_id === `${self_data["id"]}_start_value` || trigger_id === `${self_data["id"]}_end_value` @@ -24,21 +26,36 @@ function update_range_slider_values( if (isNaN(start) || isNaN(end)) { return dash_clientside.no_update; } - [start_text_value, end_text_value] = [start, end]; + return [start, end, [start, end], [start, end]]; + + // slider component is the trigger } else if (trigger_id === self_data["id"]) { - [start_text_value, end_text_value] = [slider[0], slider[1]]; - } else { - [start_text_value, end_text_value] = - input_store !== null ? input_store : [slider[0], slider[1]]; + return [slider[0], slider[1], slider, slider]; } - - start_value = Math.min(start_text_value, end_text_value); - end_value = Math.max(start_text_value, end_text_value); - start_value = Math.max(self_data["min"], start_value); - end_value = Math.min(self_data["max"], end_value); - slider_value = [start_value, end_value]; - - return [start_value, end_value, slider_value, [start_value, end_value]]; + // on_page_load is the trigger + if (input_store === null) { + return [ + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + slider, + ]; + } + if ( + slider[0] === start && + input_store[0] === start && + slider[1] === end && + input_store[1] === end + ) { + // To prevent filter_action to be triggered after on_page_load + return [ + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + ]; + } + return [input_store[0], input_store[1], input_store, input_store]; } window.dash_clientside = { diff --git a/vizro-core/src/vizro/static/js/models/slider.js b/vizro-core/src/vizro/static/js/models/slider.js index bc572cffe..1b15d78ae 100644 --- a/vizro-core/src/vizro/static/js/models/slider.js +++ b/vizro-core/src/vizro/static/js/models/slider.js @@ -6,20 +6,31 @@ function update_slider_values(start, slider, input_store, self_data) { trigger_id = dash_clientside.callback_context.triggered[0]["prop_id"].split(".")[0]; } + + // text form component is the trigger if (trigger_id === `${self_data["id"]}_end_value`) { if (isNaN(start)) { return dash_clientside.no_update; } - end_value = start; + return [start, start, start]; + + // slider component is the trigger } else if (trigger_id === self_data["id"]) { - end_value = slider; - } else { - end_value = input_store !== null ? input_store : self_data["min"]; + return [slider, slider, slider]; } - - end_value = Math.min(Math.max(self_data["min"], end_value), self_data["max"]); - - return [end_value, end_value, end_value]; + // on_page_load is the trigger + if (input_store === null) { + return [dash_clientside.no_update, dash_clientside.no_update, slider]; + } + if (slider === start && start === input_store) { + // To prevent filter_action to be triggered after on_page_load + return [ + dash_clientside.no_update, + dash_clientside.no_update, + dash_clientside.no_update, + ]; + } + return [input_store, input_store, input_store]; } window.dash_clientside = { diff --git a/vizro-core/tests/unit/vizro/actions/conftest.py b/vizro-core/tests/unit/vizro/actions/conftest.py index 902ca042f..3b7bc5337 100644 --- a/vizro-core/tests/unit/vizro/actions/conftest.py +++ b/vizro-core/tests/unit/vizro/actions/conftest.py @@ -1,4 +1,3 @@ -import pandas as pd import pytest import vizro.models as vm @@ -25,37 +24,11 @@ def iris(): return px.data.iris() -@pytest.fixture -def gapminder_dynamic_first_n_last_n_function(gapminder): - return lambda first_n=None, last_n=None: ( - pd.concat([gapminder[:first_n], gapminder[-last_n:]]) - if last_n - else gapminder[:first_n] - if first_n - else gapminder - ) - - -@pytest.fixture -def box_params(): - return {"x": "continent", "y": "lifeExp", "custom_data": ["continent"]} - - @pytest.fixture def box_chart(gapminder_2007, box_params): return px.box(gapminder_2007, **box_params) -@pytest.fixture -def box_chart_dynamic_data_frame(box_params): - return px.box("gapminder_dynamic_first_n_last_n", **box_params) - - -@pytest.fixture -def scatter_params(): - return {"x": "gdpPercap", "y": "lifeExp"} - - @pytest.fixture def scatter_chart(gapminder_2007, scatter_params): return px.scatter(gapminder_2007, **scatter_params) @@ -71,11 +44,6 @@ def scatter_matrix_chart(iris, scatter_matrix_params): return px.scatter_matrix(iris, **scatter_matrix_params) -@pytest.fixture -def scatter_chart_dynamic_data_frame(scatter_params): - return px.scatter("gapminder_dynamic_first_n_last_n", **scatter_params) - - @pytest.fixture def target_scatter_filtered_continent(request, gapminder_2007, scatter_params): continent = request.param @@ -105,21 +73,6 @@ def managers_one_page_two_graphs_one_button(box_chart, scatter_chart): Vizro._pre_build() -@pytest.fixture -def managers_one_page_two_graphs_with_dynamic_data(box_chart_dynamic_data_frame, scatter_chart_dynamic_data_frame): - """Instantiates a simple model_manager and data_manager with a page, two graph models and the button component.""" - vm.Page( - id="test_page", - title="My first dashboard", - components=[ - vm.Graph(id="box_chart", figure=box_chart_dynamic_data_frame), - vm.Graph(id="scatter_chart", figure=scatter_chart_dynamic_data_frame), - vm.Button(id="button"), - ], - ) - Vizro._pre_build() - - @pytest.fixture def managers_one_page_two_graphs_one_table_one_aggrid_one_button( box_chart, scatter_chart, dash_data_table_with_id, ag_grid_with_id diff --git a/vizro-core/tests/unit/vizro/conftest.py b/vizro-core/tests/unit/vizro/conftest.py index cba2bccc7..dd15c9fa4 100644 --- a/vizro-core/tests/unit/vizro/conftest.py +++ b/vizro-core/tests/unit/vizro/conftest.py @@ -1,5 +1,6 @@ """Fixtures to be shared across several tests.""" +import pandas as pd import plotly.graph_objects as go import pytest @@ -20,6 +21,17 @@ def stocks(): return px.data.stocks() +@pytest.fixture +def gapminder_dynamic_first_n_last_n_function(gapminder): + return lambda first_n=None, last_n=None: ( + pd.concat([gapminder[:first_n], gapminder[-last_n:]]) + if last_n + else gapminder[:first_n] + if first_n + else gapminder + ) + + @pytest.fixture def standard_px_chart(gapminder): return px.scatter( @@ -33,6 +45,26 @@ def standard_px_chart(gapminder): ) +@pytest.fixture +def scatter_params(): + return {"x": "gdpPercap", "y": "lifeExp"} + + +@pytest.fixture +def scatter_chart_dynamic_data_frame(scatter_params): + return px.scatter("gapminder_dynamic_first_n_last_n", **scatter_params) + + +@pytest.fixture +def box_params(): + return {"x": "continent", "y": "lifeExp", "custom_data": ["continent"]} + + +@pytest.fixture +def box_chart_dynamic_data_frame(box_params): + return px.box("gapminder_dynamic_first_n_last_n", **box_params) + + @pytest.fixture def standard_ag_grid(gapminder): return dash_ag_grid(data_frame=gapminder) @@ -88,6 +120,21 @@ def page_2(): return vm.Page(title="Page 2", components=[vm.Button()]) +@pytest.fixture +def managers_one_page_two_graphs_with_dynamic_data(box_chart_dynamic_data_frame, scatter_chart_dynamic_data_frame): + """Instantiates a simple model_manager and data_manager with a page, two graph models and the button component.""" + vm.Page( + id="test_page", + title="My first dashboard", + components=[ + vm.Graph(id="box_chart", figure=box_chart_dynamic_data_frame), + vm.Graph(id="scatter_chart", figure=scatter_chart_dynamic_data_frame), + vm.Button(id="button"), + ], + ) + Vizro._pre_build() + + @pytest.fixture() def vizro_app(): """Fixture to instantiate Vizro/Dash app. diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py b/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py index e0c9a9f13..4879aafc3 100644 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_range_slider.py @@ -48,7 +48,7 @@ def expected_range_slider_default(): persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id="range_slider_input_store", storage_type="session", data=[None, None]), + dcc.Store(id="range_slider_input_store", storage_type="session"), ], className="slider-text-input-container", ), @@ -105,7 +105,7 @@ def expected_range_slider_with_optional(): persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id="range_slider_input_store", storage_type="session", data=[0, 10]), + dcc.Store(id="range_slider_input_store", storage_type="session"), ], className="slider-text-input-container", ), diff --git a/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py b/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py index 56d2c5f24..92b34429e 100755 --- a/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py +++ b/vizro-core/tests/unit/vizro/models/_components/form/test_slider.py @@ -35,7 +35,7 @@ def expected_slider(): persistence_type="session", className="slider-text-input-field", ), - dcc.Store(id="slider_id_input_store", storage_type="session", data=5.0), + dcc.Store(id="slider_id_input_store", storage_type="session"), ], className="slider-text-input-container", ), diff --git a/vizro-core/tests/unit/vizro/models/_controls/test_filter.py b/vizro-core/tests/unit/vizro/models/_controls/test_filter.py index aa8c983c3..2b64666e9 100644 --- a/vizro-core/tests/unit/vizro/models/_controls/test_filter.py +++ b/vizro-core/tests/unit/vizro/models/_controls/test_filter.py @@ -4,11 +4,12 @@ import pandas as pd import pytest from asserts import assert_component_equal +from dash import dcc import vizro.models as vm import vizro.plotly.express as px from vizro import Vizro -from vizro.managers import model_manager +from vizro.managers import data_manager, model_manager from vizro.models._action._actions_chain import ActionsChain from vizro.models._controls.filter import Filter, _filter_between, _filter_isin from vizro.models.types import CapturedCallable @@ -52,6 +53,32 @@ def managers_column_only_exists_in_some(): Vizro._pre_build() +@pytest.fixture +def target_to_data_frame(): + return { + "column_numerical_exists_1": pd.DataFrame( + { + "column_numerical": [1, 2], + } + ), + "column_numerical_exists_2": pd.DataFrame( + { + "column_numerical": [2, 3], + } + ), + "column_categorical_exists_1": pd.DataFrame( + { + "column_categorical": ["a", "b"], + } + ), + "column_categorical_exists_2": pd.DataFrame( + { + "column_categorical": ["b", "c"], + } + ), + } + + class TestFilterFunctions: @pytest.mark.parametrize( "data, value, expected", @@ -219,6 +246,167 @@ def test_filter_isin_date(self, data, value, expected): pd.testing.assert_series_equal(result, expected) +class TestFilterStaticMethods: + """Tests static methods of the Filter class.""" + + @pytest.mark.parametrize( + "data_columns, expected", + [ + ([[]], []), + ([["A", "B", "A"]], ["A", "B"]), + ([[1, 2, 1]], [1, 2]), + ([[1.1, 2.2, 1.1]], [1.1, 2.2]), + ( + [ + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + datetime(2024, 1, 1), + ] + ], + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + ], + ), + ([[], []], []), + ([["A"], []], ["A"]), + ([[], ["A"]], ["A"]), + ([["A"], ["B"]], ["A", "B"]), + ([["A", "B"], ["B", "C"]], ["A", "B", "C"]), + ], + ) + def test_get_options(self, data_columns, expected): + targeted_data = pd.DataFrame({f"target_{i}": pd.Series(data) for i, data in enumerate(data_columns)}) + result = Filter._get_options(targeted_data) + assert result == expected + + @pytest.mark.parametrize( + "data_columns, current_value, expected", + [ + ([[]], None, []), + ([[]], "ALL", []), + ([[]], ["ALL", "A"], ["A"]), + ([["A"]], ["ALL", "B"], ["A", "B"]), + ([[]], "A", ["A"]), + ([[]], ["A", "B"], ["A", "B"]), + ([["A"]], "B", ["A", "B"]), + ([["A"]], ["B", "C"], ["A", "B", "C"]), + ([[1]], 2, [1, 2]), + ([[1]], [2, 3], [1, 2, 3]), + ([[1.1]], 2.2, [1.1, 2.2]), + ([[1.1]], [2.2, 3.3], [1.1, 2.2, 3.3]), + ( + [ + [ + datetime(2024, 1, 1), + ] + ], + datetime(2024, 1, 2), + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + ], + ), + ( + [ + [ + datetime(2024, 1, 1), + ] + ], + [ + datetime(2024, 1, 2), + datetime(2024, 1, 3), + ], + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + datetime(2024, 1, 3), + ], + ), + ], + ) + def test_get_options_with_current_value(self, data_columns, current_value, expected): + targeted_data = pd.DataFrame({f"target_{i}": pd.Series(data) for i, data in enumerate(data_columns)}) + result = Filter._get_options(targeted_data, current_value) + assert result == expected + + @pytest.mark.parametrize( + "data_columns, expected", + [ + ([[1, 2, 1]], (1, 2)), + ([[1.1, 2.2, 1.1]], (1.1, 2.2)), + ( + [ + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + datetime(2024, 1, 1), + ] + ], + ( + datetime(2024, 1, 1), + datetime(2024, 1, 2), + ), + ), + ([[1], []], (1, 1)), + ([[1, 2], []], (1, 2)), + ([[1, 2], [2, 3]], (1, 3)), + ], + ) + def test_get_min_max(self, data_columns, expected): + targeted_data = pd.DataFrame({f"target_{i}": pd.Series(data) for i, data in enumerate(data_columns)}) + result = Filter._get_min_max(targeted_data) + assert result == expected + + @pytest.mark.parametrize( + "data_columns, current_value, expected", + [ + ([[1, 2]], 3, (1, 3)), + ([[1, 2]], [3, 4], (1, 4)), + ([[1.1, 2.2]], 3.3, (1.1, 3.3)), + ([[1.1, 2.2]], [3.3, 4.4], (1.1, 4.4)), + ( + [ + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + ] + ], + datetime(2024, 1, 3), + ( + datetime(2024, 1, 1), + datetime(2024, 1, 3), + ), + ), + ( + [ + [ + datetime(2024, 1, 1), + datetime(2024, 1, 2), + ] + ], + [ + datetime(2024, 1, 3), + datetime(2024, 1, 4), + ], + ( + datetime(2024, 1, 1), + datetime(2024, 1, 4), + ), + ), + ([[1], []], 2, (1, 2)), + ([[1], []], [2, 3], (1, 3)), + ([[1], [2]], 3, (1, 3)), + ([[1], [2]], [3, 4], (1, 4)), + ], + ) + def test_get_min_max_with_current_value(self, data_columns, current_value, expected): + targeted_data = pd.DataFrame({f"target_{i}": pd.Series(data) for i, data in enumerate(data_columns)}) + result = Filter._get_min_max(targeted_data, current_value) + assert result == expected + + @pytest.mark.usefixtures("managers_one_page_two_graphs") class TestFilterInstantiation: """Tests model instantiation and the validators run at that time.""" @@ -244,6 +432,73 @@ def test_check_target_present_invalid(self): Filter(column="foo", targets=["invalid_target"]) +@pytest.mark.usefixtures("managers_column_only_exists_in_some") +class TestFilterCall: + """Test Filter.__call__() method with target_to_data_frame and current_value inputs.""" + + def test_filter_call_categorical_valid(self, target_to_data_frame): + filter = vm.Filter( + column="column_categorical", + targets=["column_categorical_exists_1", "column_categorical_exists_2"], + selector=vm.Dropdown(id="test_selector_id"), + ) + filter.pre_build() + + selector_build = filter(target_to_data_frame=target_to_data_frame, current_value=["a", "b"])["test_selector_id"] + assert selector_build.options == ["ALL", "a", "b", "c"] + + def test_filter_call_numerical_valid(self, target_to_data_frame): + filter = vm.Filter( + column="column_numerical", + targets=["column_numerical_exists_1", "column_numerical_exists_2"], + selector=vm.RangeSlider(id="test_selector_id"), + ) + filter.pre_build() + + selector_build = filter(target_to_data_frame=target_to_data_frame, current_value=[1, 2])["test_selector_id"] + assert selector_build.min == 1 + assert selector_build.max == 3 + + def test_filter_call_column_is_changed(self, target_to_data_frame): + filter = vm.Filter( + column="column_categorical", targets=["column_categorical_exists_1", "column_categorical_exists_2"] + ) + filter.pre_build() + + filter._column_type = "numerical" + + with pytest.raises( + ValueError, + match="column_categorical has changed type from numerical to categorical. " + "A filtered column cannot change type while the dashboard is running.", + ): + filter(target_to_data_frame=target_to_data_frame, current_value=["a", "b"]) + + def test_filter_call_selected_column_not_found_in_target(self): + filter = vm.Filter(column="column_categorical", targets=["column_categorical_exists_1"]) + filter.pre_build() + + with pytest.raises( + ValueError, + match="Selected column column_categorical not found in dataframe for column_categorical_exists_1.", + ): + filter(target_to_data_frame={"column_categorical_exists_1": pd.DataFrame()}, current_value=["a", "b"]) + + def test_filter_call_targeted_data_empty(self): + filter = vm.Filter(column="column_categorical", targets=["column_categorical_exists_1"]) + filter.pre_build() + + with pytest.raises( + ValueError, + match="Selected column column_categorical does not contain anything in any dataframe " + "for column_categorical_exists_1.", + ): + filter( + target_to_data_frame={"column_categorical_exists_1": pd.DataFrame({"column_categorical": []})}, + current_value=["a", "b"], + ) + + class TestPreBuildMethod: def test_targets_default_valid(self, managers_column_only_exists_in_some): # Core of tests is still interface level @@ -387,6 +642,72 @@ def test_validate_column_type(self, targets, managers_column_different_type): ): filter.pre_build() + @pytest.mark.usefixtures("managers_one_page_two_graphs") + def test_filter_is_not_dynamic(self): + filter = vm.Filter(column="continent") + model_manager["test_page"].controls = [filter] + filter.pre_build() + # Filter is not dynamic because it does not target a figure that uses dynamic data + assert not filter._dynamic + assert not filter.selector._dynamic + + @pytest.mark.usefixtures("managers_one_page_two_graphs_with_dynamic_data") + @pytest.mark.parametrize( + "test_column, test_selector", + [ + ("continent", vm.Checklist()), + ("continent", vm.Dropdown()), + ("continent", vm.Dropdown(multi=False)), + ("continent", vm.RadioItems()), + ("pop", vm.Slider()), + ("pop", vm.RangeSlider()), + ], + ) + def test_filter_is_dynamic_with_dynamic_selectors( + self, test_column, test_selector, gapminder_dynamic_first_n_last_n_function + ): + data_manager["gapminder_dynamic_first_n_last_n"] = gapminder_dynamic_first_n_last_n_function + filter = vm.Filter(column=test_column, selector=test_selector) + model_manager["test_page"].controls = [filter] + filter.pre_build() + # Filter is dynamic because it targets a figure that uses dynamic data + assert filter._dynamic + assert filter.selector._dynamic + + @pytest.mark.usefixtures("managers_one_page_two_graphs_with_dynamic_data") + def test_filter_is_not_dynamic_with_non_dynamic_selectors(self, gapminder_dynamic_first_n_last_n_function): + data_manager["gapminder_dynamic_first_n_last_n"] = gapminder_dynamic_first_n_last_n_function + filter = vm.Filter(column="year", selector=vm.DatePicker()) + model_manager["test_page"].controls = [filter] + filter.pre_build() + assert not filter._dynamic + + @pytest.mark.usefixtures("managers_one_page_two_graphs_with_dynamic_data") + @pytest.mark.parametrize( + "test_column ,test_selector", + [ + ("continent", vm.Checklist(options=["Africa", "Europe"])), + ("continent", vm.Dropdown(options=["Africa", "Europe"])), + ("continent", vm.Dropdown(multi=False, options=["Africa", "Europe"])), + ("continent", vm.RadioItems(options=["Africa", "Europe"])), + ("pop", vm.Slider(min=2002)), + ("pop", vm.Slider(max=2007)), + ("pop", vm.Slider(min=2002, max=2007)), + ("pop", vm.RangeSlider(min=2002)), + ("pop", vm.RangeSlider(max=2007)), + ("pop", vm.RangeSlider(min=2002, max=2007)), + ], + ) + def test_filter_is_not_dynamic_with_options_min_max_specified( + self, test_column, test_selector, gapminder_dynamic_first_n_last_n_function + ): + data_manager["gapminder_dynamic_first_n_last_n"] = gapminder_dynamic_first_n_last_n_function + filter = vm.Filter(column=test_column, selector=test_selector) + model_manager["test_page"].controls = [filter] + filter.pre_build() + assert not filter._dynamic + assert not filter.selector._dynamic + @pytest.mark.parametrize("selector", [vm.Slider, vm.RangeSlider]) def test_numerical_min_max_default(self, selector, gapminder, managers_one_page_two_graphs): filter = vm.Filter(column="lifeExp", selector=selector()) @@ -500,18 +821,19 @@ def build(self): assert default_action.actions[0].id == f"filter_action_{filter.id}" -@pytest.mark.usefixtures("managers_one_page_two_graphs") class TestFilterBuild: """Tests filter build method.""" + @pytest.mark.usefixtures("managers_one_page_two_graphs") @pytest.mark.parametrize( - "test_column,test_selector", + "test_column ,test_selector", [ ("continent", vm.Checklist()), ("continent", vm.Dropdown()), + ("continent", vm.Dropdown(multi=False)), ("continent", vm.RadioItems()), - ("pop", vm.RangeSlider()), ("pop", vm.Slider()), + ("pop", vm.RangeSlider()), ("year", vm.DatePicker()), ("year", vm.DatePicker(range=False)), ], @@ -525,3 +847,47 @@ def test_filter_build(self, test_column, test_selector): expected = test_selector.build() assert_component_equal(result, expected) + + @pytest.mark.usefixtures("managers_one_page_two_graphs_with_dynamic_data") + @pytest.mark.parametrize( + "test_column, test_selector", + [ + ("continent", vm.Checklist()), + ("continent", vm.Dropdown()), + ("continent", vm.Dropdown(multi=False)), + ("continent", vm.RadioItems()), + ("pop", vm.Slider()), + ("pop", vm.RangeSlider()), + ], + ) + def test_dynamic_filter_build(self, test_column, test_selector, gapminder_dynamic_first_n_last_n_function): + # Adding dynamic data_frame to data_manager + data_manager["gapminder_dynamic_first_n_last_n"] = gapminder_dynamic_first_n_last_n_function + filter = vm.Filter(id="filter_id", column=test_column, selector=test_selector) + model_manager["test_page"].controls = [filter] + filter.pre_build() + + result = filter.build() + expected = dcc.Loading( + id="filter_id", + children=test_selector.build(), + color="grey", + overlay_style={"visibility": "visible"}, + ) + + assert_component_equal(result, expected, keys_to_strip={"className"}) + + @pytest.mark.usefixtures("managers_one_page_two_graphs_with_dynamic_data") + def test_dynamic_filter_build_with_non_dynamic_selectors(self, gapminder_dynamic_first_n_last_n_function): + # Adding dynamic data_frame to data_manager + data_manager["gapminder_dynamic_first_n_last_n"] = gapminder_dynamic_first_n_last_n_function + + test_selector = vm.DatePicker() + filter = vm.Filter(column="year", selector=test_selector) + model_manager["test_page"].controls = [filter] + filter.pre_build() + + result = filter.build() + expected = test_selector.build() + + assert_component_equal(result, expected) From 1dfd454429fd8fcf1e4f756e2db0c093e8a431bf Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Tue, 3 Dec 2024 16:19:42 +0000 Subject: [PATCH 50/54] Small fixes --- .../pages/tutorials/explore-components.md | 4 +- .../docs/pages/user-guides/selectors.md | 87 ------------------- 2 files changed, 2 insertions(+), 89 deletions(-) diff --git a/vizro-core/docs/pages/tutorials/explore-components.md b/vizro-core/docs/pages/tutorials/explore-components.md index 12899b3f9..a770dacf1 100644 --- a/vizro-core/docs/pages/tutorials/explore-components.md +++ b/vizro-core/docs/pages/tutorials/explore-components.md @@ -496,9 +496,9 @@ The code below illustrates a functional dashboard where you can navigate from th ), ], ) - ``` - ```python + ... + dashboard = vm.Dashboard(pages=[home_page, first_page, second_page]) ``` diff --git a/vizro-core/docs/pages/user-guides/selectors.md b/vizro-core/docs/pages/user-guides/selectors.md index f9a3653a3..a1bd4be20 100644 --- a/vizro-core/docs/pages/user-guides/selectors.md +++ b/vizro-core/docs/pages/user-guides/selectors.md @@ -42,90 +42,3 @@ For more information, refer to the API reference of the selector, or the documen When the [`DatePicker`][vizro.models.DatePicker] is configured with `range=True` (the default), the underlying component is `dmc.DateRangePicker`. When `range=False` the underlying component is `dmc.DatePicker`. When configuring the [`DatePicker`][vizro.models.DatePicker] make sure to provide your dates for `min`, `max` and `value` arguments in `"yyyy-mm-dd"` format or as `datetime` type (for example, `datetime.datetime(2024, 01, 01)`). - -## Default selectors - -If you don't specify a selector, a default selector is applied based on the data type of the provided column. - -Default selectors for: - -- categorical data: [`Dropdown`][vizro.models.Dropdown] -- numerical data: [`RangeSlider`][vizro.models.RangeSlider] -- temporal data: [`DatePicker(range=True)`][vizro.models.DatePicker] - -Categorical selectors can be used independently of the data type of the column being filtered. - -To use numerical [`Filter`][vizro.models.Filter] selectors, the filtered column must be of `numeric` format, indicating that [pandas.api.types.is_numeric_dtype()](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_numeric_dtype.html) must return `True` for the filtered column. - -To use temporal [`Filter`][vizro.models.Filter] selectors, the filtered column must be of `datetime` format, indicating that [pandas.api.types.is_datetime64_any_dtype()](https://pandas.pydata.org/docs/reference/api/pandas.api.types.is_datetime64_any_dtype.html) must return `True` for the filtered column. - -`pd.DataFrame` column types can be changed to `datetime` using [pandas.to_datetime()](https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html) or - -### Example of default Filter selectors - -!!! example "Default Filter selectors" - === "app.py" - ```{.python pycafe-link} - import pandas as pd - from vizro import Vizro - import vizro.plotly.express as px - import vizro.models as vm - - df_stocks = px.data.stocks(datetimes=True) - - df_stocks_long = pd.melt( - df_stocks, - id_vars='date', - value_vars=['GOOG', 'AAPL', 'AMZN', 'FB', 'NFLX', 'MSFT'], - var_name='stocks', - value_name='value' - ) - - df_stocks_long['value'] = df_stocks_long['value'].round(3) - - page = vm.Page( - title="My first page", - components=[ - vm.Graph(figure=px.line(df_stocks_long, x="date", y="value", color="stocks")), - ], - controls=[ - vm.Filter(column="stocks"), - vm.Filter(column="value"), - vm.Filter(column="date"), - ], - ) - - dashboard = vm.Dashboard(pages=[page]) - - Vizro().build(dashboard).run() - ``` - - === "app.yaml" - ```yaml - # Still requires a .py to add data to the data manager and parse YAML configuration - # See yaml_version example - pages: - - components: - - figure: - _target_: line - data_frame: df_stocks_long - x: date - y: value - color: stocks - type: graph - controls: - - column: stocks - type: filter - - column: value - type: filter - - column: date - type: filter - title: My first page - ``` - - === "Result" - [![Filter]][filter] - -To enhance existing selectors, see our [how-to-guide on creating custom components](custom-components.md). - -[filter]: ../../assets/user_guides/selectors/default_filter_selectors.png From 8c9128c33b4e31343492ea654953d17c16b7eee7 Mon Sep 17 00:00:00 2001 From: petar-qb Date: Tue, 3 Dec 2024 22:21:13 +0100 Subject: [PATCH 51/54] Minor fixes for vizro-ai docs --- .../add-generated-chart-usecase.md | 85 +++++----- .../pages/user-guides/customize-vizro-ai.md | 32 ++-- .../user-guides/run-vizro-ai-dashboard.md | 3 +- .../user-guides/vizro-ai-langchain-guide.md | 154 +++++++++--------- 4 files changed, 136 insertions(+), 138 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index deb3e9559..829c4e1f8 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -11,36 +11,36 @@ This guide explains the different ways in which you can add a chart generated by !!! example "Vizro-AI chart" === "Code for the cell" - ```python - import vizro_ai - from vizro_ai import VizroAI - import vizro.plotly.express as px - from dotenv import load_dotenv - - load_dotenv() - - df = px.data.gapminder() - vizro_ai = VizroAI(model="gpt-4o") - - result = vizro_ai.plot( - df, - """Plot a bubble chart to show the changes in life expectancy - and GDP per capita for each country over time. - Color the bubbles by continent. - Add animation on yearly basis, and do not use facets. - Put the legend on top""", - return_elements=True, - ) - - print(f"Insight:\n{result.chart_insights}\n") - print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n") - result.get_fig_object(df).show() - ``` + ```python + import vizro_ai + from vizro_ai import VizroAI + import vizro.plotly.express as px + from dotenv import load_dotenv + + load_dotenv() + + df = px.data.gapminder() + vizro_ai = VizroAI(model="gpt-4o") + + result = vizro_ai.plot( + df, + """Plot a bubble chart to show the changes in life expectancy + and GDP per capita for each country over time. + Color the bubbles by continent. + Add animation on yearly basis, and do not use facets. + Put the legend on top""", + return_elements=True, + ) + + print(f"Insight:\n{result.chart_insights}\n") + print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n") + result.get_fig_object(df).show() + ``` === "Result" [![VizroAIChart]][vizroaichart] -1. Insert the resulting chart into a dashboard. +2. Insert the resulting chart into a dashboard. Once you are satisfied with the chart, you can add it to a [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard. @@ -99,11 +99,12 @@ The `custom_chart` function is an example of the [custom chart](https://vizro.re title = 'Demographics', components = [ vm.Graph(figure=custom_chart(df)), - vm.Graph(figure = px.box(df, - x='continent', - y='lifeExp', - color='continent', - title='Life Expectancy per Continent'))], + vm.Graph( + figure=px.box( + df, x='continent', y='lifeExp', color='continent', title='Life Expectancy per Continent' + ) + ) + ], controls = [ vm.Filter(column='country'), vm.Filter(column='continent')]) @@ -136,21 +137,23 @@ Executing the code below yields the identical dashboard as the example above. vizro_ai = VizroAI(model="gpt-4o") fig = vizro_ai.plot(df, - """Plot a bubble chart to show the changes in life expectancy - and GDP per capita for each country over time. - Color the bubbles by continent. - Add animation on yearly basis, and do not use facets. - Put the legend on top""") + """Plot a bubble chart to show the changes in life expectancy + and GDP per capita for each country over time. + Color the bubbles by continent. + Add animation on yearly basis, and do not use facets. + Put the legend on top""" + ) page = vm.Page( title = 'Demographics', components = [ vm.Graph(figure=fig), - vm.Graph(figure = px.box(df, - x='continent', - y='lifeExp', - color='continent', - title='Life Expectancy per Continent'))], + vm.Graph( + figure=px.box( + df, x='continent', y='lifeExp', color='continent', title='Life Expectancy per Continent' + ) + ) + ], controls = [ vm.Filter(column='country'), vm.Filter(column='continent')]) diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index 4ae23abad..44ed549db 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -19,24 +19,24 @@ vizro_ai = VizroAI(model="") === "OpenAI" -| Environment variable | Name(s) | -| -------------------- | ----------------- | -| API key | `OPENAI_API_KEY` | -| Base API URL | `OPENAI_API_BASE` | + | Environment variable | Name(s) | + | -------------------- | ----------------- | + | API key | `OPENAI_API_KEY` | + | Base API URL | `OPENAI_API_BASE` | -To use OpenAI with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the OpenAI models and pricing on their website](https://platform.openai.com/docs/models). Before using a model, please review OpenAI's guidelines on risk mitigation to understand potential model limitations and best practices. [See the OpenAI site for more details on responsible usage](https://platform.openai.com/docs/guides/safety-best-practices). + To use OpenAI with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the OpenAI models and pricing on their website](https://platform.openai.com/docs/models). Before using a model, please review OpenAI's guidelines on risk mitigation to understand potential model limitations and best practices. [See the OpenAI site for more details on responsible usage](https://platform.openai.com/docs/guides/safety-best-practices). -- `gpt-4o-mini` **default** -- `gpt-4-turbo` -- `gpt-4o` + - `gpt-4o-mini` **default** + - `gpt-4-turbo` + - `gpt-4o` === "Anthropic" _Currently works only for `VizroAI.plot` - we are working on making it available for `VizroAI.dashboard`_ - | Env variable | Name(s) | - | ------------ | ---------------------------------------- | - | API key | `ANTHROPIC_API_KEY` | - | Base API URL | `ANTHROPIC_API_URL`,`ANTHROPIC_BASE_URL` | + | Environment variable | Name(s) | + | -------------------- | ---------------------------------------- | + | API key | `ANTHROPIC_API_KEY` | + | Base API URL | `ANTHROPIC_API_URL`,`ANTHROPIC_BASE_URL` | To use Anthropic with Vizro-AI, you must have an account with paid-for credits available. None of the free accounts will suffice. [Check the Anthropic models and pricing on their website](https://docs.anthropic.com/en/docs/about-claude/models). Before using a model, please review Anthropic guidelines on risk mitigation to understand potential model limitations and best practices. [See the Anthropic site for more details on responsible usage](https://support.anthropic.com/en/collections/4078535-trust-safety/). @@ -54,10 +54,10 @@ To use OpenAI with Vizro-AI, you must have an account with paid-for credits avai === "MistralAI" _Currently works only for `VizroAI.plot` - we are working on making it available for `VizroAI.dashboard`_ - | Env variable | Name(s) | - | ------------ | ------------------ | - | API key | `MISTRAL_API_KEY` | - | Base API URL | `MISTRAL_BASE_URL` | + | Environment variable | Name(s) | + | -------------------- | ------------------ | + | API key | `MISTRAL_API_KEY` | + | Base API URL | `MISTRAL_BASE_URL` | To use Mistral with Vizro-AI, you can either use their API, which comes with [an associated cost](https://mistral.ai/technology/#pricing), or you could use their models for free under the Apache 2.0 license. In that case you need to setup the model API yourself. You can check [all available Mistral models including pricing on their website](https://docs.mistral.ai/getting-started/models/models_overview). This will also explain which version the below string acronyms currently point to. Before usage, please review Mistral guidelines on risk mitigation to understand potential model limitations and best practices. [See the Mistral site for more details on responsible usage](https://help.mistral.ai/en/collections/272960-le-chat/). diff --git a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md index c47ee303d..f9d5944c9 100644 --- a/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md +++ b/vizro-ai/docs/pages/user-guides/run-vizro-ai-dashboard.md @@ -34,8 +34,7 @@ This guide offers insights into different ways of running `VizroAI.dashboard` to ``` === "Result" - - ![VizroAIDashboardPage1](../../assets/user_guides/dashboard/dashboard2_page1.png) + ![VizroAIDashboardPage1](../../assets/user_guides/dashboard/dashboard2_page1.png) This triggers the dashboard building process. Once Vizro-AI finishes the dashboard generation process, you can now launch the dashboard. diff --git a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md index 75a67dd07..f5789d537 100644 --- a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md +++ b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md @@ -115,93 +115,89 @@ chain = llm_with_tools | inject_df | tool_router.map() Now you can use the chain to generate charts or dashboards based on natural language queries. The chain will generate code that you can use to create visualizations. -!!! example "Generate chart code" - === "Code" - ```python - # Load sample data - df = px.data.gapminder() +!!! example "Generate chart code" - plot_response = chain.invoke("Plot GDP per capita for each continent") - print(plot_response[0].content) - ``` + === "Code" + ```python + # Load sample data + df = px.data.gapminder() + plot_response = chain.invoke("Plot GDP per capita for each continent") + print(plot_response[0].content) + ``` === "Vizro-AI Generated Code" - - ```python - import plotly.graph_objects as go - from vizro.models.types import capture - - - @capture("graph") - def custom_chart(data_frame): - continent_gdp = data_frame.groupby("continent")["gdpPercap"].mean().reset_index() - fig = go.Figure(data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])]) - fig.update_layout( - title="GDP per Capita by Continent", - xaxis_title="Continent", - yaxis_title="GDP per Capita", - ) - return fig - ``` + ```python + import plotly.graph_objects as go + from vizro.models.types import capture + + @capture("graph") + def custom_chart(data_frame): + continent_gdp = data_frame.groupby("continent")["gdpPercap"].mean().reset_index() + fig = go.Figure( + data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])] + ) + fig.update_layout( + title="GDP per Capita by Continent", + xaxis_title="Continent", + yaxis_title="GDP per Capita", + ) + return fig + ``` !!! example "Generate dashboard code" - === "Code" - ```python - dfs = [px.data.gapminder()] - - dashboard_response = chain.invoke( - "Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp." - ) - print(dashboard_response[0].content) - ``` + === "Code" + ```python + dfs = [px.data.gapminder()] + dashboard_response = chain.invoke("Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp.") + print(dashboard_response[0].content) + ``` === "Vizro-AI Generated Code" - - ```py - ############ Imports ############## - import vizro.models as vm - from vizro.models.types import capture - import plotly.graph_objects as go - - - ####### Function definitions ###### - @capture("graph") - def gdp_life_exp_graph(data_frame): - fig = go.Figure() - fig.add_trace( - go.Scatter(x=data_frame["gdpPercap"], y=data_frame["lifeExp"], mode="markers") - ) - fig.update_layout( + ```python + ############ Imports ############## + import vizro.models as vm + from vizro.models.types import capture + import plotly.graph_objects as go + + + ####### Function definitions ###### + @capture("graph") + def gdp_life_exp_graph(data_frame): + fig = go.Figure() + fig.add_trace( + go.Scatter(x=data_frame["gdpPercap"], y=data_frame["lifeExp"], mode="markers") + ) + fig.update_layout( + title="GDP per Capita vs Life Expectancy", + xaxis_title="GDP per Capita", + yaxis_title="Life Expectancy", + ) + return fig + + + ####### Data Manager Settings ##### + #######!!! UNCOMMENT BELOW !!!##### + # from vizro.managers import data_manager + # data_manager["gdp_life_exp"] = ===> Fill in here <=== + + + ########### Model code ############ + model = vm.Dashboard( + pages=[ + vm.Page( + components=[ + vm.Graph( + id="gdp_life_exp_graph", + figure=gdp_life_exp_graph(data_frame="gdp_life_exp"), + ) + ], + title="GDP vs Life Expectancy Correlation", + layout=vm.Layout(grid=[[0]]), + controls=[], + ) + ], title="GDP per Capita vs Life Expectancy", - xaxis_title="GDP per Capita", - yaxis_title="Life Expectancy", ) - return fig - - - ####### Data Manager Settings ##### - #######!!! UNCOMMENT BELOW !!!##### - # from vizro.managers import data_manager - # data_manager["gdp_life_exp"] = ===> Fill in here <=== - - - ########### Model code ############ - model = vm.Dashboard( - pages=[ - vm.Page( - components=[ - vm.Graph( - id="gdp_life_exp_graph", - figure=gdp_life_exp_graph(data_frame="gdp_life_exp"), - ) - ], - title="GDP vs Life Expectancy Correlation", - layout=vm.Layout(grid=[[0]]), - controls=[], - ) - ], - title="GDP per Capita vs Life Expectancy", - ) - ``` + ``` From f3e4cabf079975e632a93fe122da7bcd4dad12b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 21:21:43 +0000 Subject: [PATCH 52/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../user-guides/add-generated-chart-usecase.md | 13 ++++++------- .../pages/user-guides/customize-vizro-ai.md | 1 - .../user-guides/vizro-ai-langchain-guide.md | 18 ++++++++---------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index 829c4e1f8..60eb24100 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -10,18 +10,17 @@ This guide explains the different ways in which you can add a chart generated by !!! example "Vizro-AI chart" === "Code for the cell" - ```python import vizro_ai from vizro_ai import VizroAI import vizro.plotly.express as px from dotenv import load_dotenv - + load_dotenv() - + df = px.data.gapminder() vizro_ai = VizroAI(model="gpt-4o") - + result = vizro_ai.plot( df, """Plot a bubble chart to show the changes in life expectancy @@ -30,8 +29,8 @@ This guide explains the different ways in which you can add a chart generated by Add animation on yearly basis, and do not use facets. Put the legend on top""", return_elements=True, - ) - + ) + print(f"Insight:\n{result.chart_insights}\n") print(f"Code explanation:\n{result.code_explanation}\n\nCode:\n{result.code_vizro}\n") result.get_fig_object(df).show() @@ -40,7 +39,7 @@ This guide explains the different ways in which you can add a chart generated by === "Result" [![VizroAIChart]][vizroaichart] -2. Insert the resulting chart into a dashboard. +1. Insert the resulting chart into a dashboard. Once you are satisfied with the chart, you can add it to a [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard. diff --git a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md index 44ed549db..03f35cbe5 100644 --- a/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md +++ b/vizro-ai/docs/pages/user-guides/customize-vizro-ai.md @@ -18,7 +18,6 @@ vizro_ai = VizroAI(model="") For the string settings to work, you must supply your API key via environment variables. The relevant variable names to be set are noted in each vendor tab. === "OpenAI" - | Environment variable | Name(s) | | -------------------- | ----------------- | | API key | `OPENAI_API_KEY` | diff --git a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md index f5789d537..b43653356 100644 --- a/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md +++ b/vizro-ai/docs/pages/user-guides/vizro-ai-langchain-guide.md @@ -115,9 +115,7 @@ chain = llm_with_tools | inject_df | tool_router.map() Now you can use the chain to generate charts or dashboards based on natural language queries. The chain will generate code that you can use to create visualizations. - !!! example "Generate chart code" - === "Code" ```python # Load sample data @@ -126,17 +124,17 @@ Now you can use the chain to generate charts or dashboards based on natural lang plot_response = chain.invoke("Plot GDP per capita for each continent") print(plot_response[0].content) ``` + === "Vizro-AI Generated Code" ```python import plotly.graph_objects as go from vizro.models.types import capture + @capture("graph") def custom_chart(data_frame): continent_gdp = data_frame.groupby("continent")["gdpPercap"].mean().reset_index() - fig = go.Figure( - data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])] - ) + fig = go.Figure(data=[go.Bar(x=continent_gdp["continent"], y=continent_gdp["gdpPercap"])]) fig.update_layout( title="GDP per Capita by Continent", xaxis_title="Continent", @@ -146,14 +144,16 @@ Now you can use the chain to generate charts or dashboards based on natural lang ``` !!! example "Generate dashboard code" - === "Code" ```python dfs = [px.data.gapminder()] - dashboard_response = chain.invoke("Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp.") + dashboard_response = chain.invoke( + "Create a dashboard. This dashboard has a chart showing the correlation between gdpPercap and lifeExp." + ) print(dashboard_response[0].content) ``` + === "Vizro-AI Generated Code" ```python ############ Imports ############## @@ -166,9 +166,7 @@ Now you can use the chain to generate charts or dashboards based on natural lang @capture("graph") def gdp_life_exp_graph(data_frame): fig = go.Figure() - fig.add_trace( - go.Scatter(x=data_frame["gdpPercap"], y=data_frame["lifeExp"], mode="markers") - ) + fig.add_trace(go.Scatter(x=data_frame["gdpPercap"], y=data_frame["lifeExp"], mode="markers")) fig.update_layout( title="GDP per Capita vs Life Expectancy", xaxis_title="GDP per Capita", From 61f2b3914fce73e572dfb3b940a1bf21ceeb08f7 Mon Sep 17 00:00:00 2001 From: petar-qb Date: Tue, 3 Dec 2024 22:32:18 +0100 Subject: [PATCH 53/54] Minor change --- vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index 60eb24100..cb9794887 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -39,7 +39,7 @@ This guide explains the different ways in which you can add a chart generated by === "Result" [![VizroAIChart]][vizroaichart] -1. Insert the resulting chart into a dashboard. +2. Insert the resulting chart into a dashboard. Once you are satisfied with the chart, you can add it to a [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard. From 64609ce8733054b7d1240344b0a94d6c842a7592 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 21:32:45 +0000 Subject: [PATCH 54/54] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md index cb9794887..60eb24100 100644 --- a/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md +++ b/vizro-ai/docs/pages/user-guides/add-generated-chart-usecase.md @@ -39,7 +39,7 @@ This guide explains the different ways in which you can add a chart generated by === "Result" [![VizroAIChart]][vizroaichart] -2. Insert the resulting chart into a dashboard. +1. Insert the resulting chart into a dashboard. Once you are satisfied with the chart, you can add it to a [Vizro](https://github.com/mckinsey/vizro/tree/main/vizro-core) dashboard.