diff --git a/src/crowdprinter/templates/base.html b/src/crowdprinter/templates/base.html index 06643ac..249dde1 100644 --- a/src/crowdprinter/templates/base.html +++ b/src/crowdprinter/templates/base.html @@ -1,5 +1,12 @@ {% include "crowdprinter/head.html" %}
+ {% if messages %} + + {% endif %} {% block content %}{% endblock %}
diff --git a/src/crowdprinter/templates/crowdprinter/printjob_create_text.html b/src/crowdprinter/templates/crowdprinter/printjob_create_text.html new file mode 100644 index 0000000..220954c --- /dev/null +++ b/src/crowdprinter/templates/crowdprinter/printjob_create_text.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} + +{% block content %} +
+

Add Print Job

+
+ {% csrf_token %} + {{ form.as_p }} +
+{% endblock %} diff --git a/src/crowdprinter/urls.py b/src/crowdprinter/urls.py index 534b363..2bbbc83 100644 --- a/src/crowdprinter/urls.py +++ b/src/crowdprinter/urls.py @@ -25,6 +25,9 @@ path("accounts/", include("allauth.urls")), path("", views.PrintJobListView.as_view()), path("myprints", views.MyPrintAttempts.as_view(), name="my_printattempts"), + path( + "create/text", views.PrintJobCreateView.as_view(), name="printjob_create_text" + ), path( "printjob//", include( diff --git a/src/crowdprinter/views.py b/src/crowdprinter/views.py index 6952441..085ffeb 100644 --- a/src/crowdprinter/views.py +++ b/src/crowdprinter/views.py @@ -2,21 +2,38 @@ import math import os.path import random +import tempfile +from django import forms from django.conf import settings from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.mixins import UserPassesTestMixin +from django.contrib.messages.views import SuccessMessageMixin +from django.core.files.base import ContentFile +from django.db import transaction from django.http import FileResponse from django.http import Http404 from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.urls import reverse +from django.urls import reverse_lazy from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_control +from django.views.generic import CreateView from django.views.generic import DetailView from django.views.generic import ListView from django.views.generic.base import View import crowdprinter.models as models +import stl_generator + +from .models import PrintJob + + +class SuperUserRequiredMixin(LoginRequiredMixin, UserPassesTestMixin): + def test_func(self): + return self.request.user.is_superuser class PrintJobListView(ListView): @@ -44,6 +61,63 @@ def get_queryset(self): return super().get_queryset().filter(can_attempt=True).order_by("?") +class PrintJobForm(forms.ModelForm): + text = forms.CharField( + required=True, + widget=forms.Textarea(attrs={"rows": 4, "cols": 40}), + ) + + class Meta: + model = PrintJob + fields = [ + "slug", + "count_needed", + "text", + ] + + @transaction.atomic + def save(self, commit=True): + job = super().save(commit=False) + slug = self.cleaned_data.get("slug") + + with ( + tempfile.NamedTemporaryFile(suffix=".stl", delete=False) as f_stl, + tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f_png, + tempfile.NamedTemporaryFile(suffix=".gcode", delete=False) as f_gcode, + ): + stl_generator.text_to_stl(self.cleaned_data.get("text"), f_stl) + f_stl.seek(0) + job.file_stl = ContentFile(f_stl.read(), name=f"{slug}.stl") + + stl_generator.stl_to_png(f_stl.name, f_png) + f_png.seek(0) + job.file_render = ContentFile(f_png.read(), name=f"{slug}.png") + + job.save() + + for printer in [ + models.Printer.objects.first() + ]: # TODO: support multiple printers w/ presets + stl_generator.stl_to_gcode(f_stl.name, f_gcode) + f_gcode.seek(0) + models.PrintJobFile.objects.create( + job=job, + printer=printer, + file_gcode=ContentFile(f_gcode.read(), name=f"{slug}.gcode"), + ) + + return job + + +class PrintJobCreateView(SuperUserRequiredMixin, SuccessMessageMixin, CreateView): + template_name = "crowdprinter/printjob_create_text.html" + model = PrintJob + form_class = PrintJobForm + template_name = "crowdprinter/printjob_create_text.html" + success_url = reverse_lazy("printjob_create_text") + success_message = "Job %(slug)s was created successfully" + + class MyPrintAttempts(ListView): model = models.PrintAttempt template_name = "crowdprinter/myprintattempts.html" diff --git a/pipeline/process.py b/src/stl_generator/__init__.py similarity index 72% rename from pipeline/process.py rename to src/stl_generator/__init__.py index c12a41e..d5cb3eb 100755 --- a/pipeline/process.py +++ b/src/stl_generator/__init__.py @@ -4,9 +4,11 @@ import subprocess import tempfile +BASE_DIR = pathlib.Path(__file__).parent + def text_to_stl(text, f_stl): - path_lib = pathlib.Path("generate_braille_lib.scad").absolute() + path_lib = BASE_DIR / "generate_braille_lib.scad" with tempfile.NamedTemporaryFile("w", suffix=".scad", delete=False) as f_scad: f_scad.write(f'BrailleText1="{text.lower()}";') f_scad.write(f'ProfilText1="{text}";') @@ -42,7 +44,7 @@ def stl_to_png(path_stl, f_png): def stl_to_gcode(path_stl, f_gcode): - path_pp_script = pathlib.Path("insert_m600.py").absolute() + path_pp_script = BASE_DIR / "insert_m600.py" subprocess.check_call( [ "prusa-slicer", @@ -54,15 +56,3 @@ def stl_to_gcode(path_stl, f_gcode): f_gcode.name, ] ) - - -with ( - tempfile.NamedTemporaryFile(suffix=".stl", delete=False) as f_stl, - tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f_png, - tempfile.NamedTemporaryFile(suffix=".gcode", delete=False) as f_gcode, -): - text_to_stl("Hello World", f_stl) - stl_to_png(f_stl.name, f_png) - stl_to_gcode(f_stl.name, f_gcode) - print(f_png.name) - print(f_gcode.name) diff --git a/pipeline/generate_braille_lib.scad b/src/stl_generator/generate_braille_lib.scad similarity index 100% rename from pipeline/generate_braille_lib.scad rename to src/stl_generator/generate_braille_lib.scad diff --git a/pipeline/insert_m600.py b/src/stl_generator/insert_m600.py similarity index 100% rename from pipeline/insert_m600.py rename to src/stl_generator/insert_m600.py