Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/signals-for-configuration'
Browse files Browse the repository at this point in the history
  • Loading branch information
mutantsan committed Feb 12, 2024
2 parents 2475d31 + 8eb1595 commit f062d01
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 72 deletions.
54 changes: 29 additions & 25 deletions ckanext/ap_example/plugin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from __future__ import annotations
from typing import Literal

from os import path

Expand All @@ -8,16 +9,16 @@
import ckan.plugins.toolkit as tk
import ckan.logic as logic
from ckan.config.declaration import Declaration, Key
from ckan.types import SignalMapping

import ckanext.ap_main.types as ap_types
from ckanext.ap_main.interfaces import IAdminPanel


@tk.blanket.blueprints
class AdminPanelExamplePlugin(p.SingletonPlugin):
p.implements(p.IConfigurer)
p.implements(IAdminPanel, inherit=True)
p.implements(p.IConfigDeclaration, inherit=True)
p.implements(p.ISignal)

# IConfigurer

Expand All @@ -26,29 +27,14 @@ def update_config(self, config_: tk.CKANConfig):
tk.add_public_directory(config_, "public")
tk.add_resource("assets", "ap_test")

# IAdminPanel

def register_config_sections(
self, config_list: list[ap_types.SectionConfig]
) -> list[ap_types.SectionConfig]:
config_list.append(
ap_types.SectionConfig(
name="Admin panel example",
configs=[
ap_types.ConfigurationItem(
name="Example settings",
blueprint="ap_example.config",
info="An example of schema-generated configuration form",
),
ap_types.ConfigurationItem(
name="Example display",
blueprint="ap_example.display",
info="Example of displaying values submitted from a form",
),
],
)
)
return config_list
# ISignal

def get_signal_subscriptions(self) -> SignalMapping:
return {
tk.signals.ckanext.signal("ap_main:collect_config_sections"): [
collect_config_sections_subscriber,
],
}

# IConfigDeclaration

Expand All @@ -59,3 +45,21 @@ def declare_config_options(self, declaration: Declaration, key: Key):
data_dict = safe_load(file)

return declaration.load_dict(data_dict)


def collect_config_sections_subscriber(sender: None):
return ap_types.SectionConfig(
name="Admin panel example",
configs=[
ap_types.ConfigurationItem(
name="Example settings",
blueprint="ap_example.config",
info="An example of schema-generated configuration form",
),
ap_types.ConfigurationItem(
name="Example display",
blueprint="ap_example.display",
info="Example of displaying values submitted from a form",
),
],
)
44 changes: 9 additions & 35 deletions ckanext/ap_main/helpers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from __future__ import annotations

from typing import Any, Optional
from typing import Any
from urllib.parse import urlencode

import ckan.lib.munge as munge
import ckan.model as model
import ckan.plugins as p
import ckan.plugins.toolkit as tk

Expand All @@ -13,35 +12,23 @@
import ckanext.ap_main.config as ap_config
import ckanext.ap_main.utils as ap_utils
from ckanext.ap_main.interfaces import IAdminPanel
from ckanext.ap_main.types import ConfigurationItem, SectionConfig, ToolbarButton
from ckanext.ap_main.types import SectionConfig, ToolbarButton

helper, get_helpers = Collector("ap").split()


@helper
def get_config_sections() -> list[SectionConfig]:
"""Prepare a config section structure for render"""
default_sections = [
SectionConfig(
name=tk._("Basic site settings"),
configs=[
ConfigurationItem(
name=tk._("CKAN configuration"),
info=tk._("CKAN site config options"),
blueprint=(
"ap_basic.editable_config"
if p.plugin_loaded("editable_config")
else "ap_basic.config"
),
)
],
),
]
config_sections = {}

for plugin in reversed(list(p.PluginImplementations(IAdminPanel))):
default_sections = plugin.register_config_sections(default_sections)
for _, section in ap_utils.collect_sections_signal.send():
config_sections.setdefault(
section["name"], {"name": section["name"], "configs": []}
)
config_sections[section["name"]]["configs"].extend(section["configs"])

return default_sections
return list(config_sections.values())


@helper
Expand All @@ -65,17 +52,6 @@ def get_toolbar_structure() -> list[ToolbarButton]:
icon="fa fa-folder",
url=tk.url_for("ap_content.list"),
),
# ToolbarButton(
# label=tk._("Appearance"),
# icon="fa fa-wand-magic-sparkles",
# ),
# ToolbarButton(
# label=tk._("Extensions"),
# icon="fa fa-gem",
# url=tk.url_for(
# "api.action", ver=3, logic_function="status_show", qualified=True
# ),
# ),
ToolbarButton(
label=tk._("Configuration"),
icon="fa fa-gear",
Expand All @@ -98,14 +74,12 @@ def get_toolbar_structure() -> list[ToolbarButton]:
label=tk._("Reports"),
icon="fa fa-chart-bar",
subitems=[
# ToolbarButton(label=tk._("Available updates")),
ToolbarButton(
label=tk._("Recent log messages"),
url=tk.url_for("ap_report.logs"),
)
],
),
# ToolbarButton(label=tk._("Help"), icon="fa fa-circle-info"),
ToolbarButton(
icon="fa fa-gavel",
url=tk.url_for("admin.index"),
Expand Down
6 changes: 0 additions & 6 deletions ckanext/ap_main/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@


class IAdminPanel(Interface):
def register_config_sections(
self, config_list: list[ap_types.SectionConfig]
) -> list[ap_types.SectionConfig]:
"""Extension will receive the list of section config objects."""
return config_list

def register_toolbar_button(
self, toolbar_buttons_list: list[ap_types.ToolbarButton]
) -> list[ap_types.ToolbarButton]:
Expand Down
52 changes: 50 additions & 2 deletions ckanext/ap_main/plugin.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from __future__ import annotations

from typing import Any, Callable
from typing import Any, Callable, Literal

import ckan.plugins as p
import ckan.plugins.toolkit as tk
from ckan.types import SignalMapping

from ckanext.collection.interfaces import ICollection, CollectionFactory
import ckanext.ap_main.types as ap_types
from ckanext.ap_main import helpers, collection
from ckanext.ap_main.col_renderers import get_renderers
from ckanext.ap_main import helpers, collection, utils
from ckanext.ap_main.interfaces import IAdminPanel


Expand All @@ -18,6 +19,7 @@
class AdminPanelPlugin(p.SingletonPlugin):
p.implements(p.IConfigurer)
p.implements(p.IBlueprint)
p.implements(p.ISignal)
p.implements(p.ITemplateHelpers)
p.implements(IAdminPanel, inherit=True)
p.implements(ICollection, inherit=True)
Expand Down Expand Up @@ -46,3 +48,49 @@ def get_collection_factories(self) -> dict[str, CollectionFactory]:
"ap-user": collection.UserCollection,
"ap-logs": collection.DbLogCollection,
}

# ISignal

def get_signal_subscriptions(self) -> SignalMapping:
return {
utils.collect_sections_signal: [
collect_config_sections_subscriber,
],
# utils.collect_pages_signal: [
# {
# "sender": "Basic site settings",
# "receiver": collect_basic_pages_subscriber,
# },
# ],
}


def collect_config_sections_subscriber(sender: None):
return ap_types.SectionConfig(
name="Basic site settings",
configs=[
ap_types.ConfigurationItem(
name=tk._("CKAN configuration"),
info=tk._("CKAN site config options"),
blueprint=(
"ap_basic.editable_config"
if p.plugin_loaded("editable_config")
else "ap_basic.config"
),
),
],
)


# def collect_basic_pages_subscriber(sender: Literal["Basic site settings"]):
# return [
# ap_types.ConfigurationItem(
# name=tk._("CKAN configuration"),
# info=tk._("CKAN site config options"),
# blueprint=(
# "ap_basic.editable_config"
# if p.plugin_loaded("editable_config")
# else "ap_basic.config"
# ),
# ),
# ]
8 changes: 4 additions & 4 deletions ckanext/ap_main/templates/admin_panel/config/config_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ <h1>{{ _("List of config options") }}</h1>
<div class="col-12 col-lg-6">
<div class="accordion accordion-flush" id="{{ parent_accordion_id }}">
<div class="accordion-item">
<h2 class="accordion-header" id="flush-headingOne">
<h2 class="accordion-header">
<button class="accordion-button" type="button" data-bs-toggle="collapse"
data-bs-target="#{{ accordion_id }}" aria-expanded="true"
aria-controls="{{ accordion_id }}">
aria-controls="{{ accordion_id }}" ap-section="{{ h.ap_munge_string(section.name) }}">
{{ section.name | truncate(69) }}
</button>
</h2>
<div id="{{ accordion_id }}" class="accordion-collapse show" aria-labelledby="flush-headingOne">
<div id="{{ accordion_id }}" class="accordion-collapse show">
<div class="accordion-body">
<div class="list-group">
{% for config in section.configs %}
<li class="list-group-item d-flex flex-column">
<li class="list-group-item d-flex flex-column" ap-section-item="{{ h.ap_munge_string(config.name) }}">
<a href="{{ h.url_for(config.blueprint) }}" aria-current="true">
<i class="fa-solid fa-arrow-right"></i>
{{ config.name }}
Expand Down
11 changes: 11 additions & 0 deletions ckanext/ap_main/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
_renderers_cache: dict[str, ap_types.ColRenderer] = {}


collect_sections_signal = tk.signals.ckanext.signal(
"ap_main:collect_config_sections",
"Collect configuration section names from subscribers",
)

collect_pages_signal = tk.signals.ckanext.signal(
"ap_main:collect_config_pages",
"Collect configuration pages for specific section from subscribers",
)


def ap_before_request() -> None:
try:
tk.check_access(
Expand Down

0 comments on commit f062d01

Please sign in to comment.