diff --git a/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.css b/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.css index 5a8f01a..f873278 100644 --- a/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.css +++ b/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.css @@ -121,6 +121,10 @@ div.sortinfo { margin-top: -2.75em; } +body.hide-resource-info #dtprv_paginate { + margin-top: -1.25em; +} + @media screen and (max-width: 767px) { #dtprv_filter { margin-top: 1px; diff --git a/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.js b/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.js index c99603c..992c97e 100644 --- a/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.js +++ b/ckanext/og_datatables_datefilterview/assets/og_datatables_datefilterview.js @@ -325,6 +325,7 @@ this.ckan.module('og_datatables_datefilter_view', function (jQuery) { const copyprintbuttons = dtprv.data('copy-print-buttons') const exportbutton = dtprv.data('export-button') const colreorder = dtprv.data('col-reorder') + const hideresourceinfo = (dtprv.data('hide-resource-info') ?? 'False').toString().toLowerCase() === 'true' const order = dtprv.data('order') const showid = (dtprv.data('show-id') ?? 'False').toString().toLowerCase() === 'true'; @@ -653,10 +654,14 @@ this.ckan.module('og_datatables_datefilter_view', function (jQuery) { }) // add resourceinfo in footer, very useful if this view is embedded - const resourceInfo = document.getElementById('dtv-resource-info').innerText - $('div.resourceinfo').html('' + - packagename + '—' + resourcename + - ' ') + if (!hideresourceinfo) { + const resourceInfo = document.getElementById('dtv-resource-info').innerText + $('div.resourceinfo').html('' + + packagename + '—' + resourcename + + ' ') + } else { + $('body').addClass('hide-resource-info') + } // if in list/responsive mode, hide search inputs for hidden columns if (gcurrentView === 'list') { diff --git a/ckanext/og_datatables_datefilterview/plugin.py b/ckanext/og_datatables_datefilterview/plugin.py index 20a3f35..8fed8f2 100644 --- a/ckanext/og_datatables_datefilterview/plugin.py +++ b/ckanext/og_datatables_datefilterview/plugin.py @@ -49,6 +49,8 @@ def update_config(self, config): config.get(u'ckan.datatables.view_table_displaycopyprint_default', False)) self.col_reorder_def = toolkit.asbool( config.get(u'ckan.datatables.view_table_colreorder_default', True)) + self.hide_resource_info_def = toolkit.asbool( + config.get(u'ckan.datatables.hide_resource_info_default', False)) # https://datatables.net/reference/option/lengthMenu self.page_length_choices = toolkit.aslist( @@ -105,6 +107,7 @@ def form_template(self, context, data_dict): data_dict['resource_view']['export_button_def'] = self.export_button_def data_dict['resource_view']['copy_print_buttons_def'] = self.copy_print_buttons_def data_dict['resource_view']['col_reorder_def'] = self.col_reorder_def + data_dict['resource_view']['hide_resource_info_def'] = self.hide_resource_info_def return u'og_datatables_datefilterview/datatables_form.html' def info(self): @@ -142,6 +145,7 @@ def info(self): u'export_button': [configurabledefaults_validator(self.export_button_def), boolean_validator], u'copy_print_buttons': [configurabledefaults_validator(self.copy_print_buttons_def), boolean_validator], u'col_reorder': [configurabledefaults_validator(self.col_reorder_def), boolean_validator], + u'hide_resource_info': [configurabledefaults_validator(self.hide_resource_info_def), boolean_validator], u'ellipsis_length': [default(self.ellipsis_length), natural_number_validator], u'date_format': [default(self.date_format)], @@ -180,7 +184,8 @@ def callable(key, data, errors, context): # the browser POSTs a null value, so we set it to False data[key] = False else: - # the view is being created by the default view mechanism, - # so we set the values following the configurable defaults - data[key] = default_configurable_value + # the view is being created by the default view mechanism or via API/tests + # If a value is explicitly provided, use it; otherwise use the configurable default + if data.get(key) is missing or data.get(key) is None: + data[key] = default_configurable_value return callable diff --git a/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_form.html b/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_form.html index 17650b6..d8a0b6a 100644 --- a/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_form.html +++ b/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_form.html @@ -52,6 +52,16 @@ Allow column reorder +
+ +
diff --git a/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_view.html b/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_view.html index bf4f918..b4e3e8a 100644 --- a/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_view.html +++ b/ckanext/og_datatables_datefilterview/templates/og_datatables_datefilterview/datatables_view.html @@ -44,6 +44,7 @@ data-copy-print-buttons="{{ resource_view.get('copy_print_buttons') }}" data-export-button="{{ resource_view.get('export_button') }}" data-col-reorder="{{ resource_view.get('col_reorder')}}" + data-hide-resource-info="{{ resource_view.get('hide_resource_info')|lower }}" data-show-id="{{ 'show_fields' not in resource_view or '_id' in resource_view.show_fields }}"> diff --git a/ckanext/og_datatables_datefilterview/tests/test_date_filters.py b/ckanext/og_datatables_datefilterview/tests/test_date_filters.py index c686b9e..c5bcb5b 100644 --- a/ckanext/og_datatables_datefilterview/tests/test_date_filters.py +++ b/ckanext/og_datatables_datefilterview/tests/test_date_filters.py @@ -1,6 +1,8 @@ # encoding: utf-8 import pytest +import ckan.plugins.toolkit as toolkit +from ckan.tests import factories from ckanext.og_datatables_datefilterview.blueprint import ( _is_valid_date, _normalize_date, @@ -209,3 +211,155 @@ def test_yyyy_mm_dd_stays_normalized(self): assert _is_valid_date(date_str) == True normalized = _normalize_date(date_str) assert normalized == '2024-01-15' + + +@pytest.mark.usefixtures("clean_db") +class TestResourceViewConfiguration: + """Tests for resource view configuration options""" + + def test_og_datatables_datefilterview_on_resource_page_success(self): + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables with Date Filter', + view_type='og_datatables_datefilter_view' + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('title') == 'OG Data Tables with Date Filter' + assert response.get('view_type') == 'og_datatables_datefilter_view' + + + def test_og_datatables_datefilterview_hide_resource_info_true_success(self): + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables with Date Filter', + view_type='og_datatables_datefilter_view', + hide_resource_info=True + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == True + + + def test_og_datatables_datefilterview_hide_resource_info_false_success(self): + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables with Date Filter', + view_type='og_datatables_datefilter_view', + hide_resource_info=False + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == False + + + def test_og_datatables_datefilterview_hide_resource_info_default_false_success(self): + """Test that hide_resource_info defaults to False when not specified""" + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables with Date Filter', + view_type='og_datatables_datefilter_view' + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == False + + + def test_og_datatables_datefilterview_hide_resource_info_with_other_options_success(self): + """Test hide_resource_info works correctly with other configuration options""" + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables with Date Filter', + view_type='og_datatables_datefilter_view', + hide_resource_info=True, + export_button=False, + responsive=True, + copy_print_buttons=False, + col_reorder=True + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == True + assert response.get('export_button') == False + assert response.get('responsive') == True + assert response.get('copy_print_buttons') == False + assert response.get('col_reorder') == True + + + def test_og_datatables_datefilterview_update_hide_resource_info_success(self): + """Test updating hide_resource_info on an existing view""" + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables with Date Filter', + view_type='og_datatables_datefilter_view', + hide_resource_info=False + ) + + # Update to hide resource info + toolkit.get_action('resource_view_update')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id'), 'hide_resource_info': True} + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == True diff --git a/ckanext/og_datatablesview/assets/og_datatablesview.css b/ckanext/og_datatablesview/assets/og_datatablesview.css index 5a8f01a..f873278 100644 --- a/ckanext/og_datatablesview/assets/og_datatablesview.css +++ b/ckanext/og_datatablesview/assets/og_datatablesview.css @@ -121,6 +121,10 @@ div.sortinfo { margin-top: -2.75em; } +body.hide-resource-info #dtprv_paginate { + margin-top: -1.25em; +} + @media screen and (max-width: 767px) { #dtprv_filter { margin-top: 1px; diff --git a/ckanext/og_datatablesview/assets/og_datatablesview.js b/ckanext/og_datatablesview/assets/og_datatablesview.js index 769912b..cf6e510 100644 --- a/ckanext/og_datatablesview/assets/og_datatablesview.js +++ b/ckanext/og_datatablesview/assets/og_datatablesview.js @@ -325,6 +325,7 @@ this.ckan.module('og_datatables_view', function (jQuery) { const copyprintbuttons = dtprv.data('copy-print-buttons') const exportbutton = dtprv.data('export-button') const colreorder = dtprv.data('col-reorder') + const hideresourceinfo = (dtprv.data('hide-resource-info') ?? 'False').toString().toLowerCase() === 'true' const order = dtprv.data('order') const showid = (dtprv.data('show-id') ?? 'False').toString().toLowerCase() === 'true'; @@ -645,10 +646,14 @@ this.ckan.module('og_datatables_view', function (jQuery) { }) // add resourceinfo in footer, very useful if this view is embedded - const resourceInfo = document.getElementById('dtv-resource-info').innerText - $('div.resourceinfo').html('' + - packagename + '—' + resourcename + - ' ') + if (!hideresourceinfo) { + const resourceInfo = document.getElementById('dtv-resource-info').innerText + $('div.resourceinfo').html('' + + packagename + '—' + resourcename + + ' ') + } else { + $('body').addClass('hide-resource-info') + } // if in list/responsive mode, hide search inputs for hidden columns if (gcurrentView === 'list') { diff --git a/ckanext/og_datatablesview/plugin.py b/ckanext/og_datatablesview/plugin.py index 16d939f..bc7aead 100644 --- a/ckanext/og_datatablesview/plugin.py +++ b/ckanext/og_datatablesview/plugin.py @@ -49,6 +49,8 @@ def update_config(self, config): config.get(u'ckan.datatables.view_table_displaycopyprint_default', False)) self.col_reorder_def = toolkit.asbool( config.get(u'ckan.datatables.view_table_colreorder_default', True)) + self.hide_resource_info_def = toolkit.asbool( + config.get(u'ckan.datatables.hide_resource_info_default', False)) # https://datatables.net/reference/option/lengthMenu self.page_length_choices = toolkit.aslist( @@ -105,6 +107,7 @@ def form_template(self, context, data_dict): data_dict['resource_view']['export_button_def'] = self.export_button_def data_dict['resource_view']['copy_print_buttons_def'] = self.copy_print_buttons_def data_dict['resource_view']['col_reorder_def'] = self.col_reorder_def + data_dict['resource_view']['hide_resource_info_def'] = self.hide_resource_info_def return u'og_datatables/datatables_form.html' def info(self): @@ -142,6 +145,7 @@ def info(self): u'export_button': [configurabledefaults_validator(self.export_button_def), boolean_validator], u'copy_print_buttons': [configurabledefaults_validator(self.copy_print_buttons_def), boolean_validator], u'col_reorder': [configurabledefaults_validator(self.col_reorder_def), boolean_validator], + u'hide_resource_info': [configurabledefaults_validator(self.hide_resource_info_def), boolean_validator], u'ellipsis_length': [default(self.ellipsis_length), natural_number_validator], u'date_format': [default(self.date_format)], @@ -180,7 +184,8 @@ def callable(key, data, errors, context): # the browser POSTs a null value, so we set it to False data[key] = False else: - # the view is being created by the default view mechanism, - # so we set the values following the configurable defaults - data[key] = default_configurable_value + # the view is being created by the default view mechanism or via API/tests + # If a value is explicitly provided, use it; otherwise use the configurable default + if data.get(key) is missing or data.get(key) is None: + data[key] = default_configurable_value return callable diff --git a/ckanext/og_datatablesview/templates/og_datatables/datatables_form.html b/ckanext/og_datatablesview/templates/og_datatables/datatables_form.html index 17650b6..d8a0b6a 100644 --- a/ckanext/og_datatablesview/templates/og_datatables/datatables_form.html +++ b/ckanext/og_datatablesview/templates/og_datatables/datatables_form.html @@ -52,6 +52,16 @@ Allow column reorder
+
+ +
diff --git a/ckanext/og_datatablesview/templates/og_datatables/datatables_view.html b/ckanext/og_datatablesview/templates/og_datatables/datatables_view.html index 7740982..4e9a5f4 100644 --- a/ckanext/og_datatablesview/templates/og_datatables/datatables_view.html +++ b/ckanext/og_datatablesview/templates/og_datatables/datatables_view.html @@ -44,6 +44,7 @@ data-copy-print-buttons="{{ resource_view.get('copy_print_buttons') }}" data-export-button="{{ resource_view.get('export_button') }}" data-col-reorder="{{ resource_view.get('col_reorder')}}" + data-hide-resource-info="{{ resource_view.get('hide_resource_info')|lower }}" data-show-id="{{ 'show_fields' not in resource_view or '_id' in resource_view.show_fields }}"> diff --git a/ckanext/og_datatablesview/tests/test_logic.py b/ckanext/og_datatablesview/tests/test_logic.py index ac1d8e8..2afbf6d 100644 --- a/ckanext/og_datatablesview/tests/test_logic.py +++ b/ckanext/og_datatablesview/tests/test_logic.py @@ -235,6 +235,132 @@ def test_og_datatableview_only_modify_one_view_success(self): assert response_1.get('description') != response_2.get('description') + def test_og_datatableview_hide_resource_info_true_success(self): + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables', + view_type='og_datatables_view', + hide_resource_info=True + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == True + + + def test_og_datatableview_hide_resource_info_false_success(self): + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables', + view_type='og_datatables_view', + hide_resource_info=False + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == False + + + def test_og_datatableview_hide_resource_info_default_false_success(self): + """Test that hide_resource_info defaults to False when not specified""" + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables', + view_type='og_datatables_view' + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == False + + + def test_og_datatableview_hide_resource_info_with_other_options_success(self): + """Test hide_resource_info works correctly with other configuration options""" + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables', + view_type='og_datatables_view', + hide_resource_info=True, + export_button=False, + responsive=True, + copy_print_buttons=False, + col_reorder=True + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == True + assert response.get('export_button') == False + assert response.get('responsive') == True + assert response.get('copy_print_buttons') == False + assert response.get('col_reorder') == True + + + def test_og_datatableview_update_hide_resource_info_success(self): + """Test updating hide_resource_info on an existing view""" + sysadmin = factories.Sysadmin() + dataset = factories.Dataset() + resource = factories.Resource( + package_id=dataset['id'], + format='CSV' + ) + resource_view = factories.ResourceView( + resource_id=resource['id'], + title='OG Data Tables', + view_type='og_datatables_view', + hide_resource_info=False + ) + + # Update to hide resource info + toolkit.get_action('resource_view_update')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id'), 'hide_resource_info': True} + ) + + response = toolkit.get_action('resource_view_show')( + {'user': sysadmin.get('name')}, + {'id': resource_view.get('id')} + ) + + assert response.get('hide_resource_info') == True + + class TestFormatFtsQuery: def test_format_fts_query_empty_string(self):