diff --git a/lizmap/definitions/attribute_table.py b/lizmap/definitions/attribute_table.py index 483a957b..fd87002a 100755 --- a/lizmap/definitions/attribute_table.py +++ b/lizmap/definitions/attribute_table.py @@ -2,9 +2,10 @@ from qgis.core import QgsAttributeTableConfig, QgsVectorLayer from lizmap.definitions.base import BaseDefinitions, InputType +from lizmap.definitions.definitions import LwcVersions from lizmap.toolbelt.i18n import tr -__copyright__ = 'Copyright 2020, 3Liz' +__copyright__ = 'Copyright 2025, 3Liz' __license__ = 'GPL version 3' __email__ = 'info@3liz.org' @@ -41,6 +42,21 @@ def __init__(self): 'default': '', 'tooltip': tr('List of fields to hide in the attribute table.') } + self._layer_config['export_enabled'] = { + 'type': InputType.CheckBox, + 'header': tr('Export enabled'), + 'default': True, + 'tooltip': tr('If the export of the layer is enabled.'), + 'version': LwcVersions.Lizmap_3_9, + 'use_json': True, + } + self._layer_config['export_allowed_groups'] = { + 'type': InputType.Text, + 'header': tr('Allowed groups for export'), + 'default': '', + 'tooltip': tr('Allowed list of groups for exporting the data. If empty, everyone can export the data.'), + 'version': LwcVersions.Lizmap_3_9, + } self._layer_config['pivot'] = { 'type': InputType.CheckBox, 'header': tr('Pivot table'), diff --git a/lizmap/forms/attribute_table_edition.py b/lizmap/forms/attribute_table_edition.py index 111df566..cdd700f4 100755 --- a/lizmap/forms/attribute_table_edition.py +++ b/lizmap/forms/attribute_table_edition.py @@ -1,6 +1,7 @@ """Dialog for attribute table edition.""" from qgis.core import QgsMapLayerProxyModel +from qgis.PyQt.QtGui import QIcon from lizmap.definitions.attribute_table import ( AttributeTableDefinitions, @@ -9,9 +10,9 @@ from lizmap.definitions.definitions import LwcVersions from lizmap.forms.base_edition_dialog import BaseEditionDialog from lizmap.toolbelt.i18n import tr -from lizmap.toolbelt.resources import load_ui +from lizmap.toolbelt.resources import load_ui, resources_path -__copyright__ = 'Copyright 2020, 3Liz' +__copyright__ = 'Copyright 2025, 3Liz' __license__ = 'GPL version 3' __email__ = 'info@3liz.org' @@ -28,6 +29,8 @@ def __init__(self, parent=None, unicity=None, lwc_version: LwcVersions = None): self.config.add_layer_widget('layerId', self.layer) self.config.add_layer_widget('primaryKey', self.primary_key) self.config.add_layer_widget('hiddenFields', self.fields_to_hide) + self.config.add_layer_widget('export_enabled', self.export_enabled) + self.config.add_layer_widget('export_allowed_groups', self.export_allowed_groups) self.config.add_layer_widget('pivot', self.pivot_table) self.config.add_layer_widget('hideAsChild', self.hide_subpanels) self.config.add_layer_widget('hideLayer', self.hide_layer) @@ -36,6 +39,8 @@ def __init__(self, parent=None, unicity=None, lwc_version: LwcVersions = None): self.config.add_layer_label('layerId', self.label_layer) self.config.add_layer_label('primaryKey', self.label_primary_key) self.config.add_layer_label('hiddenFields', self.label_fields_to_hide) + self.config.add_layer_label('export_enabled', self.label_export_enabled) + self.config.add_layer_label('export_allowed_groups', self.label_export_allowed_groups) self.config.add_layer_label('pivot', self.label_pivot_table) self.config.add_layer_label('hideAsChild', self.label_hide_subpanels) self.config.add_layer_label('hideLayer', self.label_hide_layer) @@ -51,6 +56,15 @@ def __init__(self, parent=None, unicity=None, lwc_version: LwcVersions = None): self.fields_to_hide.set_layer(self.layer.currentLayer()) self.setup_ui() + + # Wizard ACL group + self.export_enabled.stateChanged.connect(self.export_allowed_groups.setEnabled) + icon = QIcon(resources_path('icons', 'user_group.svg')) + self.button_wizard_group.setText('') + self.button_wizard_group.setIcon(icon) + self.button_wizard_group.clicked.connect(self.open_wizard_group) + self.button_wizard_group.setToolTip(tr("Open the group wizard")) + self.check_layer_wfs() self.enable_primary_key_field() @@ -64,6 +78,15 @@ def check_layer_wfs(self): not_in_wfs = self.is_layer_in_wfs(layer) self.show_error(not_in_wfs) + def open_wizard_group(self): + """ When the user clicks on the group wizard. """ + layer = self.layer.currentLayer() + if not layer: + return + + helper = tr("Setting groups for the layer exporting capabilities '{}'").format(layer.name()) + super().open_wizard_dialog(helper) + def post_load_form(self): self.layer_changed() diff --git a/lizmap/forms/base_edition_dialog.py b/lizmap/forms/base_edition_dialog.py index 66f60cd7..953bb415 100755 --- a/lizmap/forms/base_edition_dialog.py +++ b/lizmap/forms/base_edition_dialog.py @@ -23,7 +23,7 @@ from lizmap.qt_style_sheets import NEW_FEATURE_COLOR, NEW_FEATURE_CSS from lizmap.toolbelt.i18n import tr -__copyright__ = 'Copyright 2023, 3Liz' +__copyright__ = 'Copyright 2025, 3Liz' __license__ = 'GPL version 3' __email__ = 'info@3liz.org' @@ -61,6 +61,7 @@ def __init__(self, parent: QDialog = None, unicity=None, lwc_version: LwcVersion self.lwc_versions[LwcVersions.Lizmap_3_6] = [] self.lwc_versions[LwcVersions.Lizmap_3_7] = [] self.lwc_versions[LwcVersions.Lizmap_3_8] = [] + self.lwc_versions[LwcVersions.Lizmap_3_9] = [] def setup_ui(self): """ Build the UI. """ diff --git a/lizmap/resources/ui/ui_form_attribute_table.ui b/lizmap/resources/ui/ui_form_attribute_table.ui index a0ef33a4..95e85999 100755 --- a/lizmap/resources/ui/ui_form_attribute_table.ui +++ b/lizmap/resources/ui/ui_form_attribute_table.ui @@ -6,8 +6,8 @@ 0 0 - 425 - 303 + 554 + 390 @@ -43,6 +43,9 @@ + + + @@ -71,6 +74,13 @@ + + + + Hide layer in the list + + + @@ -81,16 +91,13 @@ - - + + - Hide layer in the list + Has a custom config - - - @@ -98,10 +105,38 @@ - - + + - Has a custom config + Export allowed groups + + + + + + + + + + + + + + + + + + + WIZARD + + + + + + + + + Export enabled diff --git a/lizmap/test/test_table_manager.py b/lizmap/test/test_table_manager.py index e4cd1a92..ee5a425f 100755 --- a/lizmap/test/test_table_manager.py +++ b/lizmap/test/test_table_manager.py @@ -991,6 +991,43 @@ def test_attribute_table(self): # Automatically added, so we add it manually for the comparaison json['lines']['custom_config'] = 'False' + # Allowing groups for exporting + json['lines']['export_enabled'] = True + self.assertIsNone(json['lines'].get('export_allowed_groups')) + + self.assertDictEqual(data, json) + + self.assertDictEqual({self.layer.id(): ['id']}, table_manager.wfs_fields_used()) + + def test_attribute_table_export_acl(self): + """Test table manager with attribute table with export ACL""" + table = QTableWidget() + definitions = AttributeTableDefinitions() + + table_manager = TableManager( + None, definitions, None, table, None, None, None, None) + + json = { + 'lines': { + 'primaryKey': 'id', + 'export_enabled': True, + 'export_allowed_groups': 'admins', + 'hiddenFields': 'id,name,value', + 'pivot': 'False', + 'hideAsChild': 'False', + 'hideLayer': 'False', + 'layerId': self.layer.id(), + 'order': 0 + } + } + self.assertEqual(table_manager.table.rowCount(), 0) + table_manager.from_json(json) + self.assertEqual(table_manager.table.rowCount(), 1) + data = table_manager.to_json(LwcVersions.latest()) + + # Automatically added, so we add it manually for the comparaison + json['lines']['custom_config'] = 'False' + self.assertDictEqual(data, json) self.assertDictEqual({self.layer.id(): ['id']}, table_manager.wfs_fields_used())