Skip to content

Commit

Permalink
update: migrate to collections
Browse files Browse the repository at this point in the history
  • Loading branch information
mutantsan committed Jan 29, 2024
1 parent f4b28c0 commit 247c2bf
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 168 deletions.
13 changes: 0 additions & 13 deletions ckanext/tour/col_renderers.py

This file was deleted.

144 changes: 144 additions & 0 deletions ckanext/tour/collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
from __future__ import annotations

from typing import Any
from ckanext.collection.utils.data.model import ModelData

from dominate import tags

import ckan.plugins.toolkit as tk

from ckanext.collection.types import InputFilter, ButtonFilter, LinkFilter
from ckanext.collection.utils import Filters

from ckanext.ap_main.collection.base import (
ApCollection,
ApColumns,
BulkAction,
RowAction,
ApHtmxTableSerializer
)

from ckanext.tour.model import Tour


def tour_row_dictizer(serializer: ApHtmxTableSerializer, row: Tour):
data = row.dictize({})
data["bulk-action"] = data["id"]
data["steps"] = len(data["steps"])

return data

class TourListCollection(ApCollection[Any]):
SerializerFactory = ApHtmxTableSerializer.with_attributes(
row_dictizer=tour_row_dictizer
)

ColumnsFactory = ApColumns.with_attributes(
names=[
"bulk-action",
"title",
"state",
"anchor",
"page",
"created_at",
"modified_at",
"steps",
"author_id",
"row_actions",
],
sortable={"created_at", "modified_at"},
searchable={"title", "page"},
labels={
"bulk-action": tk.literal(
tags.input_(
type="checkbox",
name="bulk_check",
id="bulk_check",
data_module="ap-bulk-check",
data_module_selector='input[name="entity_id"]',
)
),
"title": "Title",
"state": "State",
"anchor": "Anchor",
"page": "Page",
"created_at": "Created At",
"modified_at": "Modified At",
"steps": "Steps",
"author_id": "Author",
"row_actions": "Actions",
},
width={},
serializers={
"created_at": [("date", {})],
"modified_at": [("date", {})],
"author_id": [("user_link", {})],
},
)

DataFactory = ModelData.with_attributes(
model=Tour,
is_scalar=True,
use_naive_search=True,
use_naive_filters=True,
)

FiltersFactory = Filters.with_attributes(
static_actions=[
BulkAction(
name="bulk-action",
type="bulk_action",
options={
"label": "Action",
"options": [
{"value": "1", "text": "Disable selected tour(s)"},
{"value": "2", "text": "Enable selected tour(s)"},
{"value": "3", "text": "Remove selected tour(s)"},
],
},
),
RowAction(
name="view",
type="row_action",
options={
"endpoint": "tour.delete",
"label": "Delete",
"params": {
"tour_id": "$id",
},
},
),
RowAction(
name="view",
type="row_action",
options={
"endpoint": "tour.edit",
"label": "Edit",
"params": {
"tour_id": "$id",
},
},
)
],
static_filters=[
InputFilter(
name="q",
type="input",
options={
"label": "Search",
"placeholder": "Search",
},
),
ButtonFilter(
name="type",
type="button",
options={
"label": "Clear",
"type": "button",
"attrs": {
"onclick": "$(this).closest('form').find('input,select').val('').prevObject[0].requestSubmit()"
},
},
),
],
)
4 changes: 2 additions & 2 deletions ckanext/tour/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def delete(self, with_file: bool = False) -> None:
{"ignore_auth": True}, {"id": self.file_id}
)
except tk.ObjectNotFound:
raise TourStepFileError("Related file not found.")
pass

model.Session().autoflush = False
model.Session.delete(self)
Expand All @@ -214,6 +214,6 @@ def get_file_data(self, file_id: str) -> dict[str, Any]:
{"ignore_auth": True}, {"id": file_id}
)
except tk.ObjectNotFound:
raise TourStepFileError("Related file not found.")
return {}

return result
14 changes: 10 additions & 4 deletions ckanext/tour/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import ckan.plugins as plugins
import ckan.plugins.toolkit as tk

from ckanext.collection.interfaces import ICollection, CollectionFactory

from ckanext.ap_main.interfaces import IAdminPanel
from ckanext.ap_main.types import ColRenderer, ConfigurationItem, SectionConfig
from ckanext.tour.col_renderers import get_renderers
from ckanext.ap_main.types import ConfigurationItem, SectionConfig

from ckanext.tour.collection import TourListCollection


@tk.blanket.helpers
Expand All @@ -16,6 +19,7 @@
class TourPlugin(plugins.SingletonPlugin):
plugins.implements(plugins.IConfigurer)
plugins.implements(IAdminPanel, inherit=True)
plugins.implements(ICollection, inherit=True)

# IConfigurer

Expand Down Expand Up @@ -53,5 +57,7 @@ def register_config_sections(
)
return config_list

def get_col_renderers(self) -> dict[str, ColRenderer]:
return get_renderers()
# ICollection

def get_collection_factories(self) -> dict[str, CollectionFactory]:
return {"tour-list": TourListCollection}
40 changes: 9 additions & 31 deletions ckanext/tour/templates/tour/tour_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,16 @@
{% import 'macros/form.html' as form %}

{% block breadcrumb_content %}
<li class="active">{% link_for _("Tour list"), named_route='tour.list' %}</li>
<li class="active">{% link_for _("Tour list"), request.endpoint %}</li>
{% endblock breadcrumb_content %}

{% block ap_content %}
<h1>{{ _("Tour list") }}</h1>

<div class="row g-3">
<form action="{{ h.url_for('tour.list') }}" method="POST">
{{ h.csrf_input() }}

{% if page.items %}
<div class="bulk-actions">
{{ form.select('bulk-action', id='bulk-action', label=_('Action'), options=bulk_options, selected="", error=error) }}

<button type="submit" id="bulk-submit" class="btn btn-primary mb-3">
{{ _("Apply to selected items") }}
</button>
</div>

{% snippet "admin_panel/config/snippets/sortable_table.html", items=page.items, columns=columns, order_by=order_by, sort=sort, bulk_check=1 %}
{% else %}
{% set add_tour_url = h.url_for('tour.add') %}
<p>
{%- trans -%}
No tours found. Want to <a href="{{ add_tour_url }}">create</a> one?
{%- endtrans -%}
</p>
{% endif %}
</form>
</div> <!-- row -->
{% if collection.data.total %}
{{ collection.serializer.render() | safe }}
{% else %}
<p>
{{ _("No tours found") }}
<a href="{{ request.path }}">{{ _("Clear the search") }}</a>
</p>
{% endif %}
{% endblock ap_content %}

{% block page_pagination %}
{{ page.pager() }}
{% endblock %}
40 changes: 1 addition & 39 deletions ckanext/tour/tests/logic/test_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def test_error_on_child_should_clear_parent(self, sysadmin):

assert tour_model.Tour.all()


@pytest.mark.usefixtures("with_plugins", "clean_db", "mock_storage")
class TestTourUpdate:
def test_update_not_existing(self):
Expand All @@ -128,45 +129,6 @@ def test_update_existing(self, tour_factory):
assert updated_tour["page"] == "yyy"
assert updated_tour["anchor"] == "zzz"

def test_set_empty_title(self, tour_factory):
tour = tour_factory(steps=[], title="test-1")

tour = call_action("tour_show", id=tour["id"])
tour["title"] = ""

with pytest.raises(tk.ValidationError, match="Missing value"):
call_action("tour_update", **tour)

# def test_change_to_wrong_status(self, data_request):
# with pytest.raises(
# tk.ValidationError,
# match="Value must be one of",
# ):
# call_action(
# "msf_rd_data_request_update_status",
# id=data_request["id"],
# status="closed",
# )

# def test_change_resolved_status(self, data_request):
# result = call_action(
# "msf_rd_data_request_update_status",
# id=data_request["id"],
# status=DataRequest.Status.resolved,
# )

# assert result["status"] == DataRequest.Status.resolved

# with pytest.raises(
# tk.ValidationError,
# match="Can't update resolved data request",
# ):
# call_action(
# "msf_rd_data_request_update_status",
# id=data_request["id"],
# status=DataRequest.Status.requested,
# )


@pytest.mark.usefixtures("with_plugins", "clean_db", "mock_storage")
class TestTourStepUpdate:
Expand Down
1 change: 0 additions & 1 deletion ckanext/tour/views/tour_delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ def get(self, tour_id: str) -> str:
return tk.render("tour/tour_delete.html", extra_vars={"tour_id": tour_id})

def post(self, tour_id: str) -> Response:
import ipdb; ipdb.set_trace()
try:
tk.get_action("tour_remove")({}, {"id": tour_id})
except tk.ObjectNotFound as e:
Expand Down
Loading

0 comments on commit 247c2bf

Please sign in to comment.