import urllib import uuid from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin 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 SingleTableView from mixins.views import ( ObjectCreate, ObjectDelete, ObjectList, ObjectRead, ObjectUpdate, ) from core import db from core.models import Drug from core.views.ui.tables import DrugsTable def make_table(context): object_list = [x.__dict__ for x in context["object_list"]] table = DrugsTable(object_list) context["table"] = table # del context["results"] return context 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(":")[:2] for x in spl]] return tags def parse_tags(tags_pre): """ Parse the tags from the variable tags_pre. """ tags = [] tags_spl = tags_pre.split(",") if tags_spl: for tag in tags_spl: tag = tag.split(": ") if len(tag) == 2: key, val = tag tags.append({key: val}) return tags class DrugsTableView(SingleTableView): table_class = DrugsTable template_name = "mixins/wm/widget.html" window_content = "window-content/results.html" # htmx_partial = "partials/" paginate_by = settings.DRUGS_RESULTS_PER_PAGE widget_options = 'gs-w="10" gs-h="1" gs-y="10" gs-x="1"' def common_request(self, request, **kwargs): extra_params = {} if request.user.is_anonymous: sizes = settings.MAIN_SIZES_ANON else: sizes = settings.MAIN_SIZES if request.GET: self.template_name = "index.html" # GET arguments in URL like ?query=xyz query_params = request.GET.dict() if request.htmx: if request.resolver_match.url_name == "search_partial": self.template_name = "partials/results_table.html" elif request.POST: query_params = request.POST.dict() else: self.template_name = "index.html" # No query, this is a fresh page load # Don't try to search, since there's clearly nothing to do params_with_defaults = {} db.add_defaults(params_with_defaults) context = { "sizes": sizes, "params": params_with_defaults, "unique": "results", "widget_options": self.widget_options, "window_content": self.window_content, "title": "Results", } return render(request, self.template_name, context) # Merge everything together just in case tmp_post = request.POST.dict() tmp_get = request.GET.dict() tmp_post = {k: v for k, v in tmp_post.items() if v and not v == "None"} tmp_get = {k: v for k, v in tmp_get.items() if v and not v == "None"} query_params.update(tmp_post) query_params.update(tmp_get) # URI we're passing to the template for linking if "csrfmiddlewaretoken" in query_params: del query_params["csrfmiddlewaretoken"] # 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, self.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"] # Remove null values if "query" in query_params: if query_params["query"] == "": del query_params["query"] # Remove null tags values # TODO: TAGS if "tags" in query_params: if query_params["tags"] == "": del query_params["tags"] else: # Parse the tags and populate cast to pass to search function tags = parse_tags(query_params["tags"]) extra_params["tags"] = tags context = db.orm.drug_query(request, query_params, **extra_params) print("CONTEXT", context) # Unique is for identifying the widgets. # We don't want a random one since we only want one results pane. context["unique"] = "results" context["window_content"] = self.window_content context["widget_options"] = self.widget_options context["title"] = "Results" # Valid sizes context["sizes"] = sizes # Add any default parameters to the context params_with_defaults = dict(query_params) db.add_defaults(params_with_defaults) context["params"] = params_with_defaults # Remove anything that we or the user set to a default for # pretty URLs db.remove_defaults(query_params) url_params = urllib.parse.urlencode(query_params) context["client_uri"] = url_params # There's an error if "message" in context: response = render(request, self.template_name, context) # Still push the URL so they can share it to get assistance if request.GET: if request.htmx: response["HX-Replace-Url"] = reverse("home") + "?" + url_params elif request.POST: response["HX-Replace-Url"] = reverse("home") + "?" + url_params return response # Create data for chart.js sentiment graph # graph = make_graph(context["object_list"]) # context["data"] = graph # Create the table context = make_table(context) print("CONTEXT", context) # URI we're passing to the template for linking, table fields removed table_fields = ["page", "sort"] clean_params = {k: v for k, v in query_params.items() if k not in table_fields} clean_url_params = urllib.parse.urlencode(clean_params) context["uri"] = clean_url_params # unique = str(uuid.uuid4())[:8] # self.context = context return context def get(self, request, *args, **kwargs): print("GET") self.context = self.common_request(request) if isinstance(self.context, HttpResponse): return self.context self.object_list = self.context["object_list"] show = [] show = set().union( *([x.name for x in d._meta.get_fields()] for d in self.object_list) ) allow_empty = self.get_allow_empty() if not allow_empty: # When pagination is enabled and object_list is a queryset, # it's better to do a cheap query than to load the unpaginated # queryset in memory. if self.get_paginate_by(self.object_list) is not None and hasattr( self.object_list, "exists" ): is_empty = not self.object_list.exists() # noqa else: is_empty = not self.object_list # noqa context = self.get_context_data() for k, v in self.context.items(): if k not in context: context[k] = v context["show"] = show # if request.htmx: # self.template_name = self.window_content # if request.method == "GET": # if not request.htmx: # self.template_name = "ui/drilldown/drilldown.html" response = self.render_to_response(context) # if not request.method == "GET": if "client_uri" in context: response["HX-Replace-Url"] = reverse("home") + "?" + context["client_uri"] return response def post(self, request, *args, **kwargs): return self.get(request, *args, **kwargs)