diff --git a/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/group_add_button.html b/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/group_add_button.html new file mode 100644 index 0000000..8ed17b8 --- /dev/null +++ b/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/group_add_button.html @@ -0,0 +1,146 @@ +{# +Group Add Button - Shows add/status button for a single dataset. +#} + +{% set dataset_id = dataset_id or '' %} + +
+ + +
+ + \ No newline at end of file diff --git a/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/group_add_toolbar.html b/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/group_add_toolbar.html new file mode 100644 index 0000000..f7f0ff2 --- /dev/null +++ b/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/group_add_toolbar.html @@ -0,0 +1,142 @@ +{# +Group Add Toolbar - Alpine.js component for bulk adding datasets to groups. +#} + +
+ + {# Toggle Button #} + + + {# Group Dropdown - only visible when enabled #} + +
+ + + + \ No newline at end of file diff --git a/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/package_list_group_add.html b/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/package_list_group_add.html new file mode 100644 index 0000000..33b3a3c --- /dev/null +++ b/ckanext/digitizationknowledge/templates/digitizationknowledge/snippets/package_list_group_add.html @@ -0,0 +1,63 @@ +{# +Package list with group add buttons. +Based on CKAN's snippets/package_list.html but adds group add button to each item. +#} + +{% block package_list %} + {% if packages %} + + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/ckanext/digitizationknowledge/templates/package/search.html b/ckanext/digitizationknowledge/templates/package/search.html index ec153d4..c6f23d3 100644 --- a/ckanext/digitizationknowledge/templates/package/search.html +++ b/ckanext/digitizationknowledge/templates/package/search.html @@ -10,67 +10,36 @@ {% endblock %} -{% block page_primary_action%} +{% block page_primary_action %} {% if h.check_access('package_create') %} -
- +
+ + {# Add Resource dropdown #} + - - - + {# NEW: Group Add Toolbar - only for authenticated users #} + {% if current_user.is_authenticated %} + {% snippet 'digitizationknowledge/snippets/group_add_toolbar.html' %} + {% endif %}
{% endif %} -{%endblock%} +{% endblock %} {% block form %} @@ -92,8 +61,13 @@ {% endblock %} -{% block secondary_content %} +{% block package_search_results_list %} + {# Override to use our custom package list with group add buttons #} + {% snippet 'digitizationknowledge/snippets/package_list_group_add.html', packages=page.items %} +{% endblock %} + +{% block secondary_content %} {% set basic_facets = ['task_clusters', 'task', 'preparations', 'tags', 'digitization_academy_course', 'discipline', 'audience', 'in_language', ] %} {% set all_facet_keys = facet_titles.keys() | list %} @@ -130,7 +104,6 @@ class="btn btn-outline-secondary btn-sm"> - {{ _('Show More Filters') }} {{ _('Show Fewer Filters') }} diff --git a/ckanext/digitizationknowledge/views.py b/ckanext/digitizationknowledge/views.py index c9c86fa..16319fb 100644 --- a/ckanext/digitizationknowledge/views.py +++ b/ckanext/digitizationknowledge/views.py @@ -1,4 +1,7 @@ -from flask import Blueprint, render_template +from flask import Blueprint, render_template, jsonify + +import ckan.plugins.toolkit as toolkit +import ckan.model as model digitizationknowledge = Blueprint( @@ -13,6 +16,10 @@ # "/digitizationknowledge/page", view_func=page) +# ============================================================================= +# Terms of Use and Privacy Policy +# ============================================================================= + # Define page for Terms of Use def terms_of_use(): @@ -33,5 +40,165 @@ def privacy_policy(): "/privacy-policy", view_func=privacy_policy ) +# ============================================================================= +# Group Add Feature - HTMX Routes +# ============================================================================= + +def group_add_list_groups(): + """ + GET /group-add/groups + + Returns a JSON list of groups the current user can add datasets to. + Used to populate the group dropdown in the search page. + """ + # Check if user is logged in + if not toolkit.current_user.is_authenticated: + return jsonify({'success': False, 'error': 'Not authenticated'}), 401 + + context = { + 'user': toolkit.current_user.name, + } + + try: + # Get groups the user can manage (add datasets to) + groups = toolkit.get_action('group_list_authz')(context, {}) + + # Simplify the response - only send what the frontend needs + groups_simple = [ + { + 'id': g['id'], + 'name': g['name'], + 'display_name': g.get('display_name') or g.get('title') or g['name'] + } + for g in groups + ] + + return jsonify({'success': True, 'groups': groups_simple}) + + except toolkit.NotAuthorized: + return jsonify({'success': False, 'error': 'Not authorized'}), 403 + + +def group_add_dataset(): + """ + POST /group-add/add + + Adds a dataset to a group. Expects form data: + - dataset_id: The ID or name of the dataset + - group_id: The ID or name of the group + + Returns an HTML snippet for HTMX to swap in. + """ + # Check if user is logged in + if not toolkit.current_user.is_authenticated: + return 'Not authenticated', 401 + + # Get form data + dataset_id = toolkit.request.form.get('dataset_id') + group_id = toolkit.request.form.get('group_id') + + if not dataset_id or not group_id: + return 'Missing data', 400 + + context = { + 'user': toolkit.current_user.name, + } + + data_dict = { + 'id': group_id, # The group to add to + 'object': dataset_id, # The dataset to add + 'object_type': 'package', + 'capacity': 'public' + } + + try: + toolkit.get_action('member_create')(context, data_dict) + + # Return success HTML snippet for HTMX + return ( + '' + ' Added' + '' + ) + + except toolkit.ObjectNotFound: + return 'Not found', 404 + + except toolkit.NotAuthorized: + return 'Not authorized', 403 + + except toolkit.ValidationError: + return 'Error', 400 + + +def group_add_status(group_id, dataset_id): + """ + GET /group-add/status// + + Checks if a dataset is already a member of a group. + Returns an HTML snippet showing the current status. + """ + # Check if user is logged in + if not toolkit.current_user.is_authenticated: + return '-', 401 + + try: + # Query the Member table directly to check membership + member = model.Session.query(model.Member).filter( + model.Member.group_id == group_id, + model.Member.table_id == dataset_id, + model.Member.table_name == 'package', + model.Member.state == 'active' + ).first() + + if member: + # Already in group + return ( + '' + ' In group' + '' + ) + else: + # Not in group - show add button + return ( + f'' + ) + + except Exception: + return 'Error', 500 + + +# Register the routes +digitizationknowledge.add_url_rule( + "/group-add/groups", + view_func=group_add_list_groups, + methods=['GET'] +) + +digitizationknowledge.add_url_rule( + "/group-add/add", + view_func=group_add_dataset, + methods=['POST'] +) + +digitizationknowledge.add_url_rule( + "/group-add/status//", + view_func=group_add_status, + methods=['GET'] +) + + + +# ============================================================================= +# Blueprint registration +# ============================================================================= + def get_blueprints(): return [digitizationknowledge] +