diff --git a/README.md b/README.md index c8e44862..2a7d9447 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ | | | | --- | --- | -| Build Status | [![Linux/MacOS/Windows Build Status](https://github.com/holoviz/lumen/workflows/pytest/badge.svg)](https://github.com/holoviz/lumen/actions/workflows/test.yml) +| Build Status | [![Linux/MacOS/Windows Build Status](https://github.com/holoviz/lumen/actions/workflows/test.yaml/badge.svg)](https://github.com/holoviz/lumen/actions/workflows/test.yaml) | Coverage | [![codecov](https://codecov.io/gh/holoviz/lumen/branch/main/graph/badge.svg)](https://codecov.io/gh/holoviz/lumen) | | Latest dev release | [![Github tag](https://img.shields.io/github/v/tag/holoviz/lumen.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/lumen/tags) [![dev-site](https://img.shields.io/website-up-down-green-red/https/holoviz-dev.github.io/lumen.svg?label=dev%20website)](https://holoviz-dev.github.io/lumen/) | | Latest release | [![Github release](https://img.shields.io/github/release/holoviz/lumen.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/lumen/releases) [![PyPI version](https://img.shields.io/pypi/v/lumen.svg?colorB=cc77dd)](https://pypi.python.org/pypi/lumen) [![lumen version](https://img.shields.io/conda/v/pyviz/lumen.svg?colorB=4488ff&style=flat)](https://anaconda.org/pyviz/lumen) [![conda-forge version](https://img.shields.io/conda/v/conda-forge/lumen.svg?label=conda%7Cconda-forge&colorB=4488ff)](https://anaconda.org/conda-forge/lumen) [![defaults version](https://img.shields.io/conda/v/anaconda/lumen.svg?label=conda%7Cdefaults&style=flat&colorB=4488ff)](https://anaconda.org/anaconda/lumen) | @@ -36,12 +36,13 @@ The core strengths of Lumen include: NYC Taxi
- Palmer Penguins
- Precipitation
+ Palmer Penguins
+ USGS Earthquakes
+ + + Seattle Weather
+ Windturbines
- - Seattle Weather
- ## Getting started diff --git a/doc/_static/custom.css b/doc/_static/custom.css index f56d30fe..186c9990 100644 --- a/doc/_static/custom.css +++ b/doc/_static/custom.css @@ -3,6 +3,16 @@ --pst-color-link: deeppink; } +@media (min-width: 960px) { + .bd-page-width { + max-width: 132rem; + } +} + +.bd-main .bd-content .bd-article-container { + max-width: 88rem; +} + .navbar-light { background-color: #fff !important; box-shadow: 0 0.125rem 0.25rem 0 rgb(0 0 0 / 11%); diff --git a/doc/_static/diagram.png b/doc/_static/diagram.png index 5200a7f7..c33ba656 100644 Binary files a/doc/_static/diagram.png and b/doc/_static/diagram.png differ diff --git a/doc/_static/diagram.svg b/doc/_static/diagram.svg index 63fa3171..5be55d86 100644 --- a/doc/_static/diagram.svg +++ b/doc/_static/diagram.svg @@ -1,184 +1,192 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - Source - - - - Filter - View - - - - - - - - - - - - - - - - - - - - - - - - - - Transform - - image/svg+xmlSourceFilterView - Data Viz - - - - - - - - - - - - - - - - - - - - - - - Data Pipeline - - - + xlink:href="data:image/png;base64,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 AElFTkSuQmCC " + id="image15794" + x="295.17651" + y="-72.391197" + style="stroke:#0072b5;stroke-opacity:1" />TransformData VizData PipelinePanel diff --git a/doc/getting_started/pipelines.md b/doc/getting_started/pipelines.md index 3c89c847..bba2edea 100644 --- a/doc/getting_started/pipelines.md +++ b/doc/getting_started/pipelines.md @@ -1,5 +1,13 @@ # {octicon}`git-commit;2em;sd-mr-1` Building a data pipeline + +```{pyodide} +import lumen +import panel as pn + +pn.extension('tabulator') +``` + Lumen dashboards are a powerful, declarative way to write data-driven applications and dashboards. However Lumen components also provide a powerful abstraction that can be leveraged independently of a full dashboard YAML specification. Specifically the `Pipeline` component offers an extremely powerful basis for building data transformations that can either be used to power analysis pipelines or to drive visual components we can render in a notebook or a custom Panel dashboard. In this section we will discover how to leverage pipelines in this way. First however we need to understand how Pipelines work, specifically the order in which operations are applied. In particular we need to distinguish between operations that are applied by the `Source` and operations that are applied to **data** returned by the `Source`. This is because various `Source` types support data queries and in the case of SQL based `Source` may also support arbitrary SQL transforms. This means that the `Pipeline` will first call the `Source.get` method with state of the `Filter` and `SQLTransform` components allowing the `Source` to optimize the filter queries and transforms and return the data, once the data is returned as a `DataFrame` the declared `Transform` stages will be applied in sequence. diff --git a/doc/how_to/data_visualization/dashboard_python.md b/doc/how_to/data_visualization/dashboard_python.md index 02b45aff..624fb4a6 100644 --- a/doc/how_to/data_visualization/dashboard_python.md +++ b/doc/how_to/data_visualization/dashboard_python.md @@ -8,7 +8,7 @@ To start with let us declare the [Pipeline](lumen.pipeline.Pipeline) we will be import lumen as lm import panel as pn -pn.extension('tabulator') +pn.extension('tabulator', design='material') pipeline = lm.Pipeline.from_spec({ 'source': { diff --git a/doc/user_guide/dashboard.md b/doc/user_guide/dashboard.md deleted file mode 100644 index a5395995..00000000 --- a/doc/user_guide/dashboard.md +++ /dev/null @@ -1,230 +0,0 @@ -# Dashboard Specification - -The Lumen dashboard can be configured using a `dashboard.yml` file. The core design principle behind the yaml specification is that it instantiates instances of the four main types, i.e. [Filter](lumen.filters.Filter), [Source](lumen.sources.Source), [Transform](lumen.transforms.Transform) and [View](lumen.views.View) objects. - -For example the `type` declaration of a `Source` is matched against`source_type` and all the other keywords are passed as arguments to the class, instantiating the object with the provided configuration. - -## Sections - -We will start by breaking down the specification into individual sections. - -### `config` - -The `config` section provides general settings which apply to the whole dashboard. - -```yaml -config: - title: The title of the overall application - layout: The layout to arrange the (sub-)layouts in ('grid', 'tabs', 'column') - logo: A URL or local path to an image file - sync_with_url: Whether to sync app state with URL - template: The template to use for the monitoring application - ncols: The number of columns to use in the grid of cards -``` - -A simple example `config` might look like this: - -```yaml -config: - title: "Example Application" - layout: grid - logo: example.png - ncols: 3 -``` - -### `defaults` - -The `defaults` section allows overriding parameter defaults on the [Filter](lumen.filters.Filter), [Source](lumen.sources.Source), [Transform](lumen.transforms.Transform) and [View](lumen.views.View) objects. - -```yaml -defaults: - filters: - - type: Type to override the default on - ...: Parameter to override - sources: - - type: Type to override the default on - ...: Parameter to override - transforms: - - type: Type to override the default on - ...: Parameter to override - views: - - type: Type to override the default on - ...: Parameter to override -``` - -As an example we may want to override the default `WidgetFilter.multi` value, because we want to query with a specific value rather than multiple values: - -```yaml -defaults: - filters: - - type: widget - multi: false -``` - -### `variables` - -Variables are powerful components for declaring values that you want to use throughout your application by referencing throughout the YAML. - - -```yaml -variables: - user: - - type: url - password: - - type: env - key: MY_PASSWORD_ENV_VAR -``` - -Once declared variables can be referenced through the rest of your dashboard specification by using the reference syntax (`$`) described below. - -### `sources` - -The `sources` section allows defining [Source](lumen.sources.Source) instances which can be referenced by the pipelines. - -```yaml -sources: - - type: The type of Source to instantiate - ...: Additional parameters for the Source -``` - -As an example we may want to load a table of population data from a local CSV file using the [FileSource](lumen.sources.FileSource): - -```yaml -sources: - population: - type: file - files: [population.csv] -``` - -This will declare a `Source` called `population` which publishes a table called `population`. - -It is also possible to declare filters associated with a global `Source`. - -```yaml -sources: - population: - type: file - files: [population.csv] -``` - -### `pipelines` - -The `pipelines` section allows declaring reusable pipelines that encapsulate a [Source](lumen.sources.Source) along with any number of [Filter](lumen.filters.Filter) and [Transform](lumen.transforms.Transform) components. A pipeline can be declared in this global section or the definition can be inlined on each Layout or View. - -```yaml -pipelines: - population: - source: population - filters: - - type: widget - field: country - transforms: - - type: columns - columns: [year, country, population] -``` - -### `layouts` - -The layouts section defines the actual visual representations on the page and therefore makes up the meat of the declaration. - -```yaml -layouts: This is the list of visual layouts to render. - - title: The title of the monitoring endpoint - download: - format: When specified adds a section to the sidebar allowing users to download the filtered dataset - kwargs: Additional keyword arguments to pass to the pandas/dask to_ method - tables: Allows declaring a subset of tables to download - pipeline: The pipeline driving the views of this layout. Each View can independently declare a pipeline or all use the shared pipeline defined at the layout level - views: A list of metrics to monitor and display on the endpoint - - pipeline: The Pipeline driving the View - type: The type of View to use for rendering the table - ...: Additional parameters for the View - layout: The layout inside the card(s), e.g. 'row', 'column' or 'grid' - facet: - by: List of fields to facet by - sort: List of fields to sort by - reverse: Whether to reverse the sort order - refresh_rate: How frequently to poll for updates in milliseconds - ...: Additional parameters passed to the Card layout(s), e.g. width or height -``` - -### `auth` - -The `auth` field may provide a dictionary of any number of fields which are validated against the user information provided the the Auth provider, which is made available by Panel in the `panel.state.user_info` dictionary. To discover how to configure an Auth provider with Panel/Lumen see the [Panel documentation](https://panel.holoviz.org/user_guide/Authentication.html). - -As an example the GitHub OAuth provider returns the login of the user that is visiting the dashboard. If we add the following field to the yaml: - -```yaml -auth: - login: [philippjfr] -``` - -Lumen will check the current user `login` against all user logins listed here. For a more generic Auth mechanism many Auth providers, such as Okta, make it possible to configure a list of groups a user belongs to in which case you could list the allowed groups in the auth field. - -## Special Syntax - -To avoid repeating yourself the yaml specification supports some special syntax. - -### References - -#### Source References - -In some scenarios you might want to refer to a `Source`, a table on a `Source` or a field on a table from elsewhere in the yaml specification. - -As an example you may have local CSV file which contains a column of URLs to monitor and feed that information to a `WebsiteSource` which reports whether those URLs are live. Using the `$` syntax we can easily establish such references. - -```yaml -sources: - csv: - type: file - files: [websites.csv] - live: - type: live - urls: "$csv.websites.url" -``` - -The `$csv.websites.url` syntax will look up a `Source` called 'csv', request a table called 'websites' and then feed the 'url' column in that table to the `urls` parameter of the `WebsiteSource`. - -### Variable References - -Variables are powerful components that allow you to link settings across your entire application. Once a `Variable` has been declared in the `variables:` section of the specification you can reference it throughout your application using the `$variables.` syntax, e.g. you might have a `url` widget `Variable` that allows entering a URL using a `TextInput` widget: - -```yaml -variables: - url: - type: widget - kind: TextInput - default: AAPL.csv -``` - -Once declared you can reference this variable using the `$variables.` syntax: - -```yaml -sources: - stock_data: - type: file - tables: - ticker: $variables.url -``` - -Whenever the `url` variable is updated the `Source` will be refreshed and any views attached to that `Source` will be updated. - -### Templating - -In many cases you do not want to hardcode variables inside the yaml specification instead passing in variables from an environment variable, a shell command, a CLI argument, a HTTP request header or cookie, or a OAuth token variable. This can be achieved using the following templating syntax: - -- `{{env("USER")}}`: look in the set environment variables for the named variable - -- `{{shell("get_login thisuser -t")}}`: execute the command, and use the output as the value. The output will be trimmed of any trailing whitespace. - -- `{{cookie("USER")}}`: look in the HTTP request cookies of the served application - -- `{{header("USER")}}`: look in the HTTP request headers of the served application - -- `{{oauth("USER")}}`: look in the OAuth user token - -- `{{USER}}`: Arguments passed in using `--template-vars="{'USER': 'lumen_user'}"` when using `lumen serve` on the commandline. - -## Local components - -While Lumen ships with a wide range of components users may also define custom components in files which live alongside the `dashboard.yml` file. Specifically Lumen will automatically import `filters.py`, `sources.py`, `transforms.py` and `views.py` if these files exist alongside the dashboard specification. diff --git a/doc/user_guide/index.md b/doc/user_guide/index.md deleted file mode 100644 index 5874d2a6..00000000 --- a/doc/user_guide/index.md +++ /dev/null @@ -1,46 +0,0 @@ -# User guide - -::::{grid} 2 2 3 3 -:gutter: 1 - -:::{grid-item-card} {octicon}`browser;2em;sd-mr-1` Dashboards -:link: dashboard -:link-type: doc - -Creating Dashboards with Lumen - -+++ -[Learn more »](dashboard) -::: - -:::{grid-item-card} {octicon}`paper-airplane;2em;sd-mr-1` Pipelines -:link: pipeline -:link-type: doc - -Building Lumen data pipelines - -+++ -[Learn more »](pipeline) -::: - -:::{grid-item-card} {octicon}`server;2em;sd-mr-1` REST Specification -:link: rest -:link-type: doc - -The REST API specification for Lumen - -+++ -[Learn more »](rest) -::: - -:::: - -```{toctree} -:titlesonly: -:hidden: -:maxdepth: 2 - -dashboard -pipeline -rest -``` diff --git a/doc/user_guide/pipeline.md b/doc/user_guide/pipeline.md deleted file mode 100644 index 9d79afdd..00000000 --- a/doc/user_guide/pipeline.md +++ /dev/null @@ -1,5 +0,0 @@ -# Pipelines - -```{eval-rst} -.. notebook:: lumen ../../examples/user_guide/Pipeline.ipynb -``` diff --git a/doc/user_guide/rest.md b/doc/user_guide/rest.md deleted file mode 100644 index 577c55b0..00000000 --- a/doc/user_guide/rest.md +++ /dev/null @@ -1,47 +0,0 @@ -# REST Specification - -The REST specification defines the default format for data to be consumed by the dashboard. The API consists of three main endpoints providing access to the schema - -- `schema`: Publishes a schema for each variable and all its associated indexes, the schema should follow the [JSON schema](https://json-schema.org/) specification: - - - Query: A query may define the variable to return the schema for: - `{'table': }` - - Output: - ``` - { - : { - : {'description': string, 'schema': object, 'label': string}, - : {'description': string, 'schema': object, 'label': string}, - ... - }, - ... - } - ``` - -- `data`: This endpoints returns the actual data, it also allows filtering the data along the columns with query: - - - Query: A query must contain the table to be returned and may optionally provide a subset of columns and filters for the table columns: - `{'table':
, 'columns': [, ...], : , ...}` - - Output: It will always return a list of records containing all the metric and filter values: - ``` - [ - {: , : , ...}, - {: , : , ...}, - ... - ] - ``` - -- `dump`: Returns a complete dump of all data: - - - Query: None - - Output: - ``` - { -
: [ - {: , : , ...}, - {: , : , ...}, - ... - ], - ... - } - ``` diff --git a/examples/gallery/seattle/weather.yaml b/examples/gallery/seattle/weather.yaml index bc513223..024d1bf3 100644 --- a/examples/gallery/seattle/weather.yaml +++ b/examples/gallery/seattle/weather.yaml @@ -1,6 +1,7 @@ config: title: Altair Seattle Weather reloadable: false + sync_with_url: true sources: seattle: type: file diff --git a/lumen/dashboard.py b/lumen/dashboard.py index 2e83a000..441974f8 100644 --- a/lumen/dashboard.py +++ b/lumen/dashboard.py @@ -32,9 +32,7 @@ from .sources.base import RESTSource, Source # noqa from .state import state from .transforms.base import Transform # noqa -from .util import ( - bokeh3, catch_and_notify, expand_spec, resolve_module_reference, -) +from .util import catch_and_notify, expand_spec, resolve_module_reference from .validation import ( ValidationError, match_suggestion_message, validate_callback, ) @@ -735,13 +733,11 @@ def _create_header(self): def _create_main(self): layout_kwargs = {'sizing_mode': 'stretch_width', 'min_height': 400} - if self.config.layout is pn.Tabs and not bokeh3: - layout_kwargs['dynamic'] = True - elif self.config.layout is pn.GridBox: + if self.config.layout is pn.GridBox: layout_kwargs['ncols'] = self.config.ncols self._layout = self.config.layout(**layout_kwargs) styles = {'text-align': 'center', 'font-size': '1.8em', 'font-weight': 'bold'} - style_params = {'styles': styles} if bokeh3 else {'style': styles} + style_params = {'styles': styles} state.loading_msg = pn.pane.HTML( 'Loading...', align='center', width=400, height=400, **style_params ) @@ -1043,8 +1039,8 @@ def layout(self): pn.state.sync_busy(spinner) title_html = f'
{self.config.title}
' - styles = {'background': '#00aa41'} - header_params = dict(styles=styles) if bokeh3 else styles + styles = {'background': '#0072b5'} + header_params = dict(styles=styles) return pn.Column( pn.Row( pn.pane.HTML(title_html, margin=(20, 20), align='center'), @@ -1054,8 +1050,8 @@ def layout(self): **header_params ), pn.Row( - pn.Column(self._sidebar, width=300), - self._layout, + pn.Row(self._sidebar, max_width=320), + pn.Row(self._layout, margin=(5, 5, 5, 20)), sizing_mode='stretch_width' ), sizing_mode='stretch_both'