Skip to content

Commit 378a22e

Browse files
committed
IADBXCIGB-77 / hotfix group and organization follow actions
1 parent cc9abff commit 378a22e

5 files changed

Lines changed: 122 additions & 4 deletions

File tree

ckanext/idb_theme/plugin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515

1616
@tk.blanket.helpers
17+
@tk.blanket.blueprints
1718
@tk.blanket.config_declarations
1819
class IdbThemePlugin(ITheme, p.SingletonPlugin):
1920
@override
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
from ckan.lib.helpers import url_for
6+
from ckan.tests import factories
7+
8+
pytestmark = [
9+
pytest.mark.usefixtures("with_plugins", "clean_db"),
10+
pytest.mark.ckan_config("ckan.auth.public_user_details", False),
11+
]
12+
13+
14+
def test_non_admin_can_follow_and_unfollow_group(app):
15+
user = factories.User()
16+
group = factories.Group()
17+
app.set_session_user(user["name"])
18+
19+
response = app.post(url_for("idb_theme.group_follow", id=group["id"]))
20+
21+
assert response.status_code == 200
22+
assert "Unfollow" in response
23+
24+
response = app.post(url_for("idb_theme.group_unfollow", id=group["id"]))
25+
26+
assert response.status_code == 200
27+
assert "Follow" in response
28+
29+
30+
def test_non_admin_can_follow_and_unfollow_organization(app):
31+
user = factories.User()
32+
organization = factories.Organization()
33+
app.set_session_user(user["name"])
34+
35+
response = app.post(url_for("idb_theme.organization_follow", id=organization["id"]))
36+
37+
assert response.status_code == 200
38+
assert "Unfollow" in response
39+
40+
response = app.post(url_for("idb_theme.organization_unfollow", id=organization["id"]))
41+
42+
assert response.status_code == 200
43+
assert "Follow" in response

ckanext/idb_theme/themes/idb/templates/group/snippets/info.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@
5757
{% if error_message %}
5858
<div class="alert alert-danger">{{ error_message }}</div>
5959
{% elif am_following %}
60-
{{ ui.button(ui.icon("circle-minus", style="solid") ~ _("Unfollow"), style="danger", hx={"target": "#group-info", "post": h.url_for('group.unfollow', id=group.id)}) }}
60+
{{ ui.button(ui.icon("circle-minus", style="solid") ~ _("Unfollow"), style="danger", hx={"target": "#group-info", "post": h.url_for('idb_theme.group_unfollow', id=group.id)}) }}
6161
{% else %}
62-
{{ ui.button(ui.icon("circle-plus", style="solid") ~ _("Follow"), style="success", hx={"target": "#group-info", "post": h.url_for('group.follow', id=group.id)}) }}
62+
{{ ui.button(ui.icon("circle-plus", style="solid") ~ _("Follow"), style="success", hx={"target": "#group-info", "post": h.url_for('idb_theme.group_follow', id=group.id)}) }}
6363
{%- endif -%}
6464

6565
{% endif %}

ckanext/idb_theme/themes/idb/templates/organization/snippets/info.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@
7676
{% if error_message %}
7777
<div class="alert alert-danger">{{ error_message }}</div>
7878
{% elif am_following %}
79-
{{ ui.button(ui.icon("circle-minus", style="solid") ~ _("Unfollow"), style="danger", hx={"target": "#organization-info", "post": h.url_for('organization.unfollow', id=organization.id)}) }}
79+
{{ ui.button(ui.icon("circle-minus", style="solid") ~ _("Unfollow"), style="danger", hx={"target": "#organization-info", "post": h.url_for('idb_theme.organization_unfollow', id=organization.id)}) }}
8080
{% else %}
81-
{{ ui.button(ui.icon("circle-plus", style="solid") ~ _("Follow"), style="success", hx={"target": "#organization-info", "post": h.url_for('organization.follow', id=organization.id)}) }}
81+
{{ ui.button(ui.icon("circle-plus", style="solid") ~ _("Follow"), style="success", hx={"target": "#organization-info", "post": h.url_for('idb_theme.organization_follow', id=organization.id)}) }}
8282

8383
{% endif %}
8484
{% endif %}

ckanext/idb_theme/views.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from __future__ import annotations
2+
3+
from flask import Blueprint
4+
5+
import ckan.plugins.toolkit as tk
6+
from ckan.common import current_user
7+
8+
__all__ = ["bp"]
9+
10+
bp = Blueprint("idb_theme", __name__, url_prefix="/idb-theme")
11+
12+
13+
# Temporary hotfix for https://github.com/ckan/ckan/pull/9394.
14+
def _follow_group(id: str, *, is_organization: bool, follow: bool) -> str:
15+
group_type = "organization" if is_organization else "group"
16+
data_dict = {
17+
"id": id,
18+
"include_datasets": True,
19+
"include_users": False,
20+
}
21+
if not follow:
22+
data_dict["include_followers"] = True
23+
24+
extra_vars = {
25+
"current_user": current_user,
26+
"show_nums": True,
27+
}
28+
29+
try:
30+
action = "organization_show" if is_organization else "group_show"
31+
group_dict = tk.get_action(action)({}, data_dict)
32+
except (tk.ObjectNotFound, tk.NotAuthorized):
33+
msg = tk._(f"{group_type} not found or you have no permission to view it")
34+
tk.abort(404, msg)
35+
36+
error_message = ""
37+
try:
38+
if follow:
39+
tk.get_action("follow_group")({}, {"id": id})
40+
extra_vars["am_following"] = True
41+
else:
42+
tk.get_action("unfollow_group")({}, {"id": id})
43+
extra_vars["am_following"] = False
44+
except tk.ValidationError as error:
45+
error_message = error.error_summary
46+
47+
extra_vars["error_message"] = error_message
48+
49+
if is_organization:
50+
extra_vars["organization"] = group_dict
51+
return tk.render("organization/snippets/info.html", extra_vars)
52+
53+
extra_vars["group"] = group_dict
54+
return tk.render("group/snippets/info.html", extra_vars)
55+
56+
57+
@bp.post("/group/follow/<id>")
58+
def group_follow(id: str) -> str:
59+
return _follow_group(id, is_organization=False, follow=True)
60+
61+
62+
@bp.post("/group/unfollow/<id>")
63+
def group_unfollow(id: str) -> str:
64+
return _follow_group(id, is_organization=False, follow=False)
65+
66+
67+
@bp.post("/organization/follow/<id>")
68+
def organization_follow(id: str) -> str:
69+
return _follow_group(id, is_organization=True, follow=True)
70+
71+
72+
@bp.post("/organization/unfollow/<id>")
73+
def organization_unfollow(id: str) -> str:
74+
return _follow_group(id, is_organization=True, follow=False)

0 commit comments

Comments
 (0)