neptune/core/views/ui/drilldown.py

196 lines
6.0 KiB
Python

import json
import urllib
from django.conf import settings
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from django_tables2 import SingleTableMixin
from rest_framework.parsers import FormParser
from rest_framework.views import APIView
from core.lib.opensearch import query_results
from core.lib.threshold import (
annotate_num_chans,
annotate_num_users,
get_chans,
get_users,
)
from core.views.ui.tables import DrilldownTable
class DrilldownTableView(View, SingleTableMixin):
table_class = DrilldownTable
template_name = "ui/drilldown/table_results.html"
paginate_by = 5
def post(self, request):
context = query_results(request)
table = DrilldownTable(context["results"])
context["table"] = table
del context["results"]
if "message" in context:
return render(request, self.template_name, context)
if self.request.htmx:
template_name = "ui/drilldown/table_results.html"
else:
template_name = "ui/drilldown/table_results_partial.html"
if context:
return render(request, template_name, context)
else:
return HttpResponse("No results")
def parse_dates(dates):
spl = dates.split(" - ")
if all(spl):
spl = [f"{x.replace(' ', 'T')}" for x in spl]
if not len(spl) == 2:
message = "Invalid dates"
message_class = "danger"
return {"message": message, "class": message_class}
from_ts, to_ts = spl
from_date, from_time = from_ts.split("T")
to_date, to_time = to_ts.split("T")
return {
"from_date": from_date,
"to_date": to_date,
"from_time": from_time,
"to_time": to_time,
}
def create_tags(query):
"""
Grab the tags out of the query and make a list
we can add to the Bulma tags element when the page loads.
"""
spl = query.split("AND")
spl = [x.strip() for x in spl if ":" in x]
spl = [x.replace('"', "") for x in spl]
tags = [f"{tag}: {elem}" for tag, elem in [x.split(":") for x in spl]]
return tags
def drilldown_search(request):
template_name = "ui/drilldown/results.html"
if request.GET:
query_params = request.GET.dict()
elif request.POST:
query_params = request.POST.dict()
# Parse the dates
if "dates" in query_params:
dates = parse_dates(query_params["dates"])
del query_params["dates"]
if dates:
if "message" in dates:
return render(request, template_name, dates)
query_params["from_date"] = dates["from_date"]
query_params["to_date"] = dates["to_date"]
query_params["from_time"] = dates["from_time"]
query_params["to_time"] = dates["to_time"]
if request.GET:
context = query_results(request, query_params)
elif request.POST:
context = query_results(request, query_params)
# Turn the query into tags for populating the taglist
tags = create_tags(query_params["query"])
context["tags"] = tags
context["params"] = query_params
if "message" in context:
return render(request, template_name, context)
context["data"] = json.dumps(
[
{
"text": item.get("msg", None) or item.get("id"),
"nick": item.get("nick", None),
"value": item.get("sentiment", None) or None,
"date": item.get("ts"),
}
for item in context["results"]
]
)
if context:
response = render(request, template_name, context)
if request.GET:
return context
elif request.POST:
del query_params["csrfmiddlewaretoken"]
url_params = urllib.parse.urlencode(query_params)
response["HX-Push"] = reverse("home") + "?" + url_params
return response
else:
return HttpResponse("No results")
class Drilldown(View):
template_name = "ui/drilldown/drilldown.html"
plan_name = "drilldown"
def get(self, request):
if request.user.is_anonymous:
sizes = settings.OPENSEARCH_MAIN_SIZES_ANON
else:
sizes = settings.OPENSEARCH_MAIN_SIZES
context = {}
if request.GET:
context = drilldown_search(request)
context["sizes"] = sizes
return render(request, self.template_name, context)
def post(self, request):
return drilldown_search(request)
class ThresholdInfoModal(APIView):
parser_classes = [FormParser]
plan_name = "drilldown"
template_name = "modals/drilldown.html"
def post(self, request):
# if not request.user.has_plan(self.plan_name):
# return JsonResponse({"success": False})
if "net" not in request.data:
return JsonResponse({"success": False})
if "nick" not in request.data:
return JsonResponse({"success": False})
if "channel" not in request.data:
return JsonResponse({"success": False})
net = request.data["net"]
nick = request.data["nick"]
channel = request.data["channel"]
channels = get_chans(net, [nick])
users = get_users(net, [channel])
num_users = annotate_num_users(net, channels)
num_chans = annotate_num_chans(net, users)
if channels:
inter_users = get_users(net, channels)
else:
inter_users = []
if users:
inter_chans = get_chans(net, users)
else:
inter_chans = []
context = {
"net": net,
"nick": nick,
"channel": channel,
"chans": channels,
"users": users,
"inter_chans": inter_chans,
"inter_users": inter_users,
"num_users": num_users,
"num_chans": num_chans,
}
return render(request, self.template_name, context)