diff --git a/README.md b/README.md index 6255883..22f4ed9 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,21 @@ To run the tests, do: pytest --ckan-ini=test.ini +## Building the documentation + +We are using `mkdocs` to build the documentation. To build and deploy the documentation, do: + + CHARTS_FIELDS=1 mkdocs build && mkdocs gh-deploy + +We need to set the `CHARTS_FIELDS` for our custom handler, that autogenerate documentation +for chart types fields. + +If you're working on the documentation, you can run the following command to start a live-reloading server without +gathering the chart types fields data. It will speed up the process significantly, as we won't need to wait for the +CKAN initialization: + + mkdocs serve -a 127.0.0.1:8001 + ## License [AGPL](https://www.gnu.org/licenses/agpl-3.0.en.html) diff --git a/docs/install.md b/docs/install.md index cb4ef01..694fd88 100644 --- a/docs/install.md +++ b/docs/install.md @@ -23,7 +23,7 @@ Compatibility with core CKAN versions: pip install ckanext-charts[pyarrow] ``` -2. Enable the main plugin and harvesters you want to use in your CKAN configuration file (e.g. `ckan.ini` or `production.ini`): +2. Enable the view and builder plugins in your CKAN configuration file (e.g. `ckan.ini` or `production.ini`): ```ini ckan.plugins = ... charts_view charts_builder_view ... diff --git a/mkdocstrings_handlers/ChartFieldsHandler/handler.py b/mkdocstrings_handlers/ChartFieldsHandler/handler.py index ceb97ea..37e207e 100644 --- a/mkdocstrings_handlers/ChartFieldsHandler/handler.py +++ b/mkdocstrings_handlers/ChartFieldsHandler/handler.py @@ -1,7 +1,6 @@ from __future__ import annotations import os -import importlib from typing import Mapping, MutableMapping, Any from unittest.mock import patch, MagicMock @@ -19,7 +18,7 @@ class ChartFieldsHandler(BaseHandler): - """Custom handler for documenting the chart engine fields according to the + """Custom handler for documenting different chart types fields according to the form fields schema.""" def collect( self, identifier: str, config: MutableMapping[str, Any] diff --git a/site/404.html b/site/404.html index 7a1d7bb..c127875 100644 --- a/site/404.html +++ b/site/404.html @@ -12,7 +12,7 @@ - + diff --git a/site/assets/_mkdocstrings.css b/site/assets/_mkdocstrings.css index 8b83f70..e03e464 100644 --- a/site/assets/_mkdocstrings.css +++ b/site/assets/_mkdocstrings.css @@ -26,20 +26,33 @@ float: right; } +/* Parameter headings must be inline, not blocks. */ +.doc-heading-parameter { + display: inline; +} + +/* Prefer space on the right, not the left of parameter permalinks. */ +.doc-heading-parameter .headerlink { + margin-left: 0 !important; + margin-right: 0.2rem; +} + /* Backward-compatibility: docstring section titles in bold. */ .doc-section-title { font-weight: bold; } /* Symbols in Navigation and ToC. */ -:root, +:root, :host, [data-md-color-scheme="default"] { + --doc-symbol-parameter-fg-color: #df50af; --doc-symbol-attribute-fg-color: #953800; --doc-symbol-function-fg-color: #8250df; --doc-symbol-method-fg-color: #8250df; --doc-symbol-class-fg-color: #0550ae; --doc-symbol-module-fg-color: #5cad0f; + --doc-symbol-parameter-bg-color: #df50af1a; --doc-symbol-attribute-bg-color: #9538001a; --doc-symbol-function-bg-color: #8250df1a; --doc-symbol-method-bg-color: #8250df1a; @@ -48,12 +61,14 @@ } [data-md-color-scheme="slate"] { + --doc-symbol-parameter-fg-color: #ffa8cc; --doc-symbol-attribute-fg-color: #ffa657; --doc-symbol-function-fg-color: #d2a8ff; --doc-symbol-method-fg-color: #d2a8ff; --doc-symbol-class-fg-color: #79c0ff; --doc-symbol-module-fg-color: #baff79; + --doc-symbol-parameter-bg-color: #ffa8cc1a; --doc-symbol-attribute-bg-color: #ffa6571a; --doc-symbol-function-bg-color: #d2a8ff1a; --doc-symbol-method-bg-color: #d2a8ff1a; @@ -68,6 +83,15 @@ code.doc-symbol { font-weight: bold; } +code.doc-symbol-parameter { + color: var(--doc-symbol-parameter-fg-color); + background-color: var(--doc-symbol-parameter-bg-color); +} + +code.doc-symbol-parameter::after { + content: "param"; +} + code.doc-symbol-attribute { color: var(--doc-symbol-attribute-fg-color); background-color: var(--doc-symbol-attribute-bg-color); diff --git a/site/caching/base/index.html b/site/caching/base/index.html index c8ed579..6c5571e 100644 --- a/site/caching/base/index.html +++ b/site/caching/base/index.html @@ -18,7 +18,7 @@ - + @@ -1071,6 +1071,11 @@

Base Cache Strategy

+ + + + +
@@ -1108,7 +1113,9 @@

- key + + key +

The cache key to retrieve the data.

@@ -1179,7 +1186,9 @@

- key + + key +

The cache key to invalidate.

@@ -1226,7 +1235,9 @@

- key + + key +

The cache key to store the data.

@@ -1240,7 +1251,9 @@

- data + + data +

The data to be stored.

diff --git a/site/caching/file/index.html b/site/caching/file/index.html index f02ae3f..81a530d 100644 --- a/site/caching/file/index.html +++ b/site/caching/file/index.html @@ -18,7 +18,7 @@ - + @@ -1283,6 +1283,11 @@

+ + + + +
@@ -1316,7 +1321,9 @@

- key + + key +

The cache key to generate the filename.

@@ -1383,7 +1390,9 @@

- key + + key +

The cache key to retrieve the data.

@@ -1450,7 +1459,9 @@

- key + + key +

The cache key to invalidate.

@@ -1498,7 +1509,9 @@

- file_path + + file_path +

The path to the file.

@@ -1565,7 +1578,9 @@

- key + + key +

The cache key to generate the file path.

@@ -1636,7 +1651,9 @@

- file + + file +

The file object to read the data.

@@ -1703,7 +1720,9 @@

- key + + key +

The cache key to store the data.

@@ -1717,7 +1736,9 @@

- data + + data +

The data to be stored.

@@ -1764,7 +1785,9 @@

- file_path + + file_path +

The path to the file.

@@ -1778,7 +1801,9 @@

- data + + data +

The data to be stored.

@@ -1827,6 +1852,11 @@

+ + + + +
@@ -1860,7 +1890,9 @@

- file + + file +

The file object to read the data.

@@ -1927,7 +1959,9 @@

- file_path + + file_path +

The path to the file.

@@ -1941,7 +1975,9 @@

- data + + data +

The data to be stored.

@@ -1990,6 +2026,11 @@

+ + + + +
@@ -2023,7 +2064,9 @@

- file + + file +

The file object to read the data.

@@ -2090,7 +2133,9 @@

- file_path + + file_path +

The path to the file.

@@ -2104,7 +2149,9 @@

- data + + data +

The data to be stored.

diff --git a/site/caching/index.html b/site/caching/index.html index 746507b..dbcc622 100644 --- a/site/caching/index.html +++ b/site/caching/index.html @@ -18,7 +18,7 @@ - + diff --git a/site/caching/redis/index.html b/site/caching/redis/index.html index 1a9e285..4474594 100644 --- a/site/caching/redis/index.html +++ b/site/caching/redis/index.html @@ -18,7 +18,7 @@ - + @@ -1024,6 +1024,11 @@

Redis Cache

+ + + + +
@@ -1057,7 +1062,9 @@

- key + + key +

The cache key to retrieve the data.

@@ -1124,7 +1131,9 @@

- key + + key +

The cache key to invalidate.

@@ -1167,7 +1176,9 @@

- key + + key +

The cache key to store the data.

@@ -1181,7 +1192,9 @@

- data + + data +

The data to be stored.

diff --git a/site/configuration/index.html b/site/configuration/index.html index 7043b71..968278e 100644 --- a/site/configuration/index.html +++ b/site/configuration/index.html @@ -18,7 +18,7 @@ - + diff --git a/site/engines/chartjs/index.html b/site/engines/chartjs/index.html index ebe5304..5cc0d9c 100644 --- a/site/engines/chartjs/index.html +++ b/site/engines/chartjs/index.html @@ -18,7 +18,7 @@ - + @@ -1113,6 +1113,11 @@

Chartjs

+ + + + +
Source code in ckanext/charts/chart_builders/chartjs.py
13
diff --git a/site/engines/custom/index.html b/site/engines/custom/index.html
index 18c8a8f..e61066d 100644
--- a/site/engines/custom/index.html
+++ b/site/engines/custom/index.html
@@ -18,7 +18,7 @@
       
       
       
-      
+      
     
     
       
diff --git a/site/engines/index.html b/site/engines/index.html
index e67167d..11c1960 100644
--- a/site/engines/index.html
+++ b/site/engines/index.html
@@ -18,7 +18,7 @@
       
       
       
-      
+      
     
     
       
diff --git a/site/engines/observable/index.html b/site/engines/observable/index.html
index cd04898..760a3ab 100644
--- a/site/engines/observable/index.html
+++ b/site/engines/observable/index.html
@@ -18,7 +18,7 @@
       
       
       
-      
+      
     
     
       
@@ -1075,6 +1075,11 @@ 

Observable

+ + + + +
Source code in ckanext/charts/chart_builders/observable.py
 9
diff --git a/site/engines/plotly/index.html b/site/engines/plotly/index.html
index 8b3ddef..34a8f8f 100644
--- a/site/engines/plotly/index.html
+++ b/site/engines/plotly/index.html
@@ -18,7 +18,7 @@
       
       
       
-      
+      
     
     
       
@@ -1059,6 +1059,11 @@ 

Plotly

Base class for Plotly chart builders.

Defines supported chart types for Plotly engine.

+ + + + +
Source code in ckanext/charts/chart_builders/plotly.py
- + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + - + - + + - + - + - + - + - +
16
diff --git a/site/fetchers/base/index.html b/site/fetchers/base/index.html
index 09129ca..2dc8281 100644
--- a/site/fetchers/base/index.html
+++ b/site/fetchers/base/index.html
@@ -18,7 +18,7 @@
       
       
       
-      
+      
     
     
       
@@ -1039,6 +1039,11 @@ 

Base Fetcher

+ + + + +
diff --git a/site/fetchers/datastore/index.html b/site/fetchers/datastore/index.html index 6b36c55..032ac4b 100644 --- a/site/fetchers/datastore/index.html +++ b/site/fetchers/datastore/index.html @@ -18,7 +18,7 @@ - + @@ -1023,6 +1023,11 @@

Datastore Fetcher

+ + + + +
@@ -1056,7 +1061,9 @@

resource_id + resource_id +

The ID of the resource to fetch data for.

@@ -1070,7 +1077,9 @@

limit + limit +

The maximum number of rows to fetch.

@@ -1088,7 +1097,9 @@

cache_strategy + cache_strategy +

The cache strategy to use. If not provided, diff --git a/site/fetchers/file/index.html b/site/fetchers/file/index.html index 9ec282d..99e2d00 100644 --- a/site/fetchers/file/index.html +++ b/site/fetchers/file/index.html @@ -18,7 +18,7 @@ - + @@ -1035,6 +1035,11 @@

File System Data Fetcher

+ + + + +
@@ -1068,7 +1073,9 @@

file_path + file_path +

The path to the file.

@@ -1082,7 +1089,9 @@

file_format + file_format +

The format of the file.

@@ -1100,7 +1109,9 @@

cache_strategy + cache_strategy +

The cache strategy to use. If not provided, diff --git a/site/fetchers/hardcode/index.html b/site/fetchers/hardcode/index.html index ce05345..6885e7b 100644 --- a/site/fetchers/hardcode/index.html +++ b/site/fetchers/hardcode/index.html @@ -18,7 +18,7 @@ - + @@ -1044,6 +1044,11 @@

Hardcoded Data Fetcher

+ + + + +
@@ -1077,7 +1082,9 @@

data + data +

The hardcoded data.

diff --git a/site/fetchers/index.html b/site/fetchers/index.html index d993021..f27c37c 100644 --- a/site/fetchers/index.html +++ b/site/fetchers/index.html @@ -18,7 +18,7 @@ - + diff --git a/site/fetchers/url/index.html b/site/fetchers/url/index.html index c85f3d7..4fe51a5 100644 --- a/site/fetchers/url/index.html +++ b/site/fetchers/url/index.html @@ -18,7 +18,7 @@ - + @@ -1053,6 +1053,11 @@

URL Data Fetcher

+ + + + +
@@ -1086,7 +1091,9 @@

url + url +

The URL to fetch data from.

@@ -1100,7 +1107,9 @@

file_format + file_format +

The format of the file.

@@ -1118,7 +1127,9 @@

timeout + timeout +

The timeout for the request in seconds.

@@ -1136,7 +1147,9 @@

cache_strategy + cache_strategy +

The cache strategy to use. If not provided, diff --git a/site/helpers/index.html b/site/helpers/index.html index dcb000d..581415f 100644 --- a/site/helpers/index.html +++ b/site/helpers/index.html @@ -18,7 +18,7 @@ - + @@ -1106,6 +1106,11 @@

Helper Functions

+ + + + +
@@ -1201,7 +1206,9 @@

resource_id + resource_id +

Resource ID

diff --git a/site/index.html b/site/index.html index 3750a6a..3b0f99a 100644 --- a/site/index.html +++ b/site/index.html @@ -16,7 +16,7 @@ - + @@ -331,6 +331,15 @@ + + +
  • + + + Building the documentation + + +
  • @@ -991,6 +1000,15 @@ +
  • + +
  • + + + Building the documentation + + +
  • @@ -1042,6 +1060,17 @@

    Tests

    To run the tests, do:

    pytest --ckan-ini=test.ini
     
    +

    Building the documentation

    +

    We are using mkdocs to build the documentation. To build and deploy the documentation, do:

    +
    CHARTS_FIELDS=1 mkdocs build && mkdocs gh-deploy
    +
    +

    We need to set the CHARTS_FIELDS for our custom handler, that autogenerate documentation +for chart types fields.

    +

    If you're working on the documentation, you can run the following command to start a live-reloading server without +gathering the chart types fields data. It will speed up the process significantly, as we won't need to wait for the +CKAN initialization:

    +
    mkdocs serve -a 127.0.0.1:8001
    +

    License

    AGPL

    diff --git a/site/install/index.html b/site/install/index.html index e432e89..b2d6d88 100644 --- a/site/install/index.html +++ b/site/install/index.html @@ -18,7 +18,7 @@ - + @@ -1037,7 +1037,7 @@

    Installation

  • -

    Enable the main plugin and harvesters you want to use in your CKAN configuration file (e.g. ckan.ini or production.ini):

    +

    Enable the view and builder plugins in your CKAN configuration file (e.g. ckan.ini or production.ini):

    ckan.plugins = ... charts_view charts_builder_view ...
     
  • diff --git a/site/search/search_index.json b/site/search/search_index.json index b07c762..19b0b27 100644 --- a/site/search/search_index.json +++ b/site/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-\\.\\_]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#ckanext-charts","title":"ckanext-charts","text":"

    This extension, ckanext-charts, provides additional functionality for working with charts in CKAN. It allows users to create, manage, and visualize charts based on data stored in CKAN datasets.

    The extension includes features such as chart creation, chart editing, chart embedding, and chart sharing. It also supports various chart types, including bar charts, line charts, pie charts, and more.

    With ckanext-charts, users can easily generate interactive and visually appealing charts to enhance data analysis and presentation in CKAN.

    See the documentation for more information.

    "},{"location":"#quick-start","title":"Quick start","text":"
    • Install it with PyPi with pip install ckanext-charts[pyarrow]
    • Add charts_view to the list of plugins in your CKAN config (ckan.plugins = charts_view charts_builder_view)
    "},{"location":"#developer-installation","title":"Developer installation","text":"

    To install ckanext-charts for development, activate your CKAN virtualenv and do:

    git clone https://github.com/DataShades/ckanext-charts.git\ncd ckanext-charts\npip install -e '.[dev]'\n
    "},{"location":"#tests","title":"Tests","text":"

    To run the tests, do:

    pytest --ckan-ini=test.ini\n
    "},{"location":"#license","title":"License","text":"

    AGPL

    "},{"location":"configuration/","title":"Configuration","text":"

    Configuration options

    There is a number of configuration options available for the extension. You can set them in the CKAN configuration file or using the admin configuration page.

    "},{"location":"configuration/#configuration-options","title":"Configuration options","text":""},{"location":"configuration/#cache-strategy","title":"Cache strategy","text":"

    ckanext.charts.cache_strategy [optional]

    Cache strategy for chart data.

    Options: redis, file_orc, file_csv

    Type: str

    Default: redis

    "},{"location":"configuration/#redis-cache-ttl","title":"Redis cache TTL","text":"

    ckanext.charts.redis_cache_ttl [optional]

    Time to live for the Redis cache in seconds. Set to 0 to disable cache.

    Type: int

    Default: 3600

    "},{"location":"configuration/#file-cache-ttl","title":"File cache TTL","text":"

    ckanext.charts.file_cache_ttl [optional]

    Time to live for the File cache in seconds. Set to 0 to disable cache.

    Type: int

    Default: 3600

    "},{"location":"configuration/#enable-cache","title":"Enable cache","text":"

    ckanext.charts.enable_cache [optional]

    Enable cache for the charts.

    Warning

    If the cache is disabled, the chart data will be fetched from the data source every time the chart is rendered. It could lead to performance issues if the data source is slow or the data is too large.

    Type: bool

    Default: true

    "},{"location":"configuration/#include-htmx","title":"Include HTMX","text":"

    ckanext.charts.include_htmx_asset [optional]

    Include HTMX assets. Could be disabled if another plugins are including it.

    Type: bool

    Default: true

    "},{"location":"configuration/#reinit-ckan-js","title":"Reinit CKAN JS","text":"

    ckanext.charts.reinit_ckan_js_modules [optional]

    Reinit CKAN JS modules after HTMX swap.

    Type: bool

    Default: false

    "},{"location":"configuration/#allow-anonymous-users-to-build-charts","title":"Allow anonymous users to build charts","text":"

    ckanext.charts.allow_anon_building_charts [optional]

    By default, only authenticated users can build charts. If you want to allow anonymous users to build charts, set this option to true.

    Type: bool

    Default: false

    "},{"location":"configuration/#admin-config-page","title":"Admin config page","text":"

    The extension provides an admin configuration page where you can set all the listed configuration options. The admin page available only using an extension ckanext-admin-panel. The admin panel is a separate extension that provides an alternative admin interface for CKAN. It allows you to manage CKAN settings and other extensions settings through the web interface.

    This page could be accessed by the following URL: /admin-panel/charts/config, but it will be registered only if the ckanext-admin-panel is installed and enabled.

    "},{"location":"helpers/","title":"Helper Functions","text":""},{"location":"helpers/#charts.helpers.charts_allow_anon_building_charts","title":"charts_allow_anon_building_charts()","text":"

    Check if anonymous users are allowed to build charts.

    RETURNS DESCRIPTION bool

    True if anonymous users are allowed to build charts, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_allow_anon_building_charts() -> bool:\n    \"\"\"Check if anonymous users are allowed to build charts.\n\n    Returns:\n        bool: True if anonymous users are allowed to build charts, False otherwise.\n    \"\"\"\n    return config.allow_anon_building_charts()\n
    "},{"location":"helpers/#charts.helpers.charts_get_resource_columns","title":"charts_get_resource_columns(resource_id)","text":"

    Get the columns of the given resource.

    PARAMETER DESCRIPTION resource_id

    Resource ID

    TYPE: str

    RETURNS DESCRIPTION str

    JSON string of columns options

    TYPE: str

    Source code in ckanext/charts/helpers.py
    def charts_get_resource_columns(resource_id: str) -> str:\n    \"\"\"Get the columns of the given resource.\n\n    Args:\n        resource_id: Resource ID\n\n    Returns:\n        str: JSON string of columns options\n    \"\"\"\n    fetcher = DatastoreDataFetcher(resource_id)\n\n    return json.dumps(\n        [{\"id\": col, \"title\": col} for col in fetcher.fetch_data().columns],\n    )\n
    "},{"location":"helpers/#charts.helpers.charts_include_htmx_asset","title":"charts_include_htmx_asset()","text":"

    Checks if the HTMX asset should be included.

    RETURNS DESCRIPTION bool

    True if the HTMX asset should be included, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_include_htmx_asset() -> bool:\n    \"\"\"Checks if the HTMX asset should be included.\n\n    Returns:\n        bool: True if the HTMX asset should be included, False otherwise.\n    \"\"\"\n    return config.include_htmx_asset()\n
    "},{"location":"helpers/#charts.helpers.charts_reinit_ckan_js_modules","title":"charts_reinit_ckan_js_modules()","text":"

    Checks if CKAN JS modules should be reinitialized.

    RETURNS DESCRIPTION bool

    True if CKAN JS modules should be reinitialized, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_reinit_ckan_js_modules() -> bool:\n    \"\"\"Checks if CKAN JS modules should be reinitialized.\n\n    Returns:\n        bool: True if CKAN JS modules should be reinitialized, False otherwise.\n    \"\"\"\n    return config.reinit_ckan_js_modules()\n
    "},{"location":"helpers/#charts.helpers.charts_user_is_authenticated","title":"charts_user_is_authenticated()","text":"

    Check if the user is authenticated.

    RETURNS DESCRIPTION bool

    True if the user is authenticated, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_user_is_authenticated() -> bool:\n    \"\"\"Check if the user is authenticated.\n\n    Returns:\n        bool: True if the user is authenticated, False otherwise.\n    \"\"\"\n    return tk.current_user.is_authenticated\n
    "},{"location":"helpers/#charts.helpers.get_available_chart_engines_options","title":"get_available_chart_engines_options()","text":"

    Get the available chart engines.

    RETURNS DESCRIPTION list[dict[str, str]]

    List of chart engines options

    Source code in ckanext/charts/helpers.py
    def get_available_chart_engines_options() -> list[dict[str, str]]:\n    \"\"\"Get the available chart engines.\n\n    Returns:\n        List of chart engines options\n    \"\"\"\n    return [{\"value\": engine, \"text\": engine} for engine in get_chart_engines()]\n
    "},{"location":"helpers/#charts.helpers.get_file_cache_size","title":"get_file_cache_size()","text":"

    Get the size of the file cache in a human-readable format.

    RETURNS DESCRIPTION str

    Human-readable file cache size

    TYPE: str

    Source code in ckanext/charts/helpers.py
    def get_file_cache_size() -> str:\n    \"\"\"Get the size of the file cache in a human-readable format.\n\n    Returns:\n        str: Human-readable file cache size\n    \"\"\"\n    return utils.printable_file_size(count_file_cache_size())\n
    "},{"location":"helpers/#charts.helpers.get_redis_cache_size","title":"get_redis_cache_size()","text":"

    Get the size of the Redis cache in a human-readable format.

    RETURNS DESCRIPTION str

    Human-readable Redis cache size

    TYPE: str

    Source code in ckanext/charts/helpers.py
    def get_redis_cache_size() -> str:\n    \"\"\"Get the size of the Redis cache in a human-readable format.\n\n    Returns:\n        str: Human-readable Redis cache size\n    \"\"\"\n    return utils.printable_file_size(count_redis_cache_size())\n
    "},{"location":"install/","title":"Installation","text":""},{"location":"install/#requirements","title":"Requirements","text":"

    Requires Redis 7+

    Compatibility with core CKAN versions:

    CKAN version Compatible? 2.9 and earlier no 2.10+ yes"},{"location":"install/#installation_1","title":"Installation","text":"
    1. Install the extension from PyPI:

      pip install ckanext-charts\n

      If you want to use ORC file cache, you have to install the extension with the pyarrow extra:

      pip install ckanext-charts[pyarrow]\n

    2. Enable the main plugin and harvesters you want to use in your CKAN configuration file (e.g. ckan.ini or production.ini):

      ckan.plugins = ... charts_view charts_builder_view ...\n
    "},{"location":"install/#dependencies","title":"Dependencies","text":"

    The extension requires the following CKAN extensions to be installed and enabled:

    1. ckanext-scheming: We're using the scheming extension to create custom forms for the chart builders.

    2. ckanext-admin-panel (optional): If you want to use the admin configuration page, you need to install and enable this extension. The admin panel is a separate extension that provides an alternative admin interface for CKAN. It allows you to manage CKAN settings and other extensions settings through the web interface and significantly extends the default CKAN admin interface.

    "},{"location":"troubleshooting/","title":"Troubleshooting","text":"

    ImportError: lxml.html.clean module is now a separate project lxml_html_clean

    Install lxml[html_clean] or lxml_html_clean directly using pip.

    "},{"location":"usage/","title":"Usage","text":""},{"location":"usage/#basic-usage","title":"Basic usage","text":"

    This extension offers two plugins: charts_view and charts_builder_view. The first plugin is a standard chart builder designed for system administrators or anyone with permission to edit or create a resource view. Creating a preview using this plugin generates a static chart with saved settings. This chart retains the settings and will always be rendered in the same way.

    The charts_builder_view plugin does not have any special settings during the creation or editing stages. Instead, it renders a chart builder JS widget on a resource page, allowing any user to interact with the resource data and create a chart that meets their needs. In the future, we plan to implement a feature that will allow users to save their charts.

    "},{"location":"usage/#restrict-user-chart-builder-for-anonymous-users","title":"Restrict user chart builder for anonymous users","text":"

    The user chart builder could be restricted to only authenticated users. See the config settings section for more information. In this case, user will be forced to log in to build a chart. After the user logs in, user will be redirected to the chart builder page back.

    "},{"location":"utils/","title":"Utility Functions","text":""},{"location":"utils/#charts.utils.build_chart_for_data","title":"build_chart_for_data(settings, data)","text":"

    Build chart for the given dataframe and settings.

    PARAMETER DESCRIPTION settings

    Chart settings

    TYPE: dict[str, Any]

    data

    Dataframe with data

    TYPE: DataFrame

    RETURNS DESCRIPTION str | None

    Chart config as JSON string

    Source code in ckanext/charts/utils.py
    def build_chart_for_data(settings: dict[str, Any], data: pd.DataFrame) -> str | None:\n    \"\"\"Build chart for the given dataframe and settings.\n\n    Args:\n        settings: Chart settings\n        data: Dataframe with data\n\n    Returns:\n        Chart config as JSON string\n    \"\"\"\n    return _build_chart(settings, data)\n
    "},{"location":"utils/#charts.utils.build_chart_for_resource","title":"build_chart_for_resource(settings, resource_id)","text":"

    Build chart for the given resource ID.

    Uses a DatastoreDataFetcher to fetch data from the resource.

    PARAMETER DESCRIPTION settings

    Chart settings

    TYPE: dict[str, Any]

    resource_id

    Resource ID

    TYPE: str

    RETURNS DESCRIPTION str | None

    str | None: Chart config as JSON string or None if the chart can't be built

    Source code in ckanext/charts/utils.py
    def build_chart_for_resource(settings: dict[str, Any], resource_id: str) -> str | None:\n    \"\"\"Build chart for the given resource ID.\n\n    Uses a DatastoreDataFetcher to fetch data from the resource.\n\n    Args:\n        settings: Chart settings\n        resource_id: Resource ID\n\n    Returns:\n        str | None: Chart config as JSON string or None if the chart can't be built\n    \"\"\"\n    settings.pop(\"__extras\", None)\n\n    try:\n        df = DatastoreDataFetcher(resource_id).fetch_data()\n    except tk.ValidationError:\n        return None\n\n    return _build_chart(settings, df)\n
    "},{"location":"utils/#charts.utils.can_view","title":"can_view(data_dict)","text":"

    Check if the resource can be viewed as a chart.

    For now, we work only with resources stored with the DataStore.

    PARAMETER DESCRIPTION data_dict

    Resource data dictionary

    TYPE: dict[str, Any]

    RETURNS DESCRIPTION bool

    True if the resource can be viewed as a chart, False otherwise

    TYPE: bool

    Source code in ckanext/charts/utils.py
    def can_view(data_dict: dict[str, Any]) -> bool:\n    \"\"\"Check if the resource can be viewed as a chart.\n\n    For now, we work only with resources stored with the DataStore.\n\n    Args:\n        data_dict: Resource data dictionary\n\n    Returns:\n        bool: True if the resource can be viewed as a chart, False otherwise\n    \"\"\"\n    if data_dict[\"resource\"].get(\"datastore_active\"):\n        return True\n\n    # TODO: Add support for XML, XLS, XLSX, and other formats tabular data?\n    # if data_dict[\"resource\"][\"format\"].lower() == \"xml\":\n    #     return True\n\n    return False\n
    "},{"location":"utils/#charts.utils.get_chart_form_builder","title":"get_chart_form_builder(engine, chart_type)","text":"

    Get form builder for the given engine and chart type.

    Source code in ckanext/charts/utils.py
    def get_chart_form_builder(engine: str, chart_type: str):\n    \"\"\"Get form builder for the given engine and chart type.\"\"\"\n    builders = get_chart_engines()\n\n    if engine not in builders:\n        raise NotImplementedError(f\"Engine {engine} is not supported\")\n\n    return builders[engine].get_form_for_type(chart_type)\n
    "},{"location":"utils/#charts.utils.get_column_options","title":"get_column_options(resource_id)","text":"

    Get column options for the given resource.

    PARAMETER DESCRIPTION resource_id

    Resource ID

    TYPE: str

    RETURNS DESCRIPTION list[dict[str, str]]

    List of column options

    Source code in ckanext/charts/utils.py
    def get_column_options(resource_id: str) -> list[dict[str, str]]:\n    \"\"\"Get column options for the given resource.\n\n    Args:\n        resource_id: Resource ID\n\n    Returns:\n        List of column options\n    \"\"\"\n    df = DatastoreDataFetcher(resource_id).fetch_data()\n\n    return [{\"text\": col, \"value\": col} for col in df.columns]\n
    "},{"location":"utils/#charts.utils.printable_file_size","title":"printable_file_size(size_bytes)","text":"

    Convert file size in bytes to human-readable format.

    PARAMETER DESCRIPTION size_bytes

    File size in bytes

    TYPE: int

    RETURNS DESCRIPTION str

    Human-readable file size

    TYPE: str

    Examples:

    >>> printable_file_size(123456789)\n'117.7 MB'\n
    >>> printable_file_size(7777)\n'7.6 KB'\n
    Source code in ckanext/charts/utils.py
    def printable_file_size(size_bytes: int) -> str:\n    \"\"\"Convert file size in bytes to human-readable format.\n\n    Args:\n        size_bytes: File size in bytes\n\n    Returns:\n        str: Human-readable file size\n\n    Examples:\n        >>> printable_file_size(123456789)\n        '117.7 MB'\n\n        >>> printable_file_size(7777)\n        '7.6 KB'\n    \"\"\"\n    if size_bytes == 0:\n        return \"0 bytes\"\n\n    size_name = (\"bytes\", \"KB\", \"MB\", \"GB\", \"TB\")\n    i = int(math.floor(math.log(size_bytes, 1024)))\n    p = math.pow(1024, i)\n    s = round(float(size_bytes) / p, 1)\n\n    return f\"{s} {size_name[i]}\"\n
    "},{"location":"validators/","title":"Validators","text":""},{"location":"validators/#charts.logic.validators.charts_if_empty_same_as","title":"charts_if_empty_same_as(other_key)","text":"

    A custom version of if_empty_same_as validator for charts.

    This validator is used to set the value of a field to the value of another field if it is empty or missing.

    PARAMETER DESCRIPTION other_key

    The key of the field to copy the value from

    TYPE: str

    RETURNS DESCRIPTION Callable[..., Any]

    Callable[..., Any]: The validator function

    Source code in ckanext/charts/logic/validators.py
    def charts_if_empty_same_as(other_key: str) -> Callable[..., Any]:\n    \"\"\"A custom version of if_empty_same_as validator for charts.\n\n    This validator is used to set the value of a field to the value of another\n    field if it is empty or missing.\n\n    Args:\n        other_key (str): The key of the field to copy the value from\n\n    Returns:\n        Callable[..., Any]: The validator function\n    \"\"\"\n\n    def callable(key, data, errors, context):\n        value = data.get(key)\n        if not value or value is tk.missing:\n            try:\n                data[key] = data[key[:-1] + (other_key,)]\n            except KeyError:\n                data[key] = data.get((\"__extras\",), {}).get(other_key, \"\")\n\n    return callable\n
    "},{"location":"validators/#charts.logic.validators.charts_list_length_validator","title":"charts_list_length_validator(max_length)","text":"

    A validator to check the length of a list.

    PARAMETER DESCRIPTION max_length

    The maximum length of the list

    TYPE: int

    RETURNS DESCRIPTION Callable[..., Any]

    Callable[..., Any]: The validator function

    Source code in ckanext/charts/logic/validators.py
    def charts_list_length_validator(max_length: int) -> Callable[..., Any]:\n    \"\"\"A validator to check the length of a list.\n\n    Args:\n        max_length (int): The maximum length of the list\n\n    Returns:\n        Callable[..., Any]: The validator function\n    \"\"\"\n    def callable(\n        key: types.FlattenKey,\n        data: types.FlattenDataDict,\n        errors: types.FlattenErrorDict,\n        context: types.Context,\n    ):\n        if len(data[key]) > max_length:\n            raise tk.Invalid(tk._(\"Length must be less than {0}\").format(max_length))\n\n    return callable\n
    "},{"location":"validators/#charts.logic.validators.charts_list_to_csv","title":"charts_list_to_csv(data)","text":"

    Convert a list of strings to a CSV string.

    PARAMETER DESCRIPTION data

    The data to convert

    TYPE: list[str] | str

    RETURNS DESCRIPTION str

    The comma separated string

    TYPE: str

    Source code in ckanext/charts/logic/validators.py
    def charts_list_to_csv(data: list[str] | str) -> str:\n    \"\"\"Convert a list of strings to a CSV string.\n\n    Args:\n        data (list[str] | str): The data to convert\n\n    Returns:\n        str: The comma separated string\n    \"\"\"\n    if not isinstance(data, list):\n        return data\n\n    return \", \".join(data)\n
    "},{"location":"validators/#charts.logic.validators.charts_strategy_support","title":"charts_strategy_support(strategy)","text":"

    Check if the cache strategy is supported.

    PARAMETER DESCRIPTION strategy

    The cache strategy

    TYPE: str

    RETURNS DESCRIPTION str

    The cache strategy if it is supported

    TYPE: str

    RAISES DESCRIPTION Invalid

    If the cache strategy is not supported

    Source code in ckanext/charts/logic/validators.py
    def charts_strategy_support(strategy: str) -> str:\n    \"\"\"Check if the cache strategy is supported.\n\n    Args:\n        strategy (str): The cache strategy\n\n    Returns:\n        str: The cache strategy if it is supported\n\n    Raises:\n        tk.Invalid: If the cache strategy is not supported\n    \"\"\"\n    if strategy not in const.SUPPORTED_CACHE_STRATEGIES:\n        raise tk.Invalid(tk._(\"Invalid cache strategy\"))\n\n    if strategy == const.CACHE_FILE_ORC:\n        try:\n            from pyarrow import orc as _  # noqa\n        except ImportError:\n            raise tk.Invalid(\n                tk._(\"Can't use File Orc cache strategy. PyArrow is not installed\"),\n            ) from None\n\n    if not strategy:\n        return const.DEFAULT_CACHE_STRATEGY\n\n    return strategy\n
    "},{"location":"validators/#charts.logic.validators.charts_to_list_if_string","title":"charts_to_list_if_string(value)","text":"

    Convert a string to a list.

    PARAMETER DESCRIPTION value

    The value to convert

    TYPE: Any

    RETURNS DESCRIPTION Any

    list[Any]: The value in a list

    Source code in ckanext/charts/logic/validators.py
    def charts_to_list_if_string(value: Any) -> Any:\n    \"\"\"Convert a string to a list.\n\n    Args:\n        value (Any): The value to convert\n\n    Returns:\n        list[Any]: The value in a list\n    \"\"\"\n    if isinstance(value, str):\n        return [value]\n\n    return value\n
    "},{"location":"validators/#charts.logic.validators.charts_validate_extras","title":"charts_validate_extras(key, data, errors, context)","text":"

    Validate charts settings according to the chart type and engine schema.

    PARAMETER DESCRIPTION key

    The key of the field

    TYPE: FlattenKey

    data

    The data to validate

    TYPE: FlattenDataDict

    errors

    The errors dict

    TYPE: FlattenErrorDict

    context

    The context

    TYPE: Context

    Source code in ckanext/charts/logic/validators.py
    def charts_validate_extras(\n    key: types.FlattenKey,\n    data: types.FlattenDataDict,\n    errors: types.FlattenErrorDict,\n    context: types.Context,\n):\n    \"\"\"Validate charts settings according to the chart type and engine schema.\n\n    Args:\n        key (types.FlattenKey): The key of the field\n        data (types.FlattenDataDict): The data to validate\n        errors (types.FlattenErrorDict): The errors dict\n        context (types.Context): The context\n    \"\"\"\n    settings = _extract_setting(data)\n\n    if \"engine\" not in settings or \"type\" not in settings:\n        builder = DEFAULT_CHART_FORM\n    else:\n        builder = utils.get_chart_form_builder(settings[\"engine\"], settings[\"type\"])\n\n    settings, err = tk.navl_validate(\n        settings,\n        builder(settings[\"resource_id\"]).get_validation_schema(\n            context.get(\"_for_show\", False),\n        ),\n        {},\n    )\n\n    # TODO: do we have a better way to handle this? Seems like a hack\n    for k, v in settings.items():\n        data[(k,)] = v\n\n    for k, v in settings.pop(\"__extras\", {}).items():\n        data[(k,)] = v\n\n    for k, v in err.items():\n        errors[(k,)] = v\n
    "},{"location":"validators/#charts.logic.validators.float_validator","title":"float_validator(value)","text":"

    A validator for decimal numbers.

    PARAMETER DESCRIPTION value

    The value to validate

    TYPE: Any

    RETURNS DESCRIPTION float

    The value as a float

    TYPE: float

    Source code in ckanext/charts/logic/validators.py
    def float_validator(value: Any) -> float:\n    \"\"\"A validator for decimal numbers.\n\n    Args:\n        value (Any): The value to validate\n\n    Returns:\n        float: The value as a float\n    \"\"\"\n    try:\n        return float(value)\n    except ValueError:\n        raise tk.Invalid(tk._(\"Must be a decimal number\")) from None\n
    "},{"location":"caching/","title":"Caching","text":"

    The extension implement a cache strategy to store the data fetched from the different sources.

    There are three cache strategies available:

    1. redis
    2. file_orc
    3. file_csv.
    "},{"location":"caching/#file-cache","title":"File cache","text":"

    The file cache works by storing the data in an orc or csv file in the filesystem. The redis cache stores the data in a Redis database. The cache strategy can be changed at the CKAN configuration level through the admin interface or in a configuration file.

    The file-type cache strategy stores the data in a file in the filesystem. The file cache is stored in the ckanext-charts directory in the CKAN storage path. The file cache is stored in an orc or csv file format.

    Warning

    Using file_orc cache strategy requires the pyarrow python library to be installed.

    "},{"location":"caching/#redis-cache","title":"Redis cache","text":"

    The redis cache strategy stores the data in a Redis database.

    Each redis key has a ckanext-charts:* prefix and store the data as a CSV string.

    Note

    You need to have a Redis server running to use the redis cache strategy.

    "},{"location":"caching/#cache-ttl","title":"Cache TTL","text":"

    The cache TTL can be set in the CKAN configuration file. The default value is 3600 seconds (1 hour). The cache TTL can be set to 0 to disable the cache.

    The redis and file-type cache has separate TTL settings:

    • The redis cache TTL can be set with the ckanext.charts.redis_cache_ttl configuration option.
    • The file cache TTL can be set with the ckanext.charts.file_cache_ttl configuration option.
    "},{"location":"caching/#disable-cache","title":"Disable cache","text":"

    Cache could be disabled by setting ckanext.charts.enable_cache to false. In this case the data will be fetched from the source every time the chart is rendered. It could be useful for debugging purposes. But using it in production is not recommended, as it could lead to performance issues.

    "},{"location":"caching/base/","title":"Base Cache Strategy","text":"

    To implement a custom cache strategy, you need to create a new class that extends the CacheStrategy class and implement the abstract methods.

    See a naive implementation of a memcached cache strategy below:

    from io import BytesIO\n\nfrom pymemcache.client import base\nimport pandas as pd\n\nimport ckanext.charts.config as config\nfrom ckanext.charts.cache import CacheStrategy\n\nclass MemcachedCache(CacheStrategy):\n    \"\"\"Cache data to Memcached\"\"\"\n\n    def __init__(self):\n        self.client = base.Client(('localhost', 11211))\n\n    def get_data(self, key: str) -> pd.DataFrame | None:\n        \"\"\"Return data from cache if exists\"\"\"\n        try:\n            raw_data = self.client.get(key)\n\n            if not raw_data:\n                return None\n\n            return pd.read_csv(BytesIO(raw_data))\n        except Exception:\n            log.exception(f\"Failed to get data for key: {key}\")\n            return None\n\n    def set_data(self, key: str, data: pd.DataFrame):\n        \"\"\"Serialize data and save to Memcached\"\"\"\n        cache_ttl = config.get_memcached_cache_ttl()\n\n        try:\n            serialized_data = data.to_csv(index=False).encode('utf-8')\n            self.client.set(key, serialized_data, expire=cache_ttl)\n        except Exception:\n            log.exception(f\"Failed to save data to Memcached for key: {key}\")\n\n    def invalidate(self, key: str):\n        \"\"\"Invalidate cache by key\"\"\"\n        try:\n            self.client.delete(key)\n        except Exception:\n            log.exception(f\"Failed to invalidate cache for key: {key}\")\n

    Bases: ABC

    Cache strategy interface.

    Defines the abstracts methods for cache strategies.

    "},{"location":"caching/base/#charts.cache.CacheStrategy.get_data","title":"get_data(key) abstractmethod","text":"

    Return data from cache if exists.

    PARAMETER DESCRIPTION key

    The cache key to retrieve the data.

    TYPE: str

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/base/#charts.cache.CacheStrategy.invalidate","title":"invalidate(key) abstractmethod","text":"

    Invalidate cache by key.

    PARAMETER DESCRIPTION key

    The cache key to invalidate.

    TYPE: str

    "},{"location":"caching/base/#charts.cache.CacheStrategy.set_data","title":"set_data(key, data) abstractmethod","text":"

    Store data to cache.

    PARAMETER DESCRIPTION key

    The cache key to store the data.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/","title":"File Cache","text":""},{"location":"caching/file/#charts.cache.FileCache","title":"FileCache","text":"

    Bases: CacheStrategy

    Cache data as file.

    We store the cached files in a separate folder in the CKAN storage.

    "},{"location":"caching/file/#charts.cache.FileCache.generate_unique_consistent_filename","title":"generate_unique_consistent_filename(key)","text":"

    Generate unique and consistent filename based on the key.

    PARAMETER DESCRIPTION key

    The cache key to generate the filename.

    TYPE: str

    RETURNS DESCRIPTION str

    The filename.

    "},{"location":"caching/file/#charts.cache.FileCache.get_data","title":"get_data(key)","text":"

    Return data from cache if exists.

    PARAMETER DESCRIPTION key

    The cache key to retrieve the data.

    TYPE: str

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCache.invalidate","title":"invalidate(key)","text":"

    Remove data from cache.

    PARAMETER DESCRIPTION key

    The cache key to invalidate.

    TYPE: str

    "},{"location":"caching/file/#charts.cache.FileCache.is_file_cache_expired","title":"is_file_cache_expired(file_path) staticmethod","text":"

    Check if file cache is expired.

    If TTL is 0 then cache never expires.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    RETURNS DESCRIPTION bool

    True if file cache is expired, otherwise False.

    "},{"location":"caching/file/#charts.cache.FileCache.make_file_path_from_key","title":"make_file_path_from_key(key)","text":"

    Generate file path based on the key

    PARAMETER DESCRIPTION key

    The cache key to generate the file path.

    TYPE: str

    RETURNS DESCRIPTION str

    The file path.

    "},{"location":"caching/file/#charts.cache.FileCache.read_data","title":"read_data(file) abstractmethod","text":"

    Read cached data from a file object.

    PARAMETER DESCRIPTION file

    The file object to read the data.

    TYPE: IO

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCache.set_data","title":"set_data(key, data)","text":"

    Store data to cache.

    PARAMETER DESCRIPTION key

    The cache key to store the data.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/#charts.cache.FileCache.write_data","title":"write_data(file_path, data) abstractmethod","text":"

    Defines how to write data to a file.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/#charts.cache.FileCacheORC","title":"FileCacheORC","text":"

    Bases: FileCache

    Cache data as ORC file

    "},{"location":"caching/file/#charts.cache.FileCacheORC.read_data","title":"read_data(file)","text":"

    Read cached data from an ORC file.

    PARAMETER DESCRIPTION file

    The file object to read the data.

    TYPE: IO

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCacheORC.write_data","title":"write_data(file_path, data)","text":"

    Write data to an ORC file.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/#charts.cache.FileCacheCSV","title":"FileCacheCSV","text":"

    Bases: FileCache

    Cache data as CSV file

    "},{"location":"caching/file/#charts.cache.FileCacheCSV.read_data","title":"read_data(file)","text":"

    Read cached data from a CSV file.

    PARAMETER DESCRIPTION file

    The file object to read the data.

    TYPE: IO

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCacheCSV.write_data","title":"write_data(file_path, data)","text":"

    Write data to a CSV file.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/redis/","title":"Redis Cache","text":"

    Bases: CacheStrategy

    Cache data to Redis as a CSV string

    "},{"location":"caching/redis/#charts.cache.RedisCache.get_data","title":"get_data(key)","text":"

    Return data from cache if exists.

    PARAMETER DESCRIPTION key

    The cache key to retrieve the data.

    TYPE: str

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/redis/#charts.cache.RedisCache.invalidate","title":"invalidate(key)","text":"

    Remove data from cache.

    PARAMETER DESCRIPTION key

    The cache key to invalidate.

    TYPE: str

    "},{"location":"caching/redis/#charts.cache.RedisCache.set_data","title":"set_data(key, data)","text":"

    Serialize data and save to Redis.

    PARAMETER DESCRIPTION key

    The cache key to store the data.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    RAISES DESCRIPTION Exception

    If failed to save data to Redis.

    "},{"location":"engines/","title":"Index","text":"

    The ckanext-charts implements supports different chart engines, such as plotly, observable and chartjs.

    Each engine consists of two classes - chart builder and form builder. The chart builder is responsible for generating a JSON-string representation of the chart data, that will be passed to a respective JS module, that will render a chart based on the data.

    The form builder is responsible for generating a form that allows users to configure the chart from the UI.

    Also, you can implement support of a chart library of your choice by creating a custom chart engine. Read more about it here.

    "},{"location":"engines/chartjs/","title":"Chartjs","text":"

    The Chart.JS chart engine supports the following chart types:

    • Bar chart
    • Horizontal bar chart
    • Line chart
    • Pie chart
    • Doughnut chart
    • Scatter plot
    • Bubble chart
    • Radar chart
    Source code in ckanext/charts/chart_builders/chartjs.py
    class ChartJsBuilder(BaseChartBuilder):\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [\n            ChartJSBarForm,\n            ChartJSHorizontalBarForm,\n            ChartJSLineForm,\n            ChartJSPieForm,\n            ChartJSDoughnutForm,\n            ChartJSScatterForm,\n            ChartJSBubbleForm,\n            ChartJSRadarForm,\n        ]\n\n    def _create_zoom_and_title_options(self, options: dict[str, Any]) -> dict[str, Any]:\n        \"\"\"Add zoom and title plugin options to the provided options dictionary\"\"\"\n        if \"plugins\" not in options:\n            options[\"plugins\"] = {}\n\n        options[\"plugins\"].update(\n            {\n                \"zoom\": {\n                    \"zoom\": {\n                        \"wheel\": {\"enabled\": True},\n                        \"pinch\": {\"enabled\": True},\n                        \"drag\": {\"enabled\": True},\n                        \"mode\": \"xy\",\n                    },\n                    \"pan\": {\n                        \"enabled\": True,\n                        \"modifierKey\": \"shift\",\n                        \"mode\": \"xy\",\n                    },\n                },\n                \"title\": {\n                    \"display\": True,\n                    \"position\": \"bottom\",\n                },\n            },\n        )\n        return options\n
    "},{"location":"engines/chartjs/#bar-chart","title":"Bar chart","text":"

    The bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. For a horizontal bar chart, use the Horizontal bar chart chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select one or more columns for the Y-axis

    Type: List[str]

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#horizontal-bar-chart","title":"Horizontal bar chart","text":"

    The horizontal bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars are plotted horizontally.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select one or more columns for the Y-axis

    Type: List[str]

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#line-chart","title":"Line chart","text":"

    The line chart is a chart that displays information as a series of data points called 'markers' connected by straight line segments. It is useful for showing trends over time.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select one or more columns for the Y-axis

    Type: List[str]

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Invert X-axis (invert_x)

    Invert the X-axis

    Type: bool

    Invert Y-axis (invert_y)

    Invert the Y-axis

    Type: bool

    "},{"location":"engines/chartjs/#pie-chart","title":"Pie chart","text":"

    The pie chart is a circular statistical graphic that is divided into slices to illustrate numerical proportions. The arc length of each slice is proportional to the quantity it represents.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#doughnut-chart","title":"Doughnut chart","text":"

    The doughnut chart is a variant of the pie chart, with a hole in the center. It is useful for showing the relationship of parts to a whole.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#scatter-plot","title":"Scatter plot","text":"

    The scatter plot is a chart that uses Cartesian coordinates to display values for two variables for a set of data. The data points are represented as individual dots.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#bubble-chart","title":"Bubble chart","text":"

    The bubble chart is a chart that displays data points as bubbles. The size of the bubble represents a third dimension of the data.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Size (size) [Required]

    Select a column for the size

    Type: str

    "},{"location":"engines/chartjs/#radar-chart","title":"Radar chart","text":"

    The radar chart is a chart that displays multivariate data in the form of a two-dimensional chart of three or more quantitative variables represented on axes starting from the same point. The data points are connected by a line to form a polygon.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    Names (names) [Required]

    Type: str

    Values (values) [Required]

    Select 3 or more different categorical variables (dimensions)

    Type: List[str]

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/custom/","title":"Custom chart engine","text":""},{"location":"engines/custom/#implementing-new-chart-engines-support","title":"Implementing new chart engines support","text":"

    Implementing support for a new chart engine includes multiple steps and changes in Python, HTML, and JavaScript. Starting from the Python code:

    1. Create a new builder class at ckanext.charts.chart_builder that inherits from BaseChartBuilder and implements the get_supported_forms method. This method must return a list of classes that represent supported chart types forms.

    2. Each form type builder must be connected with a respective chart type builder.

    3. The chart type builder must implement a to_json method that will return a dumped JSON data, which will be passed to a JS script.

    4. The form type builder must implement a get_form_fields method that will return a list of all form fields that will be rendered for the user, allowing them to provide all the necessary information for a chart.

    5. Register your chart engine by adding the builder class to get_chart_engines in ckanext.charts.chart_builder.__init__.py.

    A full example of an implementation of bar chart for obvervable plot library.

    from __future__ import annotations\n\nimport json\nfrom typing import Any\n\nimport ckanext.charts.exception as exception\nfrom ckanext.charts.chart_builders.base import BaseChartBuilder, BaseChartForm\n\n\nclass ObservableBuilder(BaseChartBuilder):\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [ObservableBarForm]\n\n\nclass ObservableBarBuilder(ObservableBuilder):\n    def to_json(self) -> str:\n        return json.dumps(\n            {\n                \"type\": \"bar\",\n                \"data\": self.df.to_dict(orient=\"records\"),\n                \"settings\": self.settings,\n            }\n        )\n\n\nclass ObservableBarForm(BaseChartForm):\n    name = \"Bar\"\n    builder = ObservableBarBuilder\n\n    def fill_field(self, choices: list[dict[str, str]]) -> dict[str, str]:\n        field = self.color_field(choices)\n        field.update({\"field_name\": \"fill\", \"label\": \"Fill\"})\n\n        return field\n\n    def get_form_fields(self):\n        columns = [{\"value\": col, \"label\": col} for col in self.df.columns]\n        chart_types = [\n            {\"value\": form.name, \"label\": form.name}\n            for form in self.builder.get_supported_forms()\n        ]\n\n        return [\n            self.title_field(),\n            self.description_field(),\n            self.engine_field(),\n            self.type_field(chart_types),\n            self.x_axis_field(columns),\n            self.y_axis_field(columns),\n            self.fill_field(columns),\n            self.opacity_field(),\n            self.limit_field(),\n        ]\n
    "},{"location":"engines/custom/#vendor-and-custom-js","title":"Vendor and custom JS","text":"

    Another step is to register JS/CSS vendor libraries of the chart you want to use. Refer to CKAN documentation to read about adding CSS and JavaScript files using Webassets.

    You also will need a CKAN JS module, that will be responsible for rendering the Chart. This module will work with the vendor library and will be responsible for rendering the chart in the container.

    This module must be registered inside a webassets.yml as well.

        ckan.module(\"charts-render-observable\", function ($, _) {\n        \"use strict\";\n\n        return {\n            options: {\n                config: null\n            },\n\n            initialize: function () {\n                $.proxyAll(this, /_/);\n\n                if (!this.options.config) {\n                    console.error(\"No configuration provided\");\n                    return;\n                }\n\n                var plot;\n\n                switch (this.options.config.type) {\n                    case \"bar\":\n                        plot = Plot.barY(this.options.config.data, this.options.config.settings).plot();\n                        break;\n                    default:\n                        return;\n                }\n\n                this.el[0].replaceChildren(plot);\n            }\n        };\n    });\n

    "},{"location":"engines/custom/#html-container","title":"HTML container","text":"

    And an HTML file, that will provide a proper container and include your JS module with data-module.

        {% asset \"charts/observable\" %}\n\n    {% if chart %}\n        <div id=\"chart-container\" data-module=\"charts-render-observable\" data-module-config=\"{{ chart }}\"></div>\n    {% else %}\n        <p class=\"text-muted\">\n            {{ _(\"Cannot build chart with current settings\") }}\n        </p>\n    {% endif %}\n

    Note, that we should add {% asset \"charts/observable\" %} not only here, but in charts_form.html too.

    The reason for having a separate HTML file and JS module is that different libraries may require different types of container elements (such as div, canvas, etc.) to initialize or may need additional boilerplate code to build a chart. There's no easy way to abstract this, so you have to implement these things yourself.

    "},{"location":"engines/observable/","title":"Observable","text":"

    The Observable Plot chart engine supports the following chart types:

    • Bar chart
    • Horizontal bar chart
    • Pie chart
    • Line chart
    • Scatter plot
    • Auto chart
    Source code in ckanext/charts/chart_builders/observable.py
    class ObservableBuilder(BaseChartBuilder):\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [\n            ObservableBarForm,\n            ObservableHoriontalBarForm,\n            ObservableLineForm,\n            ObservablePieForm,\n            ObservableScatterForm,\n            ObservableAutoForm,\n        ]\n
    "},{"location":"engines/observable/#bar-chart","title":"Bar chart","text":"

    The bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. For a horizontal bar chart, use the Horizontal bar chart chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Fill (fill)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#horizontal-bar-chart","title":"Horizontal bar chart","text":"

    The horizontal bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars are plotted horizontally.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Fill (fill)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#line-chart","title":"Line chart","text":"

    The line chart is a chart that displays information as a series of data points called 'markers' connected by straight line segments. It is useful for showing trends over time.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Invert X-axis (invert_x)

    Invert the X-axis

    Type: bool

    Invert Y-axis (invert_y)

    Invert the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#pie-chart","title":"Pie chart","text":"

    The pie chart is a circular statistical graphic that is divided into slices to illustrate numerical proportions. The arc length of each slice is proportional to the quantity it represents.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Inner Radius (innerRadius)

    Type:

    Stroke Width (strokeWidth)

    Works only if inner radius is lower than 0

    Type:

    Font Size (fontSize)

    Type:

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Width (width)

    Width of the chart

    Type: int

    Default: 640

    Height (height)

    Height of the chart

    Type: int

    Default: 400

    "},{"location":"engines/observable/#scatter-plot","title":"Scatter plot","text":"

    The scatter plot is a chart that uses Cartesian coordinates to display values for two variables for a set of data. The data points are represented as individual dots.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#auto-chart","title":"Auto chart","text":"

    The auto chart is a chart that automatically selects the best chart type based on the data. It is useful for quickly visualizing data without having to manually select a chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/","title":"Plotly","text":"

    The Plotly chart engine supports the following chart types:

    • Bar chart
    • Horizontal bar chart
    • Pie chart
    • Line chart
    • Scatter plot

    Base class for Plotly chart builders.

    Defines supported chart types for Plotly engine.

    Source code in ckanext/charts/chart_builders/plotly.py
    class PlotlyBuilder(BaseChartBuilder):\n    \"\"\"Base class for Plotly chart builders.\n\n    Defines supported chart types for Plotly engine.\n    \"\"\"\n\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [\n            PlotlyBarForm,\n            PlotlyHoriontalBarForm,\n            PlotlyPieForm,\n            PlotlyLineForm,\n            PlotlyScatterForm,\n        ]\n
    "},{"location":"engines/plotly/#bar-chart","title":"Bar chart","text":"

    The bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. For a horizontal bar chart, use the Horizontal bar chart chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#horizontal-bar-chart","title":"Horizontal bar chart","text":"

    The horizontal bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars are plotted horizontally.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#line-chart","title":"Line chart","text":"

    The line chart is a chart that displays information as a series of data points called 'markers' connected by straight line segments. It is useful for showing trends over time.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#pie-chart","title":"Pie chart","text":"

    The pie chart is a circular statistical graphic that is divided into slices to illustrate numerical proportions. The arc length of each slice is proportional to the quantity it represents.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#scatter-plot","title":"Scatter plot","text":"

    The scatter plot is a chart that uses Cartesian coordinates to display values for two variables for a set of data. The data points are represented as individual dots.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Size (size) [Required]

    Select a column for the size

    Type: str

    Size Max (size_max)

    Type:

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    "},{"location":"fetchers/","title":"Fetchers","text":"

    Fetchers are responsible for fetching data from different sources (DataStore, URL, file system, hardcoded data).

    For the current implementation, we're working with resources that are uploaded to the DataStore, so the fetcher will be responsible for fetching the data from the DataStore.

    But it might come in handy to have fetchers for other sources, like URL, file system, etc.

    "},{"location":"fetchers/#implementing-new-fetchers","title":"Implementing new fetchers","text":"

    To register new fetchers, you need to create a new class that inherits from DataFetcherStrategy and implements the fetch_data and make_cache_key methods.

    The fetch_data method should return a pandas DataFrame object with the data that should be displayed in the chart.

    The make_cache_key method should return a unique string that will be used as a key to store the data in the cache.

    See the base class DataFetcherStrategy for more information.

    "},{"location":"fetchers/base/","title":"Base Fetcher","text":"

    All fetchers must inherit from the DataFetcherStrategy class. This class provides the basic structure for fetchers and defines the methods that must be implemented by all fetchers.

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.fetch_data","title":"fetch_data() abstractmethod","text":"

    This method should implement the data fetch logic.

    All the necessary information should be provided in the constructor.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: The fetched data

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.get_cached_data","title":"get_cached_data()","text":"

    Fetch data from the cache.

    RETURNS DESCRIPTION DataFrame | None

    pd.DataFrame | None: The cached data or None if not found

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.invalidate_cache","title":"invalidate_cache()","text":"

    Invalidate the cache for the data fetcher.

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.make_cache_key","title":"make_cache_key() abstractmethod","text":"

    This method should generate a cache key for the fetched data.

    Every data fetcher should implement this method to support caching.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/datastore/","title":"Datastore Fetcher","text":"

    Fetch dataset resource data from the DataStore.

    This fetcher is used to fetch data from the DataStore using the resource ID.

    "},{"location":"fetchers/datastore/#charts.fetchers.DatastoreDataFetcher.__init__","title":"__init__(resource_id, limit=2000000, cache_strategy=None)","text":"

    Initialize the DatastoreDataFetcher.

    PARAMETER DESCRIPTION resource_id

    The ID of the resource to fetch data for.

    TYPE: str

    limit

    The maximum number of rows to fetch.

    TYPE: int DEFAULT: 2000000

    cache_strategy

    The cache strategy to use. If not provided, the configured cache strategy will be used.

    TYPE: str DEFAULT: None

    "},{"location":"fetchers/datastore/#charts.fetchers.DatastoreDataFetcher.fetch_data","title":"fetch_data()","text":"

    Fetch data from the DataStore.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: Data from the DataStore

    "},{"location":"fetchers/datastore/#charts.fetchers.DatastoreDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Generate a cache key for the DataStore data fetcher.

    Uses the resource ID as the part of a cache key.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/file/","title":"File System Data Fetcher","text":"

    Bases: DataFetcherStrategy

    Fetch data from the file system.

    This fetcher is used to fetch data from a file on the file system.

    Supported formats
    • CSV
    • XLSX
    • XLS
    • XML
    "},{"location":"fetchers/file/#charts.fetchers.FileSystemDataFetcher.__init__","title":"__init__(file_path, file_format='csv', cache_strategy=None)","text":"

    Initialize the FileSystemDataFetcher.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    file_format

    The format of the file.

    TYPE: str DEFAULT: 'csv'

    cache_strategy

    The cache strategy to use. If not provided, the configured cache strategy will be used.

    TYPE: str DEFAULT: None

    "},{"location":"fetchers/file/#charts.fetchers.FileSystemDataFetcher.fetch_data","title":"fetch_data()","text":"

    Fetch data from the file system.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: Data fetched from the file system

    "},{"location":"fetchers/file/#charts.fetchers.FileSystemDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Generate a cache key for the FileSystem data fetcher.

    Uses the file path as the part of a cache key.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/hardcode/","title":"Hardcoded Data Fetcher","text":"

    Bases: DataFetcherStrategy

    Fetch hardcoded data.

    This fetcher is used to make a dataframe from hardcoded data, so you can build a chart from it.

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.__init__","title":"__init__(data)","text":"

    Initialize the HardcodedDataFetcher.

    PARAMETER DESCRIPTION data

    The hardcoded data.

    TYPE: dict[str, list[Any]]

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.fetch_data","title":"fetch_data()","text":"

    Transform arbitrary data into a dataframe.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: The hardcoded data as a dataframe

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.invalidate_cache","title":"invalidate_cache()","text":"

    Hardcoded data is not cached

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Hardcoded data is not cached

    "},{"location":"fetchers/url/","title":"URL Data Fetcher","text":"

    Bases: DataFetcherStrategy

    Fetch data from a URL.

    This fetcher is used to fetch data from a URL.

    Supported formats
    • CSV
    • XLSX
    • XLS
    • XML
    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.__init__","title":"__init__(url, file_format='csv', timeout=0, cache_strategy=None)","text":"

    Initialize the URLDataFetcher.

    PARAMETER DESCRIPTION url

    The URL to fetch data from.

    TYPE: str

    file_format

    The format of the file.

    TYPE: str DEFAULT: 'csv'

    timeout

    The timeout for the request in seconds.

    TYPE: int DEFAULT: 0

    cache_strategy

    The cache strategy to use. If not provided, the configured cache strategy will be used.

    TYPE: str DEFAULT: None

    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.fetch_data","title":"fetch_data()","text":"

    Fetch data from the URL.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: Data fetched from the URL

    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Generate a cache key for the URL data fetcher.

    Uses the URL as the part of a cache key.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.make_request","title":"make_request()","text":"

    Make a request to the URL and return the response content.

    RETURNS DESCRIPTION bytes

    The response content

    TYPE: bytes

    RAISES DESCRIPTION DataFetchError

    If an error occurs during the request

    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-\\.\\_]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#ckanext-charts","title":"ckanext-charts","text":"

    This extension, ckanext-charts, provides additional functionality for working with charts in CKAN. It allows users to create, manage, and visualize charts based on data stored in CKAN datasets.

    The extension includes features such as chart creation, chart editing, chart embedding, and chart sharing. It also supports various chart types, including bar charts, line charts, pie charts, and more.

    With ckanext-charts, users can easily generate interactive and visually appealing charts to enhance data analysis and presentation in CKAN.

    See the documentation for more information.

    "},{"location":"#quick-start","title":"Quick start","text":"
    • Install it with PyPi with pip install ckanext-charts[pyarrow]
    • Add charts_view to the list of plugins in your CKAN config (ckan.plugins = charts_view charts_builder_view)
    "},{"location":"#developer-installation","title":"Developer installation","text":"

    To install ckanext-charts for development, activate your CKAN virtualenv and do:

    git clone https://github.com/DataShades/ckanext-charts.git\ncd ckanext-charts\npip install -e '.[dev]'\n
    "},{"location":"#tests","title":"Tests","text":"

    To run the tests, do:

    pytest --ckan-ini=test.ini\n
    "},{"location":"#building-the-documentation","title":"Building the documentation","text":"

    We are using mkdocs to build the documentation. To build and deploy the documentation, do:

    CHARTS_FIELDS=1 mkdocs build && mkdocs gh-deploy\n

    We need to set the CHARTS_FIELDS for our custom handler, that autogenerate documentation for chart types fields.

    If you're working on the documentation, you can run the following command to start a live-reloading server without gathering the chart types fields data. It will speed up the process significantly, as we won't need to wait for the CKAN initialization:

    mkdocs serve -a 127.0.0.1:8001\n
    "},{"location":"#license","title":"License","text":"

    AGPL

    "},{"location":"configuration/","title":"Configuration","text":"

    Configuration options

    There is a number of configuration options available for the extension. You can set them in the CKAN configuration file or using the admin configuration page.

    "},{"location":"configuration/#configuration-options","title":"Configuration options","text":""},{"location":"configuration/#cache-strategy","title":"Cache strategy","text":"

    ckanext.charts.cache_strategy [optional]

    Cache strategy for chart data.

    Options: redis, file_orc, file_csv

    Type: str

    Default: redis

    "},{"location":"configuration/#redis-cache-ttl","title":"Redis cache TTL","text":"

    ckanext.charts.redis_cache_ttl [optional]

    Time to live for the Redis cache in seconds. Set to 0 to disable cache.

    Type: int

    Default: 3600

    "},{"location":"configuration/#file-cache-ttl","title":"File cache TTL","text":"

    ckanext.charts.file_cache_ttl [optional]

    Time to live for the File cache in seconds. Set to 0 to disable cache.

    Type: int

    Default: 3600

    "},{"location":"configuration/#enable-cache","title":"Enable cache","text":"

    ckanext.charts.enable_cache [optional]

    Enable cache for the charts.

    Warning

    If the cache is disabled, the chart data will be fetched from the data source every time the chart is rendered. It could lead to performance issues if the data source is slow or the data is too large.

    Type: bool

    Default: true

    "},{"location":"configuration/#include-htmx","title":"Include HTMX","text":"

    ckanext.charts.include_htmx_asset [optional]

    Include HTMX assets. Could be disabled if another plugins are including it.

    Type: bool

    Default: true

    "},{"location":"configuration/#reinit-ckan-js","title":"Reinit CKAN JS","text":"

    ckanext.charts.reinit_ckan_js_modules [optional]

    Reinit CKAN JS modules after HTMX swap.

    Type: bool

    Default: false

    "},{"location":"configuration/#allow-anonymous-users-to-build-charts","title":"Allow anonymous users to build charts","text":"

    ckanext.charts.allow_anon_building_charts [optional]

    By default, only authenticated users can build charts. If you want to allow anonymous users to build charts, set this option to true.

    Type: bool

    Default: false

    "},{"location":"configuration/#admin-config-page","title":"Admin config page","text":"

    The extension provides an admin configuration page where you can set all the listed configuration options. The admin page available only using an extension ckanext-admin-panel. The admin panel is a separate extension that provides an alternative admin interface for CKAN. It allows you to manage CKAN settings and other extensions settings through the web interface.

    This page could be accessed by the following URL: /admin-panel/charts/config, but it will be registered only if the ckanext-admin-panel is installed and enabled.

    "},{"location":"helpers/","title":"Helper Functions","text":""},{"location":"helpers/#charts.helpers.charts_allow_anon_building_charts","title":"charts_allow_anon_building_charts()","text":"

    Check if anonymous users are allowed to build charts.

    RETURNS DESCRIPTION bool

    True if anonymous users are allowed to build charts, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_allow_anon_building_charts() -> bool:\n    \"\"\"Check if anonymous users are allowed to build charts.\n\n    Returns:\n        bool: True if anonymous users are allowed to build charts, False otherwise.\n    \"\"\"\n    return config.allow_anon_building_charts()\n
    "},{"location":"helpers/#charts.helpers.charts_get_resource_columns","title":"charts_get_resource_columns(resource_id)","text":"

    Get the columns of the given resource.

    PARAMETER DESCRIPTION resource_id

    Resource ID

    TYPE: str

    RETURNS DESCRIPTION str

    JSON string of columns options

    TYPE: str

    Source code in ckanext/charts/helpers.py
    def charts_get_resource_columns(resource_id: str) -> str:\n    \"\"\"Get the columns of the given resource.\n\n    Args:\n        resource_id: Resource ID\n\n    Returns:\n        str: JSON string of columns options\n    \"\"\"\n    fetcher = DatastoreDataFetcher(resource_id)\n\n    return json.dumps(\n        [{\"id\": col, \"title\": col} for col in fetcher.fetch_data().columns],\n    )\n
    "},{"location":"helpers/#charts.helpers.charts_include_htmx_asset","title":"charts_include_htmx_asset()","text":"

    Checks if the HTMX asset should be included.

    RETURNS DESCRIPTION bool

    True if the HTMX asset should be included, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_include_htmx_asset() -> bool:\n    \"\"\"Checks if the HTMX asset should be included.\n\n    Returns:\n        bool: True if the HTMX asset should be included, False otherwise.\n    \"\"\"\n    return config.include_htmx_asset()\n
    "},{"location":"helpers/#charts.helpers.charts_reinit_ckan_js_modules","title":"charts_reinit_ckan_js_modules()","text":"

    Checks if CKAN JS modules should be reinitialized.

    RETURNS DESCRIPTION bool

    True if CKAN JS modules should be reinitialized, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_reinit_ckan_js_modules() -> bool:\n    \"\"\"Checks if CKAN JS modules should be reinitialized.\n\n    Returns:\n        bool: True if CKAN JS modules should be reinitialized, False otherwise.\n    \"\"\"\n    return config.reinit_ckan_js_modules()\n
    "},{"location":"helpers/#charts.helpers.charts_user_is_authenticated","title":"charts_user_is_authenticated()","text":"

    Check if the user is authenticated.

    RETURNS DESCRIPTION bool

    True if the user is authenticated, False otherwise.

    TYPE: bool

    Source code in ckanext/charts/helpers.py
    def charts_user_is_authenticated() -> bool:\n    \"\"\"Check if the user is authenticated.\n\n    Returns:\n        bool: True if the user is authenticated, False otherwise.\n    \"\"\"\n    return tk.current_user.is_authenticated\n
    "},{"location":"helpers/#charts.helpers.get_available_chart_engines_options","title":"get_available_chart_engines_options()","text":"

    Get the available chart engines.

    RETURNS DESCRIPTION list[dict[str, str]]

    List of chart engines options

    Source code in ckanext/charts/helpers.py
    def get_available_chart_engines_options() -> list[dict[str, str]]:\n    \"\"\"Get the available chart engines.\n\n    Returns:\n        List of chart engines options\n    \"\"\"\n    return [{\"value\": engine, \"text\": engine} for engine in get_chart_engines()]\n
    "},{"location":"helpers/#charts.helpers.get_file_cache_size","title":"get_file_cache_size()","text":"

    Get the size of the file cache in a human-readable format.

    RETURNS DESCRIPTION str

    Human-readable file cache size

    TYPE: str

    Source code in ckanext/charts/helpers.py
    def get_file_cache_size() -> str:\n    \"\"\"Get the size of the file cache in a human-readable format.\n\n    Returns:\n        str: Human-readable file cache size\n    \"\"\"\n    return utils.printable_file_size(count_file_cache_size())\n
    "},{"location":"helpers/#charts.helpers.get_redis_cache_size","title":"get_redis_cache_size()","text":"

    Get the size of the Redis cache in a human-readable format.

    RETURNS DESCRIPTION str

    Human-readable Redis cache size

    TYPE: str

    Source code in ckanext/charts/helpers.py
    def get_redis_cache_size() -> str:\n    \"\"\"Get the size of the Redis cache in a human-readable format.\n\n    Returns:\n        str: Human-readable Redis cache size\n    \"\"\"\n    return utils.printable_file_size(count_redis_cache_size())\n
    "},{"location":"install/","title":"Installation","text":""},{"location":"install/#requirements","title":"Requirements","text":"

    Requires Redis 7+

    Compatibility with core CKAN versions:

    CKAN version Compatible? 2.9 and earlier no 2.10+ yes"},{"location":"install/#installation_1","title":"Installation","text":"
    1. Install the extension from PyPI:

      pip install ckanext-charts\n

      If you want to use ORC file cache, you have to install the extension with the pyarrow extra:

      pip install ckanext-charts[pyarrow]\n

    2. Enable the view and builder plugins in your CKAN configuration file (e.g. ckan.ini or production.ini):

      ckan.plugins = ... charts_view charts_builder_view ...\n
    "},{"location":"install/#dependencies","title":"Dependencies","text":"

    The extension requires the following CKAN extensions to be installed and enabled:

    1. ckanext-scheming: We're using the scheming extension to create custom forms for the chart builders.

    2. ckanext-admin-panel (optional): If you want to use the admin configuration page, you need to install and enable this extension. The admin panel is a separate extension that provides an alternative admin interface for CKAN. It allows you to manage CKAN settings and other extensions settings through the web interface and significantly extends the default CKAN admin interface.

    "},{"location":"troubleshooting/","title":"Troubleshooting","text":"

    ImportError: lxml.html.clean module is now a separate project lxml_html_clean

    Install lxml[html_clean] or lxml_html_clean directly using pip.

    "},{"location":"usage/","title":"Usage","text":""},{"location":"usage/#basic-usage","title":"Basic usage","text":"

    This extension offers two plugins: charts_view and charts_builder_view. The first plugin is a standard chart builder designed for system administrators or anyone with permission to edit or create a resource view. Creating a preview using this plugin generates a static chart with saved settings. This chart retains the settings and will always be rendered in the same way.

    The charts_builder_view plugin does not have any special settings during the creation or editing stages. Instead, it renders a chart builder JS widget on a resource page, allowing any user to interact with the resource data and create a chart that meets their needs. In the future, we plan to implement a feature that will allow users to save their charts.

    "},{"location":"usage/#restrict-user-chart-builder-for-anonymous-users","title":"Restrict user chart builder for anonymous users","text":"

    The user chart builder could be restricted to only authenticated users. See the config settings section for more information. In this case, user will be forced to log in to build a chart. After the user logs in, user will be redirected to the chart builder page back.

    "},{"location":"utils/","title":"Utility Functions","text":""},{"location":"utils/#charts.utils.build_chart_for_data","title":"build_chart_for_data(settings, data)","text":"

    Build chart for the given dataframe and settings.

    PARAMETER DESCRIPTION settings

    Chart settings

    TYPE: dict[str, Any]

    data

    Dataframe with data

    TYPE: DataFrame

    RETURNS DESCRIPTION str | None

    Chart config as JSON string

    Source code in ckanext/charts/utils.py
    def build_chart_for_data(settings: dict[str, Any], data: pd.DataFrame) -> str | None:\n    \"\"\"Build chart for the given dataframe and settings.\n\n    Args:\n        settings: Chart settings\n        data: Dataframe with data\n\n    Returns:\n        Chart config as JSON string\n    \"\"\"\n    return _build_chart(settings, data)\n
    "},{"location":"utils/#charts.utils.build_chart_for_resource","title":"build_chart_for_resource(settings, resource_id)","text":"

    Build chart for the given resource ID.

    Uses a DatastoreDataFetcher to fetch data from the resource.

    PARAMETER DESCRIPTION settings

    Chart settings

    TYPE: dict[str, Any]

    resource_id

    Resource ID

    TYPE: str

    RETURNS DESCRIPTION str | None

    str | None: Chart config as JSON string or None if the chart can't be built

    Source code in ckanext/charts/utils.py
    def build_chart_for_resource(settings: dict[str, Any], resource_id: str) -> str | None:\n    \"\"\"Build chart for the given resource ID.\n\n    Uses a DatastoreDataFetcher to fetch data from the resource.\n\n    Args:\n        settings: Chart settings\n        resource_id: Resource ID\n\n    Returns:\n        str | None: Chart config as JSON string or None if the chart can't be built\n    \"\"\"\n    settings.pop(\"__extras\", None)\n\n    try:\n        df = DatastoreDataFetcher(resource_id).fetch_data()\n    except tk.ValidationError:\n        return None\n\n    return _build_chart(settings, df)\n
    "},{"location":"utils/#charts.utils.can_view","title":"can_view(data_dict)","text":"

    Check if the resource can be viewed as a chart.

    For now, we work only with resources stored with the DataStore.

    PARAMETER DESCRIPTION data_dict

    Resource data dictionary

    TYPE: dict[str, Any]

    RETURNS DESCRIPTION bool

    True if the resource can be viewed as a chart, False otherwise

    TYPE: bool

    Source code in ckanext/charts/utils.py
    def can_view(data_dict: dict[str, Any]) -> bool:\n    \"\"\"Check if the resource can be viewed as a chart.\n\n    For now, we work only with resources stored with the DataStore.\n\n    Args:\n        data_dict: Resource data dictionary\n\n    Returns:\n        bool: True if the resource can be viewed as a chart, False otherwise\n    \"\"\"\n    if data_dict[\"resource\"].get(\"datastore_active\"):\n        return True\n\n    # TODO: Add support for XML, XLS, XLSX, and other formats tabular data?\n    # if data_dict[\"resource\"][\"format\"].lower() == \"xml\":\n    #     return True\n\n    return False\n
    "},{"location":"utils/#charts.utils.get_chart_form_builder","title":"get_chart_form_builder(engine, chart_type)","text":"

    Get form builder for the given engine and chart type.

    Source code in ckanext/charts/utils.py
    def get_chart_form_builder(engine: str, chart_type: str):\n    \"\"\"Get form builder for the given engine and chart type.\"\"\"\n    builders = get_chart_engines()\n\n    if engine not in builders:\n        raise NotImplementedError(f\"Engine {engine} is not supported\")\n\n    return builders[engine].get_form_for_type(chart_type)\n
    "},{"location":"utils/#charts.utils.get_column_options","title":"get_column_options(resource_id)","text":"

    Get column options for the given resource.

    PARAMETER DESCRIPTION resource_id

    Resource ID

    TYPE: str

    RETURNS DESCRIPTION list[dict[str, str]]

    List of column options

    Source code in ckanext/charts/utils.py
    def get_column_options(resource_id: str) -> list[dict[str, str]]:\n    \"\"\"Get column options for the given resource.\n\n    Args:\n        resource_id: Resource ID\n\n    Returns:\n        List of column options\n    \"\"\"\n    df = DatastoreDataFetcher(resource_id).fetch_data()\n\n    return [{\"text\": col, \"value\": col} for col in df.columns]\n
    "},{"location":"utils/#charts.utils.printable_file_size","title":"printable_file_size(size_bytes)","text":"

    Convert file size in bytes to human-readable format.

    PARAMETER DESCRIPTION size_bytes

    File size in bytes

    TYPE: int

    RETURNS DESCRIPTION str

    Human-readable file size

    TYPE: str

    Examples:

    >>> printable_file_size(123456789)\n'117.7 MB'\n
    >>> printable_file_size(7777)\n'7.6 KB'\n
    Source code in ckanext/charts/utils.py
    def printable_file_size(size_bytes: int) -> str:\n    \"\"\"Convert file size in bytes to human-readable format.\n\n    Args:\n        size_bytes: File size in bytes\n\n    Returns:\n        str: Human-readable file size\n\n    Examples:\n        >>> printable_file_size(123456789)\n        '117.7 MB'\n\n        >>> printable_file_size(7777)\n        '7.6 KB'\n    \"\"\"\n    if size_bytes == 0:\n        return \"0 bytes\"\n\n    size_name = (\"bytes\", \"KB\", \"MB\", \"GB\", \"TB\")\n    i = int(math.floor(math.log(size_bytes, 1024)))\n    p = math.pow(1024, i)\n    s = round(float(size_bytes) / p, 1)\n\n    return f\"{s} {size_name[i]}\"\n
    "},{"location":"validators/","title":"Validators","text":""},{"location":"validators/#charts.logic.validators.charts_if_empty_same_as","title":"charts_if_empty_same_as(other_key)","text":"

    A custom version of if_empty_same_as validator for charts.

    This validator is used to set the value of a field to the value of another field if it is empty or missing.

    PARAMETER DESCRIPTION other_key

    The key of the field to copy the value from

    TYPE: str

    RETURNS DESCRIPTION Callable[..., Any]

    Callable[..., Any]: The validator function

    Source code in ckanext/charts/logic/validators.py
    def charts_if_empty_same_as(other_key: str) -> Callable[..., Any]:\n    \"\"\"A custom version of if_empty_same_as validator for charts.\n\n    This validator is used to set the value of a field to the value of another\n    field if it is empty or missing.\n\n    Args:\n        other_key (str): The key of the field to copy the value from\n\n    Returns:\n        Callable[..., Any]: The validator function\n    \"\"\"\n\n    def callable(key, data, errors, context):\n        value = data.get(key)\n        if not value or value is tk.missing:\n            try:\n                data[key] = data[key[:-1] + (other_key,)]\n            except KeyError:\n                data[key] = data.get((\"__extras\",), {}).get(other_key, \"\")\n\n    return callable\n
    "},{"location":"validators/#charts.logic.validators.charts_list_length_validator","title":"charts_list_length_validator(max_length)","text":"

    A validator to check the length of a list.

    PARAMETER DESCRIPTION max_length

    The maximum length of the list

    TYPE: int

    RETURNS DESCRIPTION Callable[..., Any]

    Callable[..., Any]: The validator function

    Source code in ckanext/charts/logic/validators.py
    def charts_list_length_validator(max_length: int) -> Callable[..., Any]:\n    \"\"\"A validator to check the length of a list.\n\n    Args:\n        max_length (int): The maximum length of the list\n\n    Returns:\n        Callable[..., Any]: The validator function\n    \"\"\"\n    def callable(\n        key: types.FlattenKey,\n        data: types.FlattenDataDict,\n        errors: types.FlattenErrorDict,\n        context: types.Context,\n    ):\n        if len(data[key]) > max_length:\n            raise tk.Invalid(tk._(\"Length must be less than {0}\").format(max_length))\n\n    return callable\n
    "},{"location":"validators/#charts.logic.validators.charts_list_to_csv","title":"charts_list_to_csv(data)","text":"

    Convert a list of strings to a CSV string.

    PARAMETER DESCRIPTION data

    The data to convert

    TYPE: list[str] | str

    RETURNS DESCRIPTION str

    The comma separated string

    TYPE: str

    Source code in ckanext/charts/logic/validators.py
    def charts_list_to_csv(data: list[str] | str) -> str:\n    \"\"\"Convert a list of strings to a CSV string.\n\n    Args:\n        data (list[str] | str): The data to convert\n\n    Returns:\n        str: The comma separated string\n    \"\"\"\n    if not isinstance(data, list):\n        return data\n\n    return \", \".join(data)\n
    "},{"location":"validators/#charts.logic.validators.charts_strategy_support","title":"charts_strategy_support(strategy)","text":"

    Check if the cache strategy is supported.

    PARAMETER DESCRIPTION strategy

    The cache strategy

    TYPE: str

    RETURNS DESCRIPTION str

    The cache strategy if it is supported

    TYPE: str

    RAISES DESCRIPTION Invalid

    If the cache strategy is not supported

    Source code in ckanext/charts/logic/validators.py
    def charts_strategy_support(strategy: str) -> str:\n    \"\"\"Check if the cache strategy is supported.\n\n    Args:\n        strategy (str): The cache strategy\n\n    Returns:\n        str: The cache strategy if it is supported\n\n    Raises:\n        tk.Invalid: If the cache strategy is not supported\n    \"\"\"\n    if strategy not in const.SUPPORTED_CACHE_STRATEGIES:\n        raise tk.Invalid(tk._(\"Invalid cache strategy\"))\n\n    if strategy == const.CACHE_FILE_ORC:\n        try:\n            from pyarrow import orc as _  # noqa\n        except ImportError:\n            raise tk.Invalid(\n                tk._(\"Can't use File Orc cache strategy. PyArrow is not installed\"),\n            ) from None\n\n    if not strategy:\n        return const.DEFAULT_CACHE_STRATEGY\n\n    return strategy\n
    "},{"location":"validators/#charts.logic.validators.charts_to_list_if_string","title":"charts_to_list_if_string(value)","text":"

    Convert a string to a list.

    PARAMETER DESCRIPTION value

    The value to convert

    TYPE: Any

    RETURNS DESCRIPTION Any

    list[Any]: The value in a list

    Source code in ckanext/charts/logic/validators.py
    def charts_to_list_if_string(value: Any) -> Any:\n    \"\"\"Convert a string to a list.\n\n    Args:\n        value (Any): The value to convert\n\n    Returns:\n        list[Any]: The value in a list\n    \"\"\"\n    if isinstance(value, str):\n        return [value]\n\n    return value\n
    "},{"location":"validators/#charts.logic.validators.charts_validate_extras","title":"charts_validate_extras(key, data, errors, context)","text":"

    Validate charts settings according to the chart type and engine schema.

    PARAMETER DESCRIPTION key

    The key of the field

    TYPE: FlattenKey

    data

    The data to validate

    TYPE: FlattenDataDict

    errors

    The errors dict

    TYPE: FlattenErrorDict

    context

    The context

    TYPE: Context

    Source code in ckanext/charts/logic/validators.py
    def charts_validate_extras(\n    key: types.FlattenKey,\n    data: types.FlattenDataDict,\n    errors: types.FlattenErrorDict,\n    context: types.Context,\n):\n    \"\"\"Validate charts settings according to the chart type and engine schema.\n\n    Args:\n        key (types.FlattenKey): The key of the field\n        data (types.FlattenDataDict): The data to validate\n        errors (types.FlattenErrorDict): The errors dict\n        context (types.Context): The context\n    \"\"\"\n    settings = _extract_setting(data)\n\n    if \"engine\" not in settings or \"type\" not in settings:\n        builder = DEFAULT_CHART_FORM\n    else:\n        builder = utils.get_chart_form_builder(settings[\"engine\"], settings[\"type\"])\n\n    settings, err = tk.navl_validate(\n        settings,\n        builder(settings[\"resource_id\"]).get_validation_schema(\n            context.get(\"_for_show\", False),\n        ),\n        {},\n    )\n\n    # TODO: do we have a better way to handle this? Seems like a hack\n    for k, v in settings.items():\n        data[(k,)] = v\n\n    for k, v in settings.pop(\"__extras\", {}).items():\n        data[(k,)] = v\n\n    for k, v in err.items():\n        errors[(k,)] = v\n
    "},{"location":"validators/#charts.logic.validators.float_validator","title":"float_validator(value)","text":"

    A validator for decimal numbers.

    PARAMETER DESCRIPTION value

    The value to validate

    TYPE: Any

    RETURNS DESCRIPTION float

    The value as a float

    TYPE: float

    Source code in ckanext/charts/logic/validators.py
    def float_validator(value: Any) -> float:\n    \"\"\"A validator for decimal numbers.\n\n    Args:\n        value (Any): The value to validate\n\n    Returns:\n        float: The value as a float\n    \"\"\"\n    try:\n        return float(value)\n    except ValueError:\n        raise tk.Invalid(tk._(\"Must be a decimal number\")) from None\n
    "},{"location":"caching/","title":"Caching","text":"

    The extension implement a cache strategy to store the data fetched from the different sources.

    There are three cache strategies available:

    1. redis
    2. file_orc
    3. file_csv.
    "},{"location":"caching/#file-cache","title":"File cache","text":"

    The file cache works by storing the data in an orc or csv file in the filesystem. The redis cache stores the data in a Redis database. The cache strategy can be changed at the CKAN configuration level through the admin interface or in a configuration file.

    The file-type cache strategy stores the data in a file in the filesystem. The file cache is stored in the ckanext-charts directory in the CKAN storage path. The file cache is stored in an orc or csv file format.

    Warning

    Using file_orc cache strategy requires the pyarrow python library to be installed.

    "},{"location":"caching/#redis-cache","title":"Redis cache","text":"

    The redis cache strategy stores the data in a Redis database.

    Each redis key has a ckanext-charts:* prefix and store the data as a CSV string.

    Note

    You need to have a Redis server running to use the redis cache strategy.

    "},{"location":"caching/#cache-ttl","title":"Cache TTL","text":"

    The cache TTL can be set in the CKAN configuration file. The default value is 3600 seconds (1 hour). The cache TTL can be set to 0 to disable the cache.

    The redis and file-type cache has separate TTL settings:

    • The redis cache TTL can be set with the ckanext.charts.redis_cache_ttl configuration option.
    • The file cache TTL can be set with the ckanext.charts.file_cache_ttl configuration option.
    "},{"location":"caching/#disable-cache","title":"Disable cache","text":"

    Cache could be disabled by setting ckanext.charts.enable_cache to false. In this case the data will be fetched from the source every time the chart is rendered. It could be useful for debugging purposes. But using it in production is not recommended, as it could lead to performance issues.

    "},{"location":"caching/base/","title":"Base Cache Strategy","text":"

    To implement a custom cache strategy, you need to create a new class that extends the CacheStrategy class and implement the abstract methods.

    See a naive implementation of a memcached cache strategy below:

    from io import BytesIO\n\nfrom pymemcache.client import base\nimport pandas as pd\n\nimport ckanext.charts.config as config\nfrom ckanext.charts.cache import CacheStrategy\n\nclass MemcachedCache(CacheStrategy):\n    \"\"\"Cache data to Memcached\"\"\"\n\n    def __init__(self):\n        self.client = base.Client(('localhost', 11211))\n\n    def get_data(self, key: str) -> pd.DataFrame | None:\n        \"\"\"Return data from cache if exists\"\"\"\n        try:\n            raw_data = self.client.get(key)\n\n            if not raw_data:\n                return None\n\n            return pd.read_csv(BytesIO(raw_data))\n        except Exception:\n            log.exception(f\"Failed to get data for key: {key}\")\n            return None\n\n    def set_data(self, key: str, data: pd.DataFrame):\n        \"\"\"Serialize data and save to Memcached\"\"\"\n        cache_ttl = config.get_memcached_cache_ttl()\n\n        try:\n            serialized_data = data.to_csv(index=False).encode('utf-8')\n            self.client.set(key, serialized_data, expire=cache_ttl)\n        except Exception:\n            log.exception(f\"Failed to save data to Memcached for key: {key}\")\n\n    def invalidate(self, key: str):\n        \"\"\"Invalidate cache by key\"\"\"\n        try:\n            self.client.delete(key)\n        except Exception:\n            log.exception(f\"Failed to invalidate cache for key: {key}\")\n

    Bases: ABC

    Cache strategy interface.

    Defines the abstracts methods for cache strategies.

    "},{"location":"caching/base/#charts.cache.CacheStrategy.get_data","title":"get_data(key) abstractmethod","text":"

    Return data from cache if exists.

    PARAMETER DESCRIPTION key

    The cache key to retrieve the data.

    TYPE: str

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/base/#charts.cache.CacheStrategy.invalidate","title":"invalidate(key) abstractmethod","text":"

    Invalidate cache by key.

    PARAMETER DESCRIPTION key

    The cache key to invalidate.

    TYPE: str

    "},{"location":"caching/base/#charts.cache.CacheStrategy.set_data","title":"set_data(key, data) abstractmethod","text":"

    Store data to cache.

    PARAMETER DESCRIPTION key

    The cache key to store the data.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/","title":"File Cache","text":""},{"location":"caching/file/#charts.cache.FileCache","title":"FileCache","text":"

    Bases: CacheStrategy

    Cache data as file.

    We store the cached files in a separate folder in the CKAN storage.

    "},{"location":"caching/file/#charts.cache.FileCache.generate_unique_consistent_filename","title":"generate_unique_consistent_filename(key)","text":"

    Generate unique and consistent filename based on the key.

    PARAMETER DESCRIPTION key

    The cache key to generate the filename.

    TYPE: str

    RETURNS DESCRIPTION str

    The filename.

    "},{"location":"caching/file/#charts.cache.FileCache.get_data","title":"get_data(key)","text":"

    Return data from cache if exists.

    PARAMETER DESCRIPTION key

    The cache key to retrieve the data.

    TYPE: str

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCache.invalidate","title":"invalidate(key)","text":"

    Remove data from cache.

    PARAMETER DESCRIPTION key

    The cache key to invalidate.

    TYPE: str

    "},{"location":"caching/file/#charts.cache.FileCache.is_file_cache_expired","title":"is_file_cache_expired(file_path) staticmethod","text":"

    Check if file cache is expired.

    If TTL is 0 then cache never expires.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    RETURNS DESCRIPTION bool

    True if file cache is expired, otherwise False.

    "},{"location":"caching/file/#charts.cache.FileCache.make_file_path_from_key","title":"make_file_path_from_key(key)","text":"

    Generate file path based on the key

    PARAMETER DESCRIPTION key

    The cache key to generate the file path.

    TYPE: str

    RETURNS DESCRIPTION str

    The file path.

    "},{"location":"caching/file/#charts.cache.FileCache.read_data","title":"read_data(file) abstractmethod","text":"

    Read cached data from a file object.

    PARAMETER DESCRIPTION file

    The file object to read the data.

    TYPE: IO

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCache.set_data","title":"set_data(key, data)","text":"

    Store data to cache.

    PARAMETER DESCRIPTION key

    The cache key to store the data.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/#charts.cache.FileCache.write_data","title":"write_data(file_path, data) abstractmethod","text":"

    Defines how to write data to a file.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/#charts.cache.FileCacheORC","title":"FileCacheORC","text":"

    Bases: FileCache

    Cache data as ORC file

    "},{"location":"caching/file/#charts.cache.FileCacheORC.read_data","title":"read_data(file)","text":"

    Read cached data from an ORC file.

    PARAMETER DESCRIPTION file

    The file object to read the data.

    TYPE: IO

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCacheORC.write_data","title":"write_data(file_path, data)","text":"

    Write data to an ORC file.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/file/#charts.cache.FileCacheCSV","title":"FileCacheCSV","text":"

    Bases: FileCache

    Cache data as CSV file

    "},{"location":"caching/file/#charts.cache.FileCacheCSV.read_data","title":"read_data(file)","text":"

    Read cached data from a CSV file.

    PARAMETER DESCRIPTION file

    The file object to read the data.

    TYPE: IO

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/file/#charts.cache.FileCacheCSV.write_data","title":"write_data(file_path, data)","text":"

    Write data to a CSV file.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    "},{"location":"caching/redis/","title":"Redis Cache","text":"

    Bases: CacheStrategy

    Cache data to Redis as a CSV string

    "},{"location":"caching/redis/#charts.cache.RedisCache.get_data","title":"get_data(key)","text":"

    Return data from cache if exists.

    PARAMETER DESCRIPTION key

    The cache key to retrieve the data.

    TYPE: str

    RETURNS DESCRIPTION DataFrame | None

    The data if exists, otherwise None.

    "},{"location":"caching/redis/#charts.cache.RedisCache.invalidate","title":"invalidate(key)","text":"

    Remove data from cache.

    PARAMETER DESCRIPTION key

    The cache key to invalidate.

    TYPE: str

    "},{"location":"caching/redis/#charts.cache.RedisCache.set_data","title":"set_data(key, data)","text":"

    Serialize data and save to Redis.

    PARAMETER DESCRIPTION key

    The cache key to store the data.

    TYPE: str

    data

    The data to be stored.

    TYPE: DataFrame

    RAISES DESCRIPTION Exception

    If failed to save data to Redis.

    "},{"location":"engines/","title":"Index","text":"

    The ckanext-charts implements supports different chart engines, such as plotly, observable and chartjs.

    Each engine consists of two classes - chart builder and form builder. The chart builder is responsible for generating a JSON-string representation of the chart data, that will be passed to a respective JS module, that will render a chart based on the data.

    The form builder is responsible for generating a form that allows users to configure the chart from the UI.

    Also, you can implement support of a chart library of your choice by creating a custom chart engine. Read more about it here.

    "},{"location":"engines/chartjs/","title":"Chartjs","text":"

    The Chart.JS chart engine supports the following chart types:

    • Bar chart
    • Horizontal bar chart
    • Line chart
    • Pie chart
    • Doughnut chart
    • Scatter plot
    • Bubble chart
    • Radar chart
    Source code in ckanext/charts/chart_builders/chartjs.py
    class ChartJsBuilder(BaseChartBuilder):\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [\n            ChartJSBarForm,\n            ChartJSHorizontalBarForm,\n            ChartJSLineForm,\n            ChartJSPieForm,\n            ChartJSDoughnutForm,\n            ChartJSScatterForm,\n            ChartJSBubbleForm,\n            ChartJSRadarForm,\n        ]\n\n    def _create_zoom_and_title_options(self, options: dict[str, Any]) -> dict[str, Any]:\n        \"\"\"Add zoom and title plugin options to the provided options dictionary\"\"\"\n        if \"plugins\" not in options:\n            options[\"plugins\"] = {}\n\n        options[\"plugins\"].update(\n            {\n                \"zoom\": {\n                    \"zoom\": {\n                        \"wheel\": {\"enabled\": True},\n                        \"pinch\": {\"enabled\": True},\n                        \"drag\": {\"enabled\": True},\n                        \"mode\": \"xy\",\n                    },\n                    \"pan\": {\n                        \"enabled\": True,\n                        \"modifierKey\": \"shift\",\n                        \"mode\": \"xy\",\n                    },\n                },\n                \"title\": {\n                    \"display\": True,\n                    \"position\": \"bottom\",\n                },\n            },\n        )\n        return options\n
    "},{"location":"engines/chartjs/#bar-chart","title":"Bar chart","text":"

    The bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. For a horizontal bar chart, use the Horizontal bar chart chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select one or more columns for the Y-axis

    Type: List[str]

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#horizontal-bar-chart","title":"Horizontal bar chart","text":"

    The horizontal bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars are plotted horizontally.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select one or more columns for the Y-axis

    Type: List[str]

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#line-chart","title":"Line chart","text":"

    The line chart is a chart that displays information as a series of data points called 'markers' connected by straight line segments. It is useful for showing trends over time.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select one or more columns for the Y-axis

    Type: List[str]

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Invert X-axis (invert_x)

    Invert the X-axis

    Type: bool

    Invert Y-axis (invert_y)

    Invert the Y-axis

    Type: bool

    "},{"location":"engines/chartjs/#pie-chart","title":"Pie chart","text":"

    The pie chart is a circular statistical graphic that is divided into slices to illustrate numerical proportions. The arc length of each slice is proportional to the quantity it represents.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#doughnut-chart","title":"Doughnut chart","text":"

    The doughnut chart is a variant of the pie chart, with a hole in the center. It is useful for showing the relationship of parts to a whole.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#scatter-plot","title":"Scatter plot","text":"

    The scatter plot is a chart that uses Cartesian coordinates to display values for two variables for a set of data. The data points are represented as individual dots.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/chartjs/#bubble-chart","title":"Bubble chart","text":"

    The bubble chart is a chart that displays data points as bubbles. The size of the bubble represents a third dimension of the data.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Size (size) [Required]

    Select a column for the size

    Type: str

    "},{"location":"engines/chartjs/#radar-chart","title":"Radar chart","text":"

    The radar chart is a chart that displays multivariate data in the form of a two-dimensional chart of three or more quantitative variables represented on axes starting from the same point. The data points are connected by a line to form a polygon.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Doughnut, Scatter, Bubble, Radar

    Names (names) [Required]

    Type: str

    Values (values) [Required]

    Select 3 or more different categorical variables (dimensions)

    Type: List[str]

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/custom/","title":"Custom chart engine","text":""},{"location":"engines/custom/#implementing-new-chart-engines-support","title":"Implementing new chart engines support","text":"

    Implementing support for a new chart engine includes multiple steps and changes in Python, HTML, and JavaScript. Starting from the Python code:

    1. Create a new builder class at ckanext.charts.chart_builder that inherits from BaseChartBuilder and implements the get_supported_forms method. This method must return a list of classes that represent supported chart types forms.

    2. Each form type builder must be connected with a respective chart type builder.

    3. The chart type builder must implement a to_json method that will return a dumped JSON data, which will be passed to a JS script.

    4. The form type builder must implement a get_form_fields method that will return a list of all form fields that will be rendered for the user, allowing them to provide all the necessary information for a chart.

    5. Register your chart engine by adding the builder class to get_chart_engines in ckanext.charts.chart_builder.__init__.py.

    A full example of an implementation of bar chart for obvervable plot library.

    from __future__ import annotations\n\nimport json\nfrom typing import Any\n\nimport ckanext.charts.exception as exception\nfrom ckanext.charts.chart_builders.base import BaseChartBuilder, BaseChartForm\n\n\nclass ObservableBuilder(BaseChartBuilder):\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [ObservableBarForm]\n\n\nclass ObservableBarBuilder(ObservableBuilder):\n    def to_json(self) -> str:\n        return json.dumps(\n            {\n                \"type\": \"bar\",\n                \"data\": self.df.to_dict(orient=\"records\"),\n                \"settings\": self.settings,\n            }\n        )\n\n\nclass ObservableBarForm(BaseChartForm):\n    name = \"Bar\"\n    builder = ObservableBarBuilder\n\n    def fill_field(self, choices: list[dict[str, str]]) -> dict[str, str]:\n        field = self.color_field(choices)\n        field.update({\"field_name\": \"fill\", \"label\": \"Fill\"})\n\n        return field\n\n    def get_form_fields(self):\n        columns = [{\"value\": col, \"label\": col} for col in self.df.columns]\n        chart_types = [\n            {\"value\": form.name, \"label\": form.name}\n            for form in self.builder.get_supported_forms()\n        ]\n\n        return [\n            self.title_field(),\n            self.description_field(),\n            self.engine_field(),\n            self.type_field(chart_types),\n            self.x_axis_field(columns),\n            self.y_axis_field(columns),\n            self.fill_field(columns),\n            self.opacity_field(),\n            self.limit_field(),\n        ]\n
    "},{"location":"engines/custom/#vendor-and-custom-js","title":"Vendor and custom JS","text":"

    Another step is to register JS/CSS vendor libraries of the chart you want to use. Refer to CKAN documentation to read about adding CSS and JavaScript files using Webassets.

    You also will need a CKAN JS module, that will be responsible for rendering the Chart. This module will work with the vendor library and will be responsible for rendering the chart in the container.

    This module must be registered inside a webassets.yml as well.

        ckan.module(\"charts-render-observable\", function ($, _) {\n        \"use strict\";\n\n        return {\n            options: {\n                config: null\n            },\n\n            initialize: function () {\n                $.proxyAll(this, /_/);\n\n                if (!this.options.config) {\n                    console.error(\"No configuration provided\");\n                    return;\n                }\n\n                var plot;\n\n                switch (this.options.config.type) {\n                    case \"bar\":\n                        plot = Plot.barY(this.options.config.data, this.options.config.settings).plot();\n                        break;\n                    default:\n                        return;\n                }\n\n                this.el[0].replaceChildren(plot);\n            }\n        };\n    });\n

    "},{"location":"engines/custom/#html-container","title":"HTML container","text":"

    And an HTML file, that will provide a proper container and include your JS module with data-module.

        {% asset \"charts/observable\" %}\n\n    {% if chart %}\n        <div id=\"chart-container\" data-module=\"charts-render-observable\" data-module-config=\"{{ chart }}\"></div>\n    {% else %}\n        <p class=\"text-muted\">\n            {{ _(\"Cannot build chart with current settings\") }}\n        </p>\n    {% endif %}\n

    Note, that we should add {% asset \"charts/observable\" %} not only here, but in charts_form.html too.

    The reason for having a separate HTML file and JS module is that different libraries may require different types of container elements (such as div, canvas, etc.) to initialize or may need additional boilerplate code to build a chart. There's no easy way to abstract this, so you have to implement these things yourself.

    "},{"location":"engines/observable/","title":"Observable","text":"

    The Observable Plot chart engine supports the following chart types:

    • Bar chart
    • Horizontal bar chart
    • Pie chart
    • Line chart
    • Scatter plot
    • Auto chart
    Source code in ckanext/charts/chart_builders/observable.py
    class ObservableBuilder(BaseChartBuilder):\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [\n            ObservableBarForm,\n            ObservableHoriontalBarForm,\n            ObservableLineForm,\n            ObservablePieForm,\n            ObservableScatterForm,\n            ObservableAutoForm,\n        ]\n
    "},{"location":"engines/observable/#bar-chart","title":"Bar chart","text":"

    The bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. For a horizontal bar chart, use the Horizontal bar chart chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Fill (fill)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#horizontal-bar-chart","title":"Horizontal bar chart","text":"

    The horizontal bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars are plotted horizontally.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Fill (fill)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#line-chart","title":"Line chart","text":"

    The line chart is a chart that displays information as a series of data points called 'markers' connected by straight line segments. It is useful for showing trends over time.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Invert X-axis (invert_x)

    Invert the X-axis

    Type: bool

    Invert Y-axis (invert_y)

    Invert the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#pie-chart","title":"Pie chart","text":"

    The pie chart is a circular statistical graphic that is divided into slices to illustrate numerical proportions. The arc length of each slice is proportional to the quantity it represents.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Inner Radius (innerRadius)

    Type:

    Stroke Width (strokeWidth)

    Works only if inner radius is lower than 0

    Type:

    Font Size (fontSize)

    Type:

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Width (width)

    Width of the chart

    Type: int

    Default: 640

    Height (height)

    Height of the chart

    Type: int

    Default: 400

    "},{"location":"engines/observable/#scatter-plot","title":"Scatter plot","text":"

    The scatter plot is a chart that uses Cartesian coordinates to display values for two variables for a set of data. The data points are represented as individual dots.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/observable/#auto-chart","title":"Auto chart","text":"

    The auto chart is a chart that automatically selects the best chart type based on the data. It is useful for quickly visualizing data without having to manually select a chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Line, Pie, Scatter, Auto

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/","title":"Plotly","text":"

    The Plotly chart engine supports the following chart types:

    • Bar chart
    • Horizontal bar chart
    • Pie chart
    • Line chart
    • Scatter plot

    Base class for Plotly chart builders.

    Defines supported chart types for Plotly engine.

    Source code in ckanext/charts/chart_builders/plotly.py
    class PlotlyBuilder(BaseChartBuilder):\n    \"\"\"Base class for Plotly chart builders.\n\n    Defines supported chart types for Plotly engine.\n    \"\"\"\n\n    @classmethod\n    def get_supported_forms(cls) -> list[type[Any]]:\n        return [\n            PlotlyBarForm,\n            PlotlyHoriontalBarForm,\n            PlotlyPieForm,\n            PlotlyLineForm,\n            PlotlyScatterForm,\n        ]\n
    "},{"location":"engines/plotly/#bar-chart","title":"Bar chart","text":"

    The bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars can be plotted vertically or horizontally. For a horizontal bar chart, use the Horizontal bar chart chart type.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#horizontal-bar-chart","title":"Horizontal bar chart","text":"

    The horizontal bar chart is a chart with rectangular bars with lengths proportional to the values that they represent. The bars are plotted horizontally.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#line-chart","title":"Line chart","text":"

    The line chart is a chart that displays information as a series of data points called 'markers' connected by straight line segments. It is useful for showing trends over time.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#pie-chart","title":"Pie chart","text":"

    The pie chart is a circular statistical graphic that is divided into slices to illustrate numerical proportions. The arc length of each slice is proportional to the quantity it represents.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    Values (values) [Required]

    Type: str

    Names (names) [Required]

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    "},{"location":"engines/plotly/#scatter-plot","title":"Scatter plot","text":"

    The scatter plot is a chart that uses Cartesian coordinates to display values for two variables for a set of data. The data points are represented as individual dots.

    Title (title)

    Title of the chart view

    Type: str

    Description (description)

    Description of the chart view

    Type: str

    Engine (engine) [Required]

    Select the chart engine to use

    Type: str

    Default: plotly

    Choices: plotly, observable, chartjs

    Type (type) [Required]

    Select the type of the chart, e.g. Line, Bar, Scatter, etc.

    Type: str

    Default: Line

    Choices: Bar, Horizontal Bar, Pie, Line, Scatter

    X Axis (x) [Required]

    Select a column for the X-axes

    Type: str

    Y Axis (y) [Required]

    Select a column for the Y-axis

    Type: str

    Log-scale X-axis (log_x)

    Use log scale for the X-axis

    Type: bool

    Log-scale Y-axis (log_y)

    Use log scale for the Y-axis

    Type: bool

    Sort X-axis (sort_x)

    Sort the X-axis values

    Type: bool

    Sort Y-axis (sort_y)

    Sort the Y-axis values

    Type: bool

    Skip N/A and NULL values (skip_null_values)

    Entries of the data with missing values will not be graphed or will be skipped

    Type: bool

    Size (size) [Required]

    Select a column for the size

    Type: str

    Size Max (size_max)

    Type:

    Limit (limit)

    Limit the number of rows to show in the chart

    Type: int

    Default: 100

    Color (color)

    Select a column for the color

    Type: str

    Animation Frame (animation_frame)

    Select a column for the animation frame

    Type: str

    Opacity (opacity)

    Opacity level of the chart

    Type: float

    Default: 1

    "},{"location":"fetchers/","title":"Fetchers","text":"

    Fetchers are responsible for fetching data from different sources (DataStore, URL, file system, hardcoded data).

    For the current implementation, we're working with resources that are uploaded to the DataStore, so the fetcher will be responsible for fetching the data from the DataStore.

    But it might come in handy to have fetchers for other sources, like URL, file system, etc.

    "},{"location":"fetchers/#implementing-new-fetchers","title":"Implementing new fetchers","text":"

    To register new fetchers, you need to create a new class that inherits from DataFetcherStrategy and implements the fetch_data and make_cache_key methods.

    The fetch_data method should return a pandas DataFrame object with the data that should be displayed in the chart.

    The make_cache_key method should return a unique string that will be used as a key to store the data in the cache.

    See the base class DataFetcherStrategy for more information.

    "},{"location":"fetchers/base/","title":"Base Fetcher","text":"

    All fetchers must inherit from the DataFetcherStrategy class. This class provides the basic structure for fetchers and defines the methods that must be implemented by all fetchers.

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.fetch_data","title":"fetch_data() abstractmethod","text":"

    This method should implement the data fetch logic.

    All the necessary information should be provided in the constructor.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: The fetched data

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.get_cached_data","title":"get_cached_data()","text":"

    Fetch data from the cache.

    RETURNS DESCRIPTION DataFrame | None

    pd.DataFrame | None: The cached data or None if not found

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.invalidate_cache","title":"invalidate_cache()","text":"

    Invalidate the cache for the data fetcher.

    "},{"location":"fetchers/base/#charts.fetchers.DataFetcherStrategy.make_cache_key","title":"make_cache_key() abstractmethod","text":"

    This method should generate a cache key for the fetched data.

    Every data fetcher should implement this method to support caching.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/datastore/","title":"Datastore Fetcher","text":"

    Fetch dataset resource data from the DataStore.

    This fetcher is used to fetch data from the DataStore using the resource ID.

    "},{"location":"fetchers/datastore/#charts.fetchers.DatastoreDataFetcher.__init__","title":"__init__(resource_id, limit=2000000, cache_strategy=None)","text":"

    Initialize the DatastoreDataFetcher.

    PARAMETER DESCRIPTION resource_id

    The ID of the resource to fetch data for.

    TYPE: str

    limit

    The maximum number of rows to fetch.

    TYPE: int DEFAULT: 2000000

    cache_strategy

    The cache strategy to use. If not provided, the configured cache strategy will be used.

    TYPE: str DEFAULT: None

    "},{"location":"fetchers/datastore/#charts.fetchers.DatastoreDataFetcher.fetch_data","title":"fetch_data()","text":"

    Fetch data from the DataStore.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: Data from the DataStore

    "},{"location":"fetchers/datastore/#charts.fetchers.DatastoreDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Generate a cache key for the DataStore data fetcher.

    Uses the resource ID as the part of a cache key.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/file/","title":"File System Data Fetcher","text":"

    Bases: DataFetcherStrategy

    Fetch data from the file system.

    This fetcher is used to fetch data from a file on the file system.

    Supported formats
    • CSV
    • XLSX
    • XLS
    • XML
    "},{"location":"fetchers/file/#charts.fetchers.FileSystemDataFetcher.__init__","title":"__init__(file_path, file_format='csv', cache_strategy=None)","text":"

    Initialize the FileSystemDataFetcher.

    PARAMETER DESCRIPTION file_path

    The path to the file.

    TYPE: str

    file_format

    The format of the file.

    TYPE: str DEFAULT: 'csv'

    cache_strategy

    The cache strategy to use. If not provided, the configured cache strategy will be used.

    TYPE: str DEFAULT: None

    "},{"location":"fetchers/file/#charts.fetchers.FileSystemDataFetcher.fetch_data","title":"fetch_data()","text":"

    Fetch data from the file system.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: Data fetched from the file system

    "},{"location":"fetchers/file/#charts.fetchers.FileSystemDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Generate a cache key for the FileSystem data fetcher.

    Uses the file path as the part of a cache key.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/hardcode/","title":"Hardcoded Data Fetcher","text":"

    Bases: DataFetcherStrategy

    Fetch hardcoded data.

    This fetcher is used to make a dataframe from hardcoded data, so you can build a chart from it.

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.__init__","title":"__init__(data)","text":"

    Initialize the HardcodedDataFetcher.

    PARAMETER DESCRIPTION data

    The hardcoded data.

    TYPE: dict[str, list[Any]]

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.fetch_data","title":"fetch_data()","text":"

    Transform arbitrary data into a dataframe.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: The hardcoded data as a dataframe

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.invalidate_cache","title":"invalidate_cache()","text":"

    Hardcoded data is not cached

    "},{"location":"fetchers/hardcode/#charts.fetchers.HardcodedDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Hardcoded data is not cached

    "},{"location":"fetchers/url/","title":"URL Data Fetcher","text":"

    Bases: DataFetcherStrategy

    Fetch data from a URL.

    This fetcher is used to fetch data from a URL.

    Supported formats
    • CSV
    • XLSX
    • XLS
    • XML
    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.__init__","title":"__init__(url, file_format='csv', timeout=0, cache_strategy=None)","text":"

    Initialize the URLDataFetcher.

    PARAMETER DESCRIPTION url

    The URL to fetch data from.

    TYPE: str

    file_format

    The format of the file.

    TYPE: str DEFAULT: 'csv'

    timeout

    The timeout for the request in seconds.

    TYPE: int DEFAULT: 0

    cache_strategy

    The cache strategy to use. If not provided, the configured cache strategy will be used.

    TYPE: str DEFAULT: None

    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.fetch_data","title":"fetch_data()","text":"

    Fetch data from the URL.

    RETURNS DESCRIPTION DataFrame

    pd.DataFrame: Data fetched from the URL

    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.make_cache_key","title":"make_cache_key()","text":"

    Generate a cache key for the URL data fetcher.

    Uses the URL as the part of a cache key.

    RETURNS DESCRIPTION str

    The cache key

    TYPE: str

    "},{"location":"fetchers/url/#charts.fetchers.URLDataFetcher.make_request","title":"make_request()","text":"

    Make a request to the URL and return the response content.

    RETURNS DESCRIPTION bytes

    The response content

    TYPE: bytes

    RAISES DESCRIPTION DataFetchError

    If an error occurs during the request

    "}]} \ No newline at end of file diff --git a/site/sitemap.xml b/site/sitemap.xml index 1772fb3..d8fa9c4 100644 --- a/site/sitemap.xml +++ b/site/sitemap.xml @@ -2,94 +2,94 @@ https://.github.io/ckanext-charts/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/configuration/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/helpers/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/install/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/troubleshooting/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/usage/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/utils/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/validators/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/caching/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/caching/base/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/caching/file/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/caching/redis/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/engines/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/engines/chartjs/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/engines/custom/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/engines/observable/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/engines/plotly/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/fetchers/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/fetchers/base/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/fetchers/datastore/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/fetchers/file/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/fetchers/hardcode/ - 2024-12-02 + 2024-12-03 https://.github.io/ckanext-charts/fetchers/url/ - 2024-12-02 + 2024-12-03 \ No newline at end of file diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz index 8ab8bed..b90a135 100644 Binary files a/site/sitemap.xml.gz and b/site/sitemap.xml.gz differ diff --git a/site/troubleshooting/index.html b/site/troubleshooting/index.html index 2078a9d..ca0b429 100644 --- a/site/troubleshooting/index.html +++ b/site/troubleshooting/index.html @@ -16,7 +16,7 @@ - + diff --git a/site/usage/index.html b/site/usage/index.html index 177c2d9..dc06543 100644 --- a/site/usage/index.html +++ b/site/usage/index.html @@ -18,7 +18,7 @@ - + diff --git a/site/utils/index.html b/site/utils/index.html index ced685a..8eefb9e 100644 --- a/site/utils/index.html +++ b/site/utils/index.html @@ -18,7 +18,7 @@ - + @@ -1070,6 +1070,11 @@

    Utility Functions

    + + + + +
    @@ -1103,7 +1108,9 @@

    settings + settings +

    Chart settings

    @@ -1117,7 +1124,9 @@

    data + data +

    Dataframe with data

    @@ -1210,7 +1219,9 @@

    settings + settings +

    Chart settings

    @@ -1224,7 +1235,9 @@

    resource_id + resource_id +

    Resource ID

    @@ -1335,7 +1348,9 @@

    data_dict + data_dict +

    Resource data dictionary

    @@ -1483,7 +1498,9 @@

    resource_id + resource_id +

    Resource ID

    @@ -1577,7 +1594,9 @@

    size_bytes + size_bytes +

    File size in bytes

    diff --git a/site/validators/index.html b/site/validators/index.html index 792d5b7..73c2c89 100644 --- a/site/validators/index.html +++ b/site/validators/index.html @@ -18,7 +18,7 @@ - + @@ -1088,6 +1088,11 @@

    Validators

    + + + + +
    @@ -1123,7 +1128,9 @@

    other_key + other_key +

    The key of the field to copy the value from

    @@ -1237,7 +1244,9 @@

    -

    max_length + max_length +

    The maximum length of the list

    @@ -1345,7 +1354,9 @@

    data + data +

    The data to convert

    @@ -1445,7 +1456,9 @@

    strategy + strategy +

    The cache strategy

    @@ -1597,7 +1610,9 @@

    -

    value + value +

    The value to convert

    @@ -1693,7 +1708,9 @@

    key + key +

    The key of the field

    @@ -1707,7 +1724,9 @@

    data + data +

    The data to validate

    @@ -1721,7 +1740,9 @@

    errors + errors +

    The errors dict

    @@ -1735,7 +1756,9 @@

    context + context +

    The context

    @@ -1857,7 +1880,9 @@

    value + value +

    The value to validate