2018-05-01 02:17:18 +00:00
|
|
|
|
import json
|
|
|
|
|
|
2018-04-02 13:02:49 +00:00
|
|
|
|
from django.conf import settings
|
2019-03-04 20:03:43 +00:00
|
|
|
|
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
2018-04-16 04:27:13 +00:00
|
|
|
|
from django.core.mail import send_mail
|
|
|
|
|
from django.db.models import Q
|
|
|
|
|
from django.http import Http404, HttpResponse
|
|
|
|
|
from django.urls import reverse
|
2019-03-04 19:48:29 +00:00
|
|
|
|
from django.urls import reverse_lazy
|
2019-03-04 20:37:39 +00:00
|
|
|
|
from django.utils.translation import get_language
|
2018-04-14 02:40:42 +00:00
|
|
|
|
from django.views import View
|
2017-10-08 20:21:51 +00:00
|
|
|
|
from django.views.generic import DetailView
|
|
|
|
|
from django.views.generic.base import TemplateView
|
2019-03-04 19:48:29 +00:00
|
|
|
|
from django.views.generic.edit import CreateView, UpdateView
|
2018-04-16 04:27:13 +00:00
|
|
|
|
|
|
|
|
|
from dal import autocomplete
|
|
|
|
|
|
2018-05-01 02:17:18 +00:00
|
|
|
|
from apps.files.models import File
|
|
|
|
|
|
2018-10-13 05:04:44 +00:00
|
|
|
|
from .models import CaseStudy, CaseStudyDraft, SpatialRefSys, PointOfInterest
|
|
|
|
|
from .forms import ShortCaseStudyForm, LongCaseStudyForm, PointOfInterest
|
2017-05-20 23:47:14 +00:00
|
|
|
|
|
2018-04-14 02:40:42 +00:00
|
|
|
|
|
2018-04-02 13:02:49 +00:00
|
|
|
|
NOTIFY_MESSAGE = """
|
|
|
|
|
Hello,
|
|
|
|
|
|
|
|
|
|
Someone has submitted a new case study to the Ojuso website. Please
|
|
|
|
|
follow the below link to look over and approve it:
|
|
|
|
|
|
|
|
|
|
%s%s
|
|
|
|
|
|
|
|
|
|
– Case Study Robot
|
|
|
|
|
|
|
|
|
|
"""
|
2017-06-16 16:06:22 +00:00
|
|
|
|
|
2019-08-19 21:37:32 +00:00
|
|
|
|
|
2017-10-08 20:21:51 +00:00
|
|
|
|
class Map(TemplateView):
|
|
|
|
|
template_name = "map/index.html"
|
2017-05-20 23:47:14 +00:00
|
|
|
|
|
2017-06-16 16:06:22 +00:00
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class CreateCaseStudySelector(LoginRequiredMixin, TemplateView):
|
2018-10-12 22:50:51 +00:00
|
|
|
|
template_name = "map/form-selector.html"
|
2017-06-16 16:06:22 +00:00
|
|
|
|
|
2017-10-08 20:21:51 +00:00
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class CreatePointOfInterest(LoginRequiredMixin, CreateView):
|
2018-10-13 05:04:44 +00:00
|
|
|
|
"""View for base case study form."""
|
2019-08-19 21:37:32 +00:00
|
|
|
|
|
|
|
|
|
template_name = "map/form-poi.html"
|
|
|
|
|
success_url = "/case-study/create/success/"
|
2018-10-13 05:04:44 +00:00
|
|
|
|
model = PointOfInterest
|
|
|
|
|
form_class = PointOfInterest
|
|
|
|
|
|
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
def send_email(study_id):
|
|
|
|
|
"""Sends email to moderator to approve case study."""
|
2018-04-02 13:02:49 +00:00
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
try:
|
2018-04-02 13:02:49 +00:00
|
|
|
|
send_mail(
|
2019-08-19 21:37:32 +00:00
|
|
|
|
"New case study submitted",
|
|
|
|
|
NOTIFY_MESSAGE
|
|
|
|
|
% (
|
2018-04-02 13:02:49 +00:00
|
|
|
|
settings.SITE_URL,
|
2019-08-19 21:37:32 +00:00
|
|
|
|
reverse("admin:map_casestudy_change", args=[study_id]),
|
2018-04-02 13:02:49 +00:00
|
|
|
|
),
|
2019-08-19 21:37:32 +00:00
|
|
|
|
"noreply@ojuso.org",
|
2018-04-04 17:36:27 +00:00
|
|
|
|
[settings.DATABASE_EMAIL],
|
2018-04-02 13:02:49 +00:00
|
|
|
|
fail_silently=False,
|
|
|
|
|
)
|
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
except:
|
|
|
|
|
# XXX This is bad. We should do something more useful with the error
|
|
|
|
|
# than this.
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def delete_user_draft(user_id):
|
|
|
|
|
""" Delete the draft of a given user """
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
draft = CaseStudyDraft.objects.get(author=user_id)
|
|
|
|
|
draft.delete()
|
|
|
|
|
except CaseStudyDraft.DoesNotExist:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FilesHandlerMixin:
|
|
|
|
|
def remove_bad_fields(self, form):
|
2019-08-19 21:37:32 +00:00
|
|
|
|
form.cleaned_data.pop("official_project_documents", None)
|
|
|
|
|
form.cleaned_data.pop("other_documents", None)
|
|
|
|
|
form.cleaned_data.pop("shapefiles", None)
|
|
|
|
|
form.cleaned_data.pop("images", None)
|
2018-04-23 05:15:33 +00:00
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
def add_file_refs(self, form):
|
2019-08-19 21:37:32 +00:00
|
|
|
|
self.object.official_project_documents.set(
|
|
|
|
|
form.cleaned_data.get("official_project_documents_files", [])
|
|
|
|
|
)
|
|
|
|
|
self.object.other_documents.set(
|
|
|
|
|
form.cleaned_data.get("other_documents_files", [])
|
|
|
|
|
)
|
|
|
|
|
self.object.shapefiles.set(form.cleaned_data.get("shapefiles_files", []))
|
|
|
|
|
self.object.images.set(form.cleaned_data.get("images_files", []))
|
2018-04-23 05:15:33 +00:00
|
|
|
|
|
2019-03-04 20:37:39 +00:00
|
|
|
|
def handle_files(self, form):
|
2019-03-04 19:48:29 +00:00
|
|
|
|
self.remove_bad_fields(form)
|
|
|
|
|
self.object = form.save()
|
|
|
|
|
self.add_file_refs(form)
|
2018-05-30 03:16:22 +00:00
|
|
|
|
self.object.save()
|
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
|
|
|
|
|
class BaseCreateForm(LoginRequiredMixin, FilesHandlerMixin, CreateView):
|
|
|
|
|
"""View for base case study form."""
|
2019-08-19 21:37:32 +00:00
|
|
|
|
|
|
|
|
|
template_name = "map/form-case_study.html"
|
|
|
|
|
success_url = reverse_lazy("form-success")
|
2019-03-04 19:48:29 +00:00
|
|
|
|
model = CaseStudy
|
2018-04-16 00:57:05 +00:00
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
def form_valid(self, form):
|
2019-03-04 20:37:39 +00:00
|
|
|
|
self.handle_files(form)
|
|
|
|
|
|
|
|
|
|
self.object.author = self.request.user
|
|
|
|
|
self.object.language = get_language()
|
2019-03-04 20:41:15 +00:00
|
|
|
|
self.object.form_type = self.form_type
|
2019-03-04 20:37:39 +00:00
|
|
|
|
self.object.save()
|
2018-04-16 00:57:05 +00:00
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
send_email(self.object.id)
|
|
|
|
|
delete_user_draft(self.request.user)
|
2018-04-02 13:02:49 +00:00
|
|
|
|
|
2019-03-04 20:37:39 +00:00
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
2017-10-08 20:21:51 +00:00
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class CreateShortCaseStudy(BaseCreateForm):
|
2017-10-09 23:58:36 +00:00
|
|
|
|
"""View for short version of case study form."""
|
2019-08-19 21:37:32 +00:00
|
|
|
|
|
2017-10-08 20:21:51 +00:00
|
|
|
|
form_class = ShortCaseStudyForm
|
2019-03-04 20:41:15 +00:00
|
|
|
|
form_type = "short"
|
2017-10-08 20:21:51 +00:00
|
|
|
|
|
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class CreateLongCaseStudy(BaseCreateForm):
|
2017-10-09 23:58:36 +00:00
|
|
|
|
"""View for long version of case study form."""
|
2019-08-19 21:37:32 +00:00
|
|
|
|
|
2017-10-08 20:21:51 +00:00
|
|
|
|
form_class = LongCaseStudyForm
|
2019-03-04 20:41:15 +00:00
|
|
|
|
form_type = "long"
|
2017-10-08 20:21:51 +00:00
|
|
|
|
|
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class CreateCaseStudySuccess(TemplateView):
|
2019-08-19 21:37:32 +00:00
|
|
|
|
template_name = "map/form-success.html"
|
2017-10-09 23:58:36 +00:00
|
|
|
|
|
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class ViewCaseStudyDetail(DetailView):
|
2017-10-08 20:21:51 +00:00
|
|
|
|
template_name = "map/detail.html"
|
|
|
|
|
model = CaseStudy
|
|
|
|
|
context_object_name = "case_study"
|
2018-04-14 02:40:42 +00:00
|
|
|
|
|
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
class BaseEditForm(LoginRequiredMixin, FilesHandlerMixin, UpdateView):
|
|
|
|
|
"""View for base case study form."""
|
2019-08-19 21:37:32 +00:00
|
|
|
|
|
|
|
|
|
template_name = "map/form-case_study.html"
|
|
|
|
|
success_url = reverse_lazy("form-success")
|
2019-03-04 19:48:29 +00:00
|
|
|
|
model = CaseStudy
|
|
|
|
|
|
2019-03-04 20:37:39 +00:00
|
|
|
|
def form_valid(self, form):
|
|
|
|
|
self.handle_files(form)
|
|
|
|
|
|
|
|
|
|
return super().form_valid(form)
|
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
|
2019-03-04 20:03:43 +00:00
|
|
|
|
class EditCaseStudy(UserPassesTestMixin, BaseEditForm):
|
2019-03-04 19:48:29 +00:00
|
|
|
|
form_class = ShortCaseStudyForm
|
|
|
|
|
|
2019-03-04 20:03:43 +00:00
|
|
|
|
def test_func(self):
|
2019-03-07 09:15:18 +00:00
|
|
|
|
if settings.FFCAN_EDIT is False:
|
|
|
|
|
return False
|
|
|
|
|
|
2019-03-04 20:03:43 +00:00
|
|
|
|
object = self.get_object()
|
|
|
|
|
if object.author:
|
|
|
|
|
author = object.author.id
|
|
|
|
|
else:
|
|
|
|
|
author = -1
|
|
|
|
|
|
2019-08-19 21:37:32 +00:00
|
|
|
|
return self.request.user.is_authenticated and (author is self.request.user.id)
|
2019-03-04 20:03:43 +00:00
|
|
|
|
|
2019-03-04 19:48:29 +00:00
|
|
|
|
|
2018-04-16 04:27:13 +00:00
|
|
|
|
class SpatialRefSysAutocomplete(autocomplete.Select2QuerySetView):
|
|
|
|
|
def get_queryset(self):
|
|
|
|
|
qs = SpatialRefSys.objects.all()
|
|
|
|
|
|
|
|
|
|
if self.q:
|
|
|
|
|
qs = qs.filter(
|
2019-08-19 21:37:32 +00:00
|
|
|
|
Q(auth_name__icontains=self.q) | Q(auth_srid__icontains=self.q)
|
2018-04-16 04:27:13 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return qs
|
|
|
|
|
|
|
|
|
|
|
2019-03-04 19:57:47 +00:00
|
|
|
|
class DraftsAPI(LoginRequiredMixin, View):
|
2019-04-07 16:47:03 +00:00
|
|
|
|
"""
|
|
|
|
|
Retrieve or save a draft.
|
|
|
|
|
|
|
|
|
|
XXX This should be refactored to use csrf protection.
|
|
|
|
|
"""
|
2018-04-14 02:40:42 +00:00
|
|
|
|
|
|
|
|
|
def get_object(self, request):
|
|
|
|
|
try:
|
|
|
|
|
return CaseStudyDraft.objects.get(author=request.user)
|
|
|
|
|
except:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def get(self, request):
|
|
|
|
|
draft = self.get_object(request)
|
2018-10-01 19:19:21 +00:00
|
|
|
|
|
2018-04-14 02:40:42 +00:00
|
|
|
|
if draft == None:
|
2019-08-19 21:37:32 +00:00
|
|
|
|
return HttpResponse(status=404) # Not Found
|
2018-04-14 02:40:42 +00:00
|
|
|
|
else:
|
|
|
|
|
return HttpResponse(draft.data, content_type="application/json")
|
|
|
|
|
|
|
|
|
|
def put(self, request):
|
|
|
|
|
# Find an existing object is there is one
|
|
|
|
|
draft = self.get_object(request)
|
2018-10-01 19:19:21 +00:00
|
|
|
|
|
2018-04-14 02:40:42 +00:00
|
|
|
|
if draft == None:
|
|
|
|
|
# If there isn't, create a new draft...
|
2018-10-01 19:19:21 +00:00
|
|
|
|
draft = CaseStudyDraft(author=request.user, data=request.body.decode())
|
2018-04-14 02:40:42 +00:00
|
|
|
|
draft.save()
|
2019-08-19 21:37:32 +00:00
|
|
|
|
return HttpResponse(status=201) # Created
|
2018-04-14 02:40:42 +00:00
|
|
|
|
else:
|
2018-10-01 19:19:21 +00:00
|
|
|
|
draft.data = request.body.decode()
|
2018-04-14 02:40:42 +00:00
|
|
|
|
draft.save()
|
2019-08-19 21:37:32 +00:00
|
|
|
|
return HttpResponse(status=200) # OK
|
2018-04-14 02:40:42 +00:00
|
|
|
|
|
|
|
|
|
def delete(self, request):
|
|
|
|
|
draft = self.get_object(request)
|
2018-04-23 05:15:33 +00:00
|
|
|
|
|
2018-04-14 02:40:42 +00:00
|
|
|
|
if draft != None:
|
2018-05-01 02:17:18 +00:00
|
|
|
|
data = json.loads(draft.data)
|
|
|
|
|
|
2019-08-19 21:37:32 +00:00
|
|
|
|
for k in [
|
|
|
|
|
"official_project_documents",
|
|
|
|
|
"other_documents",
|
|
|
|
|
"shapefiles",
|
|
|
|
|
"images",
|
|
|
|
|
]:
|
2018-05-01 02:17:18 +00:00
|
|
|
|
|
2018-05-01 05:08:40 +00:00
|
|
|
|
try:
|
2019-08-19 21:37:32 +00:00
|
|
|
|
keyname = k + "_files"
|
|
|
|
|
field = data["data"]["form"][keyname]
|
2018-06-27 18:50:24 +00:00
|
|
|
|
|
2018-10-12 22:30:47 +00:00
|
|
|
|
# Ignore empty fields
|
2019-08-19 21:37:32 +00:00
|
|
|
|
if field["value"] == "":
|
2018-10-12 22:30:47 +00:00
|
|
|
|
continue
|
2018-05-01 02:17:18 +00:00
|
|
|
|
|
2019-08-19 21:37:32 +00:00
|
|
|
|
file_list = json.loads(field["value"])
|
2018-10-12 22:30:47 +00:00
|
|
|
|
|
|
|
|
|
# Delete those items
|
|
|
|
|
for item in file_list:
|
|
|
|
|
try:
|
2019-08-19 21:37:32 +00:00
|
|
|
|
f = File.objects.get(id=item["id"])
|
2018-10-12 22:30:47 +00:00
|
|
|
|
if f.user != self.request.user:
|
|
|
|
|
continue
|
|
|
|
|
f.delete()
|
|
|
|
|
except File.DoesNotExist:
|
2018-05-01 02:17:18 +00:00
|
|
|
|
continue
|
2018-10-12 22:30:47 +00:00
|
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
continue
|
|
|
|
|
|
2018-04-14 02:40:42 +00:00
|
|
|
|
draft.delete()
|
2018-04-23 05:15:33 +00:00
|
|
|
|
|
2018-04-14 02:40:42 +00:00
|
|
|
|
return HttpResponse(status=204)
|