SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit d82a5a32 authored by George Katsikas's avatar George Katsikas :goat:
Browse files

add download button to graphs

parent db765e65
No related branches found
No related tags found
No related merge requests found
...@@ -3,14 +3,18 @@ ...@@ -3,14 +3,18 @@
{% block content %} {% block content %}
<h1>SciPost Graphs</h1> <h1>SciPost Graphs</h1>
<div id="plot-container" class="row" hx-include="this"> <div id="plot-container" class="row h-100" hx-include="this">
<div class="col-12 col-lg-3 d-flex flex-column" <div class="col-12 col-lg-3 d-flex flex-column"
hx-post="{% url "graphs:plot_options_form" %}" hx-post="{% url "graphs:plot_options_form" %}"
hx-trigger="load, change from:#plot-container"></div> hx-trigger="load, change from:#plot-container, click from:#plot-refresh">
<div id="plot" </div>
class="col d-flex flex-column align-items-center"
hx-get="{% url "graphs:plot" %}" <div class="col d-flex flex-column">
hx-params="not csrfmiddlewaretoken" <div id="plot"
hx-trigger="change from:#plot-container"></div> class="h-100 w-100"
hx-get="{% url "graphs:plot" %}"
hx-params="not csrfmiddlewaretoken"
hx-trigger="change from:#plot-container"></div>
</div>
</div> </div>
{% endblock content %} {% endblock content %}
{% if plot_svg %} {% if plot_svg %}{{ plot_svg|safe }}{% endif %}
{{ plot_svg|safe }}
{% endif %}
<div id="plot-controls" class="my-2 d-flex gap-2 justify-content-end">
<button id="plot-refresh" class="btn btn-primary">Refresh</button>
<button id="plot-download"
type="button"
class="btn btn-primary dropdown-toggle"
data-bs-toggle="dropdown"
aria-expanded="false">Download</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="{{ request.get_full_path }}&download=svg" >SVG</a></li>
<li><a class="dropdown-item" href="{{ request.get_full_path }}&download=pdf" >PDF</a></li>
<li><a class="dropdown-item" href="{{ request.get_full_path }}&download=png" >PNG</a></li>
<li><a class="dropdown-item" href="{{ request.get_full_path }}&download=jpg" >JPG</a></li>
<li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="{{ request.get_full_path }}&download=csv">CSV</a></li>
</ul>
</div>
...@@ -4,7 +4,7 @@ __license__ = "AGPL v3" ...@@ -4,7 +4,7 @@ __license__ = "AGPL v3"
import io import io
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import render from django.shortcuts import HttpResponse, render
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views import View from django.views import View
...@@ -42,7 +42,7 @@ class PlotView(View): ...@@ -42,7 +42,7 @@ class PlotView(View):
def get(self, request): def get(self, request):
form = PlotOptionsForm(request.GET) form = PlotOptionsForm(request.GET)
if not form.is_valid(): if not form.is_valid() and request.GET.get("widget"):
return HTMXResponse( return HTMXResponse(
"Invalid plot options: " + str(form.errors), tag="danger" "Invalid plot options: " + str(form.errors), tag="danger"
) )
...@@ -67,8 +67,55 @@ class PlotView(View): ...@@ -67,8 +67,55 @@ class PlotView(View):
else: else:
self.plot_options["generic"][option] = value self.plot_options["generic"][option] = value
if request.GET.get("download"):
return self.download(request.GET.get("download", "svg"))
return self.render_to_response(self.get_context_data()) return self.render_to_response(self.get_context_data())
def download(self, file_type):
figure = self.render_figure()
bytes_io = io.BytesIO()
match file_type:
case "svg":
figure.savefig(bytes_io, format="svg")
response = HttpResponse(
bytes_io.getvalue(), content_type="image/svg+xml"
)
case "png":
figure.savefig(bytes_io, format="png", dpi=300)
response = HttpResponse(bytes_io.getvalue(), content_type="image/png")
case "pdf":
figure.savefig(bytes_io, format="pdf")
response = HttpResponse(
bytes_io.getvalue(), content_type="application/pdf"
)
case "jpg":
figure.savefig(bytes_io, format="jpg", dpi=300)
response = HttpResponse(bytes_io.getvalue(), content_type="image/jpg")
case "csv":
x, y = self.kind.get_data()
# Write the data to a CSV file
csv = io.StringIO()
csv.write("x,y\n")
for i in range(len(x)):
csv.write(f"{x[i]},{y[i]}\n")
csv.seek(0)
response = HttpResponse(csv, content_type="text/csv")
case _:
raise ValueError(f"Invalid file type: {file_type}")
response["Content-Disposition"] = f"attachment; filename=plot.{file_type}"
return response
def render_figure(self): def render_figure(self):
if not self.plotter or not self.kind: if not self.plotter or not self.kind:
return None return None
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment