Skip to content

Commit

Permalink
Labels: Added complex filtering logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ebeers-png committed Dec 19, 2023
1 parent acd8337 commit a425f26
Show file tree
Hide file tree
Showing 13 changed files with 293 additions and 180 deletions.
28 changes: 28 additions & 0 deletions seed/migrations/0211_add_filtergroup_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.2.18 on 2023-12-19 16:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('seed', '0210_natural_sort'),
]

operations = [
migrations.AddField(
model_name='filtergroup',
name='and_labels',
field=models.ManyToManyField(related_name='and_filter_groups', to='seed.StatusLabel'),
),
migrations.AddField(
model_name='filtergroup',
name='exclude_labels',
field=models.ManyToManyField(related_name='exclude_filter_groups', to='seed.StatusLabel'),
),
migrations.AddField(
model_name='filtergroup',
name='or_labels',
field=models.ManyToManyField(related_name='or_filter_groups', to='seed.StatusLabel'),
),
]
40 changes: 40 additions & 0 deletions seed/migrations/0212_move_filtergroup_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 3.2.18 on 2023-12-19 16:15

from django.db import migrations

def move_filter_groups(apps, schema_editor):
FilterGroup = apps.get_model('seed', 'FilterGroup')
for filter_group in FilterGroup.objects.all():
if filter_group.labels.exists() and filter_group.label_logic == 0: # and
filter_group.and_labels.set(filter_group.labels.all())
elif filter_group.labels.exists() and filter_group.label_logic == 1: # or
filter_group.or_labels.set(filter_group.labels.all())
elif filter_group.labels.exists() and filter_group.label_logic == 2: # exclude
filter_group.exclude_labels.set(filter_group.labels.all())

def move_filter_groups_back(apps, schema_editor):
# if the filter group only has one set of labels, we can move those back
FilterGroup = apps.get_model('seed', 'FilterGroup')
for filter_group in FilterGroup.objects.all():
if filter_group.and_labels.exists() and not (filter_group.or_labels.exists() or filter_group.exclude_labels.exists()):
filter_group.labels.set(filter_group.and_labels.all())
filter_group.label_logic = 0
filter_group.save()
elif filter_group.or_labels.exists() and not (filter_group.and_labels.exists() or filter_group.exclude_labels.exists()):
filter_group.labels.set(filter_group.or_labels.all())
filter_group.label_logic = 1
filter_group.save()
elif filter_group.exclude_labels.exists() and not (filter_group.and_labels.exists() or filter_group.or_labels.exists()):
filter_group.labels.set(filter_group.exclude_labels.all())
filter_group.label_logic = 2
filter_group.save()

class Migration(migrations.Migration):

dependencies = [
('seed', '0211_add_filtergroup_labels'),
]

operations = [
migrations.RunPython(move_filter_groups, move_filter_groups_back)
]
21 changes: 21 additions & 0 deletions seed/migrations/0213_delete_filtergroup_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.2.18 on 2023-12-19 16:20

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('seed', '0212_move_filtergroup_labels'),
]

operations = [
migrations.RemoveField(
model_name='filtergroup',
name='label_logic',
),
migrations.RemoveField(
model_name='filtergroup',
name='labels',
),
]
26 changes: 15 additions & 11 deletions seed/models/data_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,22 +243,26 @@ def _combine_views(self, filter_views, label_views):
return list(filter_views)

def _get_label_views(self, cycle, filter_group):
if len(filter_group.labels.all()) == 0:
if not filter_group.and_labels.exists() or filter_group.or_labels.exists() or filter_group.exclude_labels.exists():
return None

logic = filter_group.label_logic
labels = Label.objects.filter(id__in=filter_group.labels.all())

if logic == 0: # and
and_labels = filter_group.and_labels.all()
or_labels = filter_group.or_labels.all()
exclude_labels = filter_group.exclude_labels.all()
views = set()
if and_labels.exists(): # and
views_all = []
for label in labels:
for label in and_labels:
views = cycle.propertyview_set.filter(labels__in=[label])
views_all.append(views)
return list(set.intersection(*map(set, views_all)))
elif logic == 1: # or
return list(cycle.propertyview_set.filter(labels__in=labels))
elif logic == 2: # exclude
return list(cycle.propertyview_set.exclude(labels__in=labels))
views = set.intersection(*map(set, views_all))
if or_labels.exists(): # or
or_views = set(cycle.propertyview_set.filter(labels__in=or_labels))
views = set.intersection(views or or_views, or_views)
if exclude_labels.exists(): # exclude
exclude_views = set(cycle.propertyview_set.exclude(labels__in=exclude_labels))
views = set.intersection(views or exclude_views, exclude_views)
return list(views)

def _get_filter_group_views(self, cycle, query_dict):
org_id = self.organization.id
Expand Down
12 changes: 3 additions & 9 deletions seed/models/filter_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,16 @@
)
from seed.models.models import StatusLabel

AND = 0
LABEL_LOGIC_TYPE = [
(AND, 'and'),
(1, 'or'),
(2, 'exclude'),
]


class FilterGroup(models.Model):

name = models.CharField(max_length=255)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name='filter_groups', null=False)
inventory_type = models.IntegerField(choices=VIEW_LIST_INVENTORY_TYPE, default=VIEW_LIST_PROPERTY)
query_dict = models.JSONField(null=False, default=dict)
labels = models.ManyToManyField(StatusLabel)
label_logic = models.IntegerField(choices=LABEL_LOGIC_TYPE, default=AND)
and_labels = models.ManyToManyField(StatusLabel, related_name='and_filter_groups')
or_labels = models.ManyToManyField(StatusLabel, related_name='or_filter_groups')
exclude_labels = models.ManyToManyField(StatusLabel, related_name='exclude_filter_groups')

class Meta:
ordering = ['id']
Expand Down
8 changes: 4 additions & 4 deletions seed/serializers/filter_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
from rest_framework import serializers

from seed.models import VIEW_LIST_INVENTORY_TYPE, FilterGroup
from seed.models.filter_group import LABEL_LOGIC_TYPE


class FilterGroupSerializer(serializers.ModelSerializer):
class Meta:
model = FilterGroup
fields = ('name', 'query_dict', 'inventory_type', 'id', "organization_id", "labels", "label_logic")
fields = ('name', 'query_dict', 'inventory_type', 'id', "organization_id", "and_labels", "or_labels", "exclude_labels")
extra_kwargs = {
'user': {'read_only': True},
'organization': {'read_only': True},
Expand All @@ -24,7 +23,8 @@ def to_representation(self, instance):
ret = super().to_representation(instance)

ret["inventory_type"] = VIEW_LIST_INVENTORY_TYPE[ret["inventory_type"]][1]
ret["label_logic"] = LABEL_LOGIC_TYPE[ret["label_logic"]][1]
ret["labels"] = sorted(ret["labels"])
ret["and_labels"] = sorted(ret["and_labels"])
ret["or_labels"] = sorted(ret["or_labels"])
ret["exclude_labels"] = sorted(ret["exclude_labels"])

return ret
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ angular.module('BE.seed.controller.filter_group_modal', []).controller('filter_g
name: $scope.newName,
query_dict: $scope.data.query_dict,
inventory_type: $scope.data.inventory_type,
labels: $scope.data.labels,
label_logic: $scope.data.label_logic
and_labels: $scope.data.and_labels,
or_labels: $scope.data.or_labels,
exclude_labels: $scope.data.exclude_labels,
})
.then((result) => {
$uibModalInstance.close(result);
Expand Down
Loading

0 comments on commit a425f26

Please sign in to comment.