From 9c8619d81827718d0cd01ccfe225fd6ccfabbd0d Mon Sep 17 00:00:00 2001 From: Sergey Motornyuk Date: Sat, 27 Jan 2024 14:07:05 +0200 Subject: [PATCH] feat: collection-refresh event on body or htmx form_id reloads collection --- Makefile | 15 ++++- .../collection/serialize/htmx_table/form.html | 3 +- ckanext/collection/utils/columns.py | 66 +++++++++++++------ pyproject.toml | 5 ++ 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 125bc8b..e8d9704 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,21 @@ help: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' +# Type Section +# build Build +# chore Chore +# ci Continuous Integration +# deps Dependencies +# doc(s) Docs +# feat Features +# fix Bug Fixes +# perf Performance Improvements +# ref(actor) Code Refactoring +# revert Reverts +# style Style +# test(s) Tests changelog: ## compile changelog - git changelog -c conventional -o CHANGELOG.md + git changelog vendor: cp node_modules/htmx.org/dist/htmx.js ckanext/collection/assets/vendor diff --git a/ckanext/collection/templates/collection/serialize/htmx_table/form.html b/ckanext/collection/templates/collection/serialize/htmx_table/form.html index 0f6f049..ecf30b5 100644 --- a/ckanext/collection/templates/collection/serialize/htmx_table/form.html +++ b/ckanext/collection/templates/collection/serialize/htmx_table/form.html @@ -20,7 +20,8 @@ change, submit, change from:[form="{{ form_id }}"], - collection-trigger from:[data-collection="{{ collection.name }}"], + collection-refresh from:body, + collection-refresh from:#{{ form_id }}, change.htmx-select2 from:[form="{{ form_id }}"] delay:20' hx-target="closest .{{ base_class }}" hx-indicator="closest .{{ base_class }}" diff --git a/ckanext/collection/utils/columns.py b/ckanext/collection/utils/columns.py index ead0cee..f752d6f 100644 --- a/ckanext/collection/utils/columns.py +++ b/ckanext/collection/utils/columns.py @@ -1,10 +1,14 @@ from __future__ import annotations -from typing import Any +import enum +from typing import Any, cast from ckanext.collection import shared, types SENTINEL = object() +ALL = object() +NOT_HIDDEN = object() +NONE = object() class Columns( @@ -20,15 +24,18 @@ class Columns( labels: UI labels for columns """ + class Default(enum.Enum): + ALL = enum.auto() + NOT_HIDDEN = enum.auto() + NONE = enum.auto() + names: list[str] = shared.configurable_attribute(default_factory=lambda self: []) hidden: set[str] = shared.configurable_attribute(default_factory=lambda self: set()) - visible: set[str] = shared.configurable_attribute(SENTINEL) - sortable: set[str] = shared.configurable_attribute(SENTINEL) - filterable: set[str] = shared.configurable_attribute(SENTINEL) - searchable: set[str] = shared.configurable_attribute( - default_factory=lambda self: set(), - ) - labels: dict[str, str] = shared.configurable_attribute(SENTINEL) + visible: set[str] = shared.configurable_attribute(Default.NOT_HIDDEN) + sortable: set[str] = shared.configurable_attribute(Default.ALL) + filterable: set[str] = shared.configurable_attribute(Default.ALL) + searchable: set[str] = shared.configurable_attribute(Default.NONE) + labels: dict[str, str] = shared.configurable_attribute(Default.ALL) serializers: dict[ str, @@ -39,20 +46,37 @@ class Columns( def __init__(self, obj: types.TDataCollection, **kwargs: Any): super().__init__(obj, **kwargs) - self.apply_names() + self.configure_attributes() + + def configure_attributes(self): + if self.hidden is self.Default.ALL: + self.hidden = set(self.names) + elif isinstance(self.hidden, self.Default): + self.hidden = set() + + self.visible = self._compute_set(self.visible) + + if not self.hidden: + self.hidden = set(self.names) - self.visible + + self.sortable = self._compute_set(self.sortable) + self.filterable = self._compute_set(self.filterable) + self.searchable = self._compute_set(self.searchable) + + if isinstance(self.labels, self.Default): + self.labels = {c: c for c in self._compute_set(self.labels)} - def apply_names(self): - if self.visible is SENTINEL: - self.visible = {c for c in self.names if c not in self.hidden} + def _compute_set(self, value: Default | set[str]): + if value is self.Default.NONE: + return cast("set[str]", set()) - if self.sortable is SENTINEL: - self.sortable = set(self.names) + if value is self.Default.ALL: + return {c for c in self.names} - if self.filterable is SENTINEL: - self.filterable = set(self.names) + if value is self.Default.NOT_HIDDEN: + return {c for c in self.names if c not in self.hidden} - if self.labels is SENTINEL: - self.labels = {c: c for c in self.names} + return value def get_primary_order(self, name: str) -> str: """Format column name for usage as a primary order value.""" @@ -66,13 +90,13 @@ def get_secondary_order(self, name: str) -> str: class TableColunns(Columns[types.TDbCollection]): table: str = shared.configurable_attribute() filterable: set[str] = shared.configurable_attribute( - default_factory=lambda self: set(), + default_factory=lambda self: NONE, ) - def apply_names(self): + def configure_attributes(self): self.names = [ c["name"] for c in self.attached.db_connection.inspector.get_columns(self.table) ] - super().apply_names() + super().configure_attributes() diff --git a/pyproject.toml b/pyproject.toml index 478735c..9c2d8b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,11 @@ filterwarnings = [ "ignore::DeprecationWarning", ] +[tool.git-changelog] +output = "CHANGELOG.md" +convention = "conventional" +parse-trailers = true + [tool.pyright] pythonVersion = "3.8" include = ["ckanext"]