Skip to content

Commit 97fb728

Browse files
Merge pull request #568 from weni-ai/feature/filters-to-flow-start-logs
Add filters to flow start logs
2 parents ea5adcd + f044af3 commit 97fb728

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

temba/flows/tests.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5936,6 +5936,7 @@ def test_list(self):
59365936
other_org_flow = self.create_flow(org=self.org2)
59375937
FlowStart.create(other_org_flow, self.admin2)
59385938

5939+
# no filtering
59395940
response = self.assertListFetch(
59405941
list_url, allow_viewers=True, allow_editors=True, context_objects=[start3, start2, start1]
59415942
)
@@ -5947,12 +5948,42 @@ def test_list(self):
59475948
self.assertContains(response, "contacts who haven't already been through this flow")
59485949
self.assertContains(response, "<b>1,234</b> runs")
59495950

5951+
# filter by manual type
59505952
response = self.assertListFetch(
59515953
list_url + "?type=manual", allow_viewers=True, allow_editors=True, context_objects=[start1]
59525954
)
59535955
self.assertTrue(response.context["filtered"])
59545956
self.assertEqual(response.context["url_params"], "?type=manual&")
59555957

5958+
# filter by flow
5959+
response = self.client.get(list_url + f"?flow={flow.uuid}")
5960+
self.assertEqual(list(response.context["object_list"]), [start3, start2, start1])
5961+
5962+
# filter by group
5963+
response = self.client.get(list_url + f"?group={group.uuid}")
5964+
self.assertEqual(list(response.context["object_list"]), [start3])
5965+
5966+
# filter by time (last hour)
5967+
now = timezone.now()
5968+
start2.created_on = now - timedelta(minutes=30)
5969+
start2.save(update_fields=["created_on"])
5970+
start3.created_on = now - timedelta(hours=2)
5971+
start3.save(update_fields=["created_on"])
5972+
5973+
# test with valid time parameter
5974+
response = self.client.get(list_url + "?time=60")
5975+
self.assertEqual(list(response.context["object_list"]), [start1, start2]) # ordered by -created_on
5976+
5977+
# test with invalid time parameter
5978+
response = self.client.get(list_url + "?time=invalid")
5979+
self.assertEqual(list(response.context["object_list"]), [start1, start2, start3]) # no time filtering applied
5980+
5981+
# check that we show flows and groups in context
5982+
self.login(self.admin)
5983+
response = self.client.get(list_url)
5984+
self.assertEqual(list(response.context["flows"]), [flow])
5985+
self.assertEqual(list(response.context["contact_groups"]), [group])
5986+
59565987

59575988
class AssetServerTest(TembaTest):
59585989
def test_environment(self):

temba/flows/views.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from django.db.models.functions import Lower
2727
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
2828
from django.urls import reverse
29+
from django.utils import timezone
2930
from django.utils.encoding import force_text
3031
from django.utils.functional import cached_property
3132
from django.utils.translation import ugettext_lazy as _
@@ -2257,16 +2258,45 @@ def get_gear_links(self):
22572258
def derive_queryset(self, *args, **kwargs):
22582259
qs = super().derive_queryset(*args, **kwargs)
22592260

2261+
# Filter by start type
22602262
if self.request.GET.get("type") == "manual":
22612263
qs = qs.filter(start_type=FlowStart.TYPE_MANUAL)
22622264
else:
22632265
qs = qs.filter(start_type__in=(FlowStart.TYPE_MANUAL, FlowStart.TYPE_API, FlowStart.TYPE_API_ZAPIER))
22642266

2267+
# Filter by flow
2268+
flow_uuid = self.request.GET.get("flow")
2269+
if flow_uuid:
2270+
qs = qs.filter(flow__uuid=flow_uuid)
2271+
2272+
# Filter by group
2273+
group_uuid = self.request.GET.get("group")
2274+
if group_uuid:
2275+
qs = qs.filter(groups__uuid=group_uuid)
2276+
2277+
# Filter by time
2278+
minutes = self.request.GET.get("time")
2279+
if minutes:
2280+
try:
2281+
minutes = int(minutes)
2282+
since = timezone.now() - timedelta(minutes=minutes)
2283+
qs = qs.filter(created_on__gte=since)
2284+
except ValueError:
2285+
pass
2286+
22652287
return qs.prefetch_related("contacts", "groups")
22662288

22672289
def get_context_data(self, *args, **kwargs):
22682290
context = super().get_context_data(*args, **kwargs)
2291+
org = self.request.user.get_org()
2292+
2293+
# Add flows for filter dropdown
2294+
context["flows"] = Flow.objects.filter(org=org, is_active=True).order_by("name")
2295+
2296+
# Add contact groups for filter dropdown
2297+
context["contact_groups"] = ContactGroup.user_groups.filter(org=org, is_active=True).order_by("name")
22692298

2299+
# Handle manual filter flag
22702300
filtered = False
22712301
if self.request.GET.get("type") == "manual":
22722302
context["url_params"] = "?type=manual&"

templates/flows/flowstart_list.haml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,34 @@
1111

1212

1313
-block content
14+
%div.flex.gap-4.mb-6
15+
%temba-select#flows.flex-grow(name="flow" label='{{_("Flow")|escapejs}}' searchable="true" onchange="handleSelectChange(this, `flow`)" value="{{ request.GET.flow }}" style="flex-grow: 4;")
16+
%temba-option(name='{{_("All Flows")}}' value="")
17+
-for flow in flows
18+
%temba-option(name="{{flow.name}}" value="{{flow.uuid}}")
19+
20+
%temba-select#groups.flex-grow(name="group" label='{{_("Contact Group")|escapejs}}' searchable="true" onchange="handleSelectChange(this, `group`)" value="{{ request.GET.group }}")
21+
%temba-option(name='{{_("All Groups")}}' value="")
22+
-for group in contact_groups
23+
%temba-option(name="{{group.name}}" value="{{group.uuid}}")
24+
25+
%temba-select#time.flex-grow(name="time" label='{{_("Time")|escapejs}}' searchable="true" onchange="handleSelectChange(this, `time`)" value="{{ request.GET.time }}")
26+
%temba-option(name='{{_("All Time")}}' value="")
27+
%temba-option(name='{{_("Last minute")}}' value="1")
28+
%temba-option(name='2 {{_("minutes")}}' value="2")
29+
%temba-option(name='5 {{_("minutes")}}' value="5")
30+
%temba-option(name='15 {{_("minutes")}}' value="15")
31+
%temba-option(name='30 {{_("minutes")}}' value="30")
32+
%temba-option(name='1 {{_("hour")}}' value="60")
33+
%temba-option(name='3 {{_("hours")}}' value="180")
34+
%temba-option(name='12 {{_("hours")}}' value="720")
35+
%temba-option(name='1 {{_("day")}}' value="1440")
36+
%temba-option(name='2 {{_("days")}}' value="2880")
37+
%temba-option(name='3 {{_("days")}}' value="4320")
38+
%temba-option(name='1 {{_("week")}}' value="10080")
39+
%temba-option(name='2 {{_("weeks")}}' value="20160")
40+
%temba-option(name='1 {{_("month")}}' value="43200")
41+
1442
%table.list.lined
1543
%thead
1644
%tr
@@ -73,3 +101,24 @@
73101

74102
-block paginator
75103
-include "includes/pagination.haml"
104+
105+
-block extra-script
106+
{{ block.super }}
107+
108+
:javascript
109+
function handleSelectChange(event, name) {
110+
if (event.values.length) {
111+
const value = event.values[0].value;
112+
if (value) {
113+
const params = new URLSearchParams(window.location.search);
114+
params.set(name, value);
115+
window.location.search = params.toString();
116+
} else {
117+
const params = new URLSearchParams(window.location.search);
118+
if(params.has(name)) {
119+
params.delete(name);
120+
window.location.search = params.toString();
121+
}
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)