Skip to content

Commit

Permalink
doc: refactor and write documentation part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
mutantsan committed Dec 2, 2024
1 parent cb4134a commit 2175021
Show file tree
Hide file tree
Showing 41 changed files with 10,346 additions and 302 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The extension includes features such as chart creation, chart editing, chart emb

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

See the [documentation](https://datashades.github.io/ckanext-charts/) for more information.

## Quick start

- Install it with `PyPi` with `pip install ckanext-charts[pyarrow]`
Expand Down
74 changes: 73 additions & 1 deletion ckanext/charts/chart_builders/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ def column_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
"required": True,
"choices": choices,
"group": "Data",
"type": "str",
"validators": [
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
Expand All @@ -278,6 +279,8 @@ def title_field(self) -> dict[str, Any]:
"preset": "title",
"form_placeholder": "Chart title",
"group": "General",
"type": "str",
"help_text": "Title of the chart view",
"validators": [
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
Expand All @@ -291,6 +294,8 @@ def chart_title_field(self) -> dict[str, Any]:
"preset": "title",
"form_placeholder": "Chart title",
"group": "Styles",
"type": "str",
"help_text": "Title of the chart itself",
"validators": [
self.get_validator("default")(" "),
self.get_validator("unicode_safe"),
Expand All @@ -303,6 +308,8 @@ def chart_xlabel_field(self) -> dict[str, Any]:
"label": "Chart X axe label",
"form_placeholder": "X label",
"group": "Styles",
"type": "str",
"help_text": "Label for the X-axis",
"validators": [
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
Expand All @@ -315,6 +322,8 @@ def chart_ylabel_left_field(self) -> dict[str, Any]:
"label": "Chart Y axe left label",
"form_placeholder": "Left Y label",
"group": "Styles",
"type": "str",
"help_text": "Label for the Y-axis on the left side",
"validators": [
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
Expand All @@ -327,6 +336,8 @@ def chart_ylabel_right_field(self) -> dict[str, Any]:
"label": "Chart Y axe right label",
"form_placeholder": "Right Y label",
"group": "Styles",
"type": "str",
"help_text": "Label for the Y-axis on the right side",
"validators": [
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
Expand All @@ -340,6 +351,8 @@ def description_field(self) -> dict[str, Any]:
"form_snippet": "markdown.html",
"form_placeholder": "Information about my view",
"group": "General",
"type": "str",
"help_text": "Description of the chart view",
"validators": [
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
Expand All @@ -354,6 +367,9 @@ def engine_field(self) -> dict[str, Any]:
"required": True,
"choices": tk.h.get_available_chart_engines_options(),
"group": "Structure",
"type": "str",
"help_text": "Select the chart engine to use",
"default": "plotly",
"validators": [
self.get_validator("default")("plotly"),
self.get_validator("unicode_safe"),
Expand Down Expand Up @@ -385,6 +401,9 @@ def type_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
"hx-target": ".charts-view--form",
"data-module-clear-button": True,
},
"help_text": "Select the type of the chart, e.g. Line, Bar, Scatter, etc.",
"type": "str",
"default": "Line",
}

def x_axis_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
Expand All @@ -395,6 +414,8 @@ def x_axis_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
"required": True,
"choices": choices,
"group": "Data",
"type": "str",
"help_text": "Select a column for the X-axes",
"validators": [
self.get_validator("charts_if_empty_same_as")("values"),
self.get_validator("unicode_safe"),
Expand All @@ -411,6 +432,7 @@ def y_axis_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
self.get_validator("charts_if_empty_same_as")("names"),
self.get_validator("unicode_safe"),
],
"help_text": "Select a column for the Y-axis",
},
)

Expand Down Expand Up @@ -444,6 +466,7 @@ def y_multi_axis_field(
"data-module-multiple": "true",
"multiple": 1,
},
"type": "List[str]",
"help_text": help_text,
}

Expand Down Expand Up @@ -498,6 +521,8 @@ def split_data_field(self) -> dict[str, Any]:
"Split data into different columns by years based on datetime "
"column stated for the x-axis"
),
"type": "bool",
"default": False,
}

def skip_null_values_field(self) -> dict[str, Any]:
Expand All @@ -511,6 +536,7 @@ def skip_null_values_field(self) -> dict[str, Any]:
],
"help_text": """Entries of the data with missing values will not be
graphed or will be skipped""",
"type": "bool",
}

def break_chart_field(self) -> dict[str, Any]:
Expand All @@ -523,6 +549,7 @@ def break_chart_field(self) -> dict[str, Any]:
self.get_validator("boolean_validator"),
],
"help_text": "Break the graph at missing values",
"type": "bool",
}

def sort_x_field(self) -> dict[str, Any]:
Expand All @@ -535,6 +562,9 @@ def sort_x_field(self) -> dict[str, Any]:
self.get_validator("default")(False),
self.get_validator("boolean_validator"),
],
"help_text": "Sort the X-axis values",
"type": "bool",
"default": False,
}

def sort_y_field(self) -> dict[str, Any]:
Expand All @@ -547,6 +577,9 @@ def sort_y_field(self) -> dict[str, Any]:
self.get_validator("default")(False),
self.get_validator("boolean_validator"),
],
"help_text": "Sort the Y-axis values",
"type": "bool",
"default": False,
}

def invert_x_field(self) -> dict[str, Any]:
Expand All @@ -559,6 +592,9 @@ def invert_x_field(self) -> dict[str, Any]:
self.get_validator("default")(False),
self.get_validator("boolean_validator"),
],
"help_text": "Invert the X-axis",
"type": "bool",
"default": False,
}

def invert_y_field(self) -> dict[str, Any]:
Expand All @@ -571,6 +607,9 @@ def invert_y_field(self) -> dict[str, Any]:
self.get_validator("default")(False),
self.get_validator("boolean_validator"),
],
"help_text": "Invert the Y-axis",
"type": "bool",
"default": False,
}

def log_x_field(self) -> dict[str, Any]:
Expand All @@ -583,6 +622,9 @@ def log_x_field(self) -> dict[str, Any]:
self.get_validator("default")(False),
self.get_validator("boolean_validator"),
],
"help_text": "Use log scale for the X-axis",
"type": "bool",
"default": False,
}

def log_y_field(self) -> dict[str, Any]:
Expand All @@ -595,6 +637,9 @@ def log_y_field(self) -> dict[str, Any]:
self.get_validator("default")(False),
self.get_validator("boolean_validator"),
],
"help_text": "Use log scale for the Y-axis",
"type": "bool",
"default": False,
}

def color_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
Expand All @@ -608,6 +653,8 @@ def color_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
],
"help_text": "Select a column for the color",
"type": "str",
}

def animation_frame_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
Expand All @@ -621,6 +668,8 @@ def animation_frame_field(self, choices: list[dict[str, str]]) -> dict[str, Any]
self.get_validator("ignore_empty"),
self.get_validator("unicode_safe"),
],
"help_text": "Select a column for the animation frame",
"type": "str",
}

def opacity_field(self) -> dict[str, Any]:
Expand All @@ -634,6 +683,9 @@ def opacity_field(self) -> dict[str, Any]:
self.get_validator("default")(1),
self.get_validator("float_validator"),
],
"help_text": "Opacity level of the chart",
"type": "float",
"default": 1,
}

def limit_field(self, default: int = 100, maximum: int = 10000) -> dict[str, Any]:
Expand All @@ -649,6 +701,9 @@ def limit_field(self, default: int = 100, maximum: int = 10000) -> dict[str, Any
self.get_validator("limit_to_configured_maximum")("", maximum),
],
"group": "Data",
"help_text": "Limit the number of rows to show in the chart",
"type": "int",
"default": default,
}

def values_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
Expand Down Expand Up @@ -694,6 +749,9 @@ def width_field(self) -> dict[str, Any]:
self.get_validator("limit_to_configured_maximum")("", 1000),
],
"group": "Data",
"help_text": "Width of the chart",
"type": "int",
"default": 640,
}

def height_field(self) -> dict[str, Any]:
Expand All @@ -709,6 +767,9 @@ def height_field(self) -> dict[str, Any]:
self.get_validator("limit_to_configured_maximum")("", 1000),
],
"group": "Data",
"help_text": "Height of the chart",
"type": "int",
"default": 400,
}

def more_info_button_field(self) -> dict[str, Any]:
Expand All @@ -721,11 +782,20 @@ def more_info_button_field(self) -> dict[str, Any]:
"label": "More info",
"form_snippet": "chart_more_info_button.html",
"group": "Data",
"exclude_from_mkdocs": True,
}

def size_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
field = self.column_field(choices)
field.update({"field_name": "size", "label": "Size", "group": "Structure"})
field.update(
{
"field_name": "size",
"label": "Size",
"group": "Structure",
"help_text": "Select a column for the size",
"type": "str"
}
)

return field

Expand All @@ -740,6 +810,7 @@ def filter_field(self, choices: list[dict[str, str]]) -> dict[str, Any]:
self.get_validator("unicode_safe"),
],
"group": "Filter",
"exclude_from_mkdocs": True,
}

def engine_details_field(self) -> dict[str, Any]:
Expand All @@ -751,4 +822,5 @@ def engine_details_field(self) -> dict[str, Any]:
"label": "Engine details",
"form_snippet": "chart_engine_details.html",
"group": "Structure",
"exclude_from_mkdocs": True,
}
39 changes: 18 additions & 21 deletions ckanext/charts/chart_builders/chartjs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,26 @@ def get_supported_forms(cls) -> list[type[Any]]:
ChartJSRadarForm,
]

def create_zoom_and_title_options(self, options: str[dict, Any]) -> dict[str, Any]:
def _create_zoom_and_title_options(self, options: dict[str, Any]) -> dict[str, Any]:
"""Add zoom and title plugin options to the provided options dictionary"""
zoom_options = {
"zoom": {
"wheel": {"enabled": True},
"pinch": {"enabled": True},
"drag": {"enabled": True},
"mode": "xy",
},
"pan": {
"enabled": True,
"modifierKey": "shift",
"mode": "xy",
},
}

if "plugins" not in options:
options["plugins"] = {}

options["plugins"].update(
{
"zoom": zoom_options,
"zoom": {
"zoom": {
"wheel": {"enabled": True},
"pinch": {"enabled": True},
"drag": {"enabled": True},
"mode": "xy",
},
"pan": {
"enabled": True,
"modifierKey": "shift",
"mode": "xy",
},
},
"title": {
"display": True,
"position": "bottom",
Expand Down Expand Up @@ -95,7 +93,7 @@ def _prepare_data(self) -> dict[str, Any]:
)

data["data"]["datasets"] = datasets
data["options"] = self.create_zoom_and_title_options(data["options"])
data["options"] = self._create_zoom_and_title_options(data["options"])

return data

Expand Down Expand Up @@ -127,7 +125,6 @@ def get_form_fields(self):
self.filter_field(columns),
]


class ChartJSHorizontalBarBuilder(ChartJSBarBuilder):
def to_json(self) -> str:
data = self._prepare_data()
Expand Down Expand Up @@ -167,7 +164,7 @@ def to_json(self) -> str:
"reverse": self.settings.get("invert_y", False),
},
}
data["options"] = self.create_zoom_and_title_options(data["options"])
data["options"] = self._create_zoom_and_title_options(data["options"])
return json.dumps(data)


Expand Down Expand Up @@ -292,7 +289,7 @@ def to_json(self) -> str:
"data": dataset_data,
},
]
data["options"] = self.create_zoom_and_title_options(data["options"])
data["options"] = self._create_zoom_and_title_options(data["options"])
return json.dumps(self._configure_date_axis(data))

def _configure_date_axis(self, data: dict[str, Any]) -> dict[str, Any]:
Expand Down Expand Up @@ -377,7 +374,7 @@ def to_json(self) -> str:
data["data"]["datasets"] = [
{"label": self.settings["y"], "data": dataset_data},
]
data["options"] = self.create_zoom_and_title_options(data["options"])
data["options"] = self._create_zoom_and_title_options(data["options"])

return json.dumps(self._configure_date_axis(data))

Expand Down
5 changes: 5 additions & 0 deletions ckanext/charts/chart_builders/plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@


class PlotlyBuilder(BaseChartBuilder):
"""Base class for Plotly chart builders.
Defines supported chart types for Plotly engine.
"""

@classmethod
def get_supported_forms(cls) -> list[type[Any]]:
return [
Expand Down
Loading

0 comments on commit 2175021

Please sign in to comment.