Skip to content

Commit

Permalink
✨ Allow to store layer's expression filters (authenticathed users) (#623
Browse files Browse the repository at this point in the history
)

* Fix 'mode=delete' behaviour.

* Add FilterLayerSaved model.

* Add mode 'save' and 'delete_saved' in response_filtertoken.

* Add FilterLayerSaved to django admin.

* Add filtertoken new workflow with mode 'save' 'delete_saved' 'apply'

* Testing.

* Testing.

* Testing.

* Testing.

* Refactoring and documentation.

* Add 'filters' property to 'layers' of /api/config REST API.

* Fix

* Change unique condition fro FilterLayerSaved.

* Add test fo /api/config REST API.

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@43226d3

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@001b107

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@84421d7

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@ffbb2a8

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@70c6dbb

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@358886c

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@de74189

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@27e043f

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@9e404cb
    g3w-client-plugin-editing: g3w-suite/g3w-client-plugin-editing@17685ab

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@526a8ea

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@d3b90db

* ✨ Client:
    g3w-client: g3w-suite/g3w-client@533681d

---------

Co-authored-by: wlorenzetti <[email protected]>
Co-authored-by: volterra79 <[email protected]>
  • Loading branch information
3 people authored Oct 31, 2023
1 parent d44c2b7 commit 11f7c9f
Show file tree
Hide file tree
Showing 15 changed files with 500 additions and 28 deletions.
2 changes: 1 addition & 1 deletion g3w-admin/client/static/client/css/app.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion g3w-admin/client/static/client/js/app.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion g3w-admin/editing/static/editing/js/plugin.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions g3w-admin/qdjango/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ class SessionTokenFilterAdmin(admin.ModelAdmin):
]


@admin.register(FilterLayerSaved)
class FilterLayerSavedAdmin(admin.ModelAdmin):
list_display = (
'user',
'layer',
'qgs_expr',
'created',
'modified',
)

class QgisAuthAdminForm(ModelForm):

username = CharField()
Expand Down
22 changes: 21 additions & 1 deletion g3w-admin/qdjango/api/layers/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
__date__ = '2020-05-06'
__copyright__ = 'Copyright 2015 - 2020, Gis3w'

from qdjango.models import Layer
from qdjango.models import Layer, FilterLayerSaved
from rest_framework import serializers
from usersmanage.models import User, Group as AuthGroup

Expand All @@ -36,3 +36,23 @@ class Meta:
fields = ['pk', 'name']


class FilterLayerSavedSerializer(serializers.ModelSerializer):

class Meta:
model = FilterLayerSaved
fields = (
'id',
'name',
)

def to_representation(self, instance):

ret = super().to_representation(instance)

# Change pk(id) with fid
del(ret['id'])
ret['fid'] = instance.pk

return ret


39 changes: 37 additions & 2 deletions g3w-admin/qdjango/api/projects/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@
from rest_framework import serializers
from rest_framework.fields import empty
from owslib.wms import WebMapService
from qdjango.models import Project, Layer, Widget, SessionTokenFilter, GeoConstraintRule, MSG_LEVELS
from qdjango.models import (
Project,
Layer,
Widget,
SessionTokenFilter,
GeoConstraintRule,
MSG_LEVELS,
FilterLayerSaved
)
from qdjango.utils.data import QGIS_LAYER_TYPE_NO_GEOM
from qdjango.utils.models import get_capabilities4layer, get_view_layer_ids
from qdjango.signals import load_qdjango_widget_layer
from qdjango.apps import get_qgs_project
from qdjango.utils.structure import QdjangoMetaLayer, datasourcearcgis2dict
from qdjango.api.layers.serializers import FilterLayerSavedSerializer
from core.utils.structure import mapLayerAttributes
from core.configs import *
from core.signals import after_serialized_project_layer
Expand Down Expand Up @@ -412,6 +421,16 @@ def to_representation(self, instance):
meta_layer = QdjangoMetaLayer()
to_remove_from_layerstree = []

# Get FilterToken layer filters saved:
# Build a layer_filters dict to pass FilterLayerSaved instance to LayerSerializer
layer_filters = {}
filters = FilterLayerSaved.objects.filter(user=self.request.user, layer__project=instance)
for f in filters:
if f.layer.qgs_layer_id not in layer_filters:
layer_filters[f.layer.qgs_layer_id] = []
layer_filters[f.layer.qgs_layer_id].append(f)


def readLeaf(layer, container):

if 'nodes' in layer:
Expand All @@ -431,7 +450,12 @@ def readLeaf(layer, container):

try:
layer_serialized = LayerSerializer(
layers[layer['id']], qgs_project=qgs_project, request=self.request, layertreenode=layer)
layers[layer['id']],
qgs_project=qgs_project,
request=self.request,
layertreenode=layer,
filters=layer_filters[layer['id']] if layer['id'] in layer_filters else []
)
except KeyError:
logger.error(
'Layer %s is missing from QGIS project!' % layer['id'])
Expand Down Expand Up @@ -600,6 +624,10 @@ def __init__(self, instance=None, data=empty, **kwargs):
self.layertreenode = kwargs['layertreenode']
del (kwargs['layertreenode'])

# FilterLayerSaved
self.filters = kwargs['filters']
del (kwargs['filters'])

super(LayerSerializer, self).__init__(instance, data, **kwargs)

class Meta:
Expand Down Expand Up @@ -849,6 +877,13 @@ def to_representation(self, instance):
if 'showfeaturecount' in self.layertreenode and self.layertreenode['showfeaturecount']:
ret['featurecount'] = get_qgis_featurecount(qgs_maplayer)


# Set FilterLayerSaved instances
if len(self.filters) > 0:
ret['filters'] = []
for f in self.filters:
ret['filters'].append(FilterLayerSavedSerializer(f).data)

return ret


Expand Down
29 changes: 29 additions & 0 deletions g3w-admin/qdjango/migrations/0109_filterlayersaved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 3.2.20 on 2023-10-13 15:07

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import model_utils.fields


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('qdjango', '0108_alter_layer_slug'),
]

operations = [
migrations.CreateModel(
name='FilterLayerSaved',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('qgs_expr', models.TextField()),
('layer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='qdjango.layer')),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL)),
],
),
]
18 changes: 18 additions & 0 deletions g3w-admin/qdjango/migrations/0110_sessiontokenfilterlayer_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.20 on 2023-10-16 12:47

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('qdjango', '0109_filterlayersaved'),
]

operations = [
migrations.AddField(
model_name='sessiontokenfilterlayer',
name='name',
field=models.TextField(null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.20 on 2023-10-16 13:06

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('qdjango', '0110_sessiontokenfilterlayer_name'),
]

operations = [
migrations.AlterField(
model_name='sessiontokenfilterlayer',
name='name',
field=models.TextField(null=True, unique=True),
),
]
22 changes: 22 additions & 0 deletions g3w-admin/qdjango/migrations/0112_auto_20231017_0752.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 3.2.20 on 2023-10-17 07:52

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('qdjango', '0111_alter_sessiontokenfilterlayer_name'),
]

operations = [
migrations.RemoveField(
model_name='sessiontokenfilterlayer',
name='name',
),
migrations.AddField(
model_name='filterlayersaved',
name='name',
field=models.TextField(null=True, unique=True),
),
]
24 changes: 24 additions & 0 deletions g3w-admin/qdjango/migrations/0113_auto_20231019_1237.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 3.2.20 on 2023-10-19 12:37

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('qdjango', '0112_auto_20231017_0752'),
]

operations = [
migrations.AlterField(
model_name='filterlayersaved',
name='name',
field=models.TextField(null=True),
),
migrations.AlterUniqueTogether(
name='filterlayersaved',
unique_together={('user', 'layer', 'name')},
),
]
20 changes: 19 additions & 1 deletion g3w-admin/qdjango/models/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from django.db import models
from django.utils.http import int_to_base36
from django.utils.crypto import salted_hmac
from model_utils.models import TimeStampedModel
from usersmanage.models import User
from .projects import Layer
from datetime import datetime
Expand Down Expand Up @@ -86,12 +87,29 @@ class Meta:

class SessionTokenFilterLayer(models.Model):
"""
Model to save qgis espresion for layer by session token filter.
Model to save qgis expression for layer by session token filter.
"""

session_token_filter = models.ForeignKey(SessionTokenFilter, on_delete=models.CASCADE, related_name='stf_layers')
layer = models.ForeignKey(Layer, on_delete=models.CASCADE)
qgs_expr = models.TextField()


class Meta:
app_label = 'qdjango'


class FilterLayerSaved(TimeStampedModel):
"""
Model to save qgis expression for layer by user.
"""

user = models.ForeignKey(User, null=True, blank=True, on_delete=models.DO_NOTHING)
layer = models.ForeignKey(Layer, on_delete=models.CASCADE)
qgs_expr = models.TextField()
name = models.TextField(null=True)

class Meta:
app_label = 'qdjango'
unique_together = ['user', 'layer', 'name']

Binary file modified g3w-admin/qdjango/tests/data/geodata/qgis_widget_test_data.gpkg
Binary file not shown.
Loading

0 comments on commit 11f7c9f

Please sign in to comment.