Skip to content

Commit

Permalink
add CRUD views
Browse files Browse the repository at this point in the history
  • Loading branch information
jeriox committed Sep 23, 2024
1 parent f1ee9bd commit d75dd01
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 7 deletions.
39 changes: 39 additions & 0 deletions ephios/plugins/files/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from django.forms import FileInput, Form, ModelForm, ModelMultipleChoiceField
from django.utils.translation import gettext as _
from django_select2.forms import Select2MultipleWidget

from ephios.core.forms.events import BasePluginFormMixin
from ephios.plugins.files.models import Document


class DocumentForm(ModelForm):
class Meta:
model = Document
fields = ["title", "file"]
widgets = {"file": FileInput(attrs={"accept": ".pdf"})}


class EventAttachedDocumentForm(BasePluginFormMixin, Form):
documents = ModelMultipleChoiceField(
queryset=Document.objects.all(), required=False, widget=Select2MultipleWidget
)

def __init__(self, *args, **kwargs):
kwargs.setdefault("prefix", "files")
self.event = kwargs.pop("event")
self.request = kwargs.pop("request")
super().__init__(*args, **kwargs)
self.fields["documents"].initial = (
self.event.documents.all() if self.event and self.event.pk else []
)

def save(self):
if self.cleaned_data["documents"]:
self.event.documents.set(self.cleaned_data["documents"])

@property
def heading(self):
return _("Attach files")

def is_function_active(self):
return self.event and self.event.documents.exists()
16 changes: 13 additions & 3 deletions ephios/plugins/files/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Generated by Django 5.0.8 on 2024-09-21 12:01
# Generated by Django 5.0.8 on 2024-09-23 19:05

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = []
dependencies = [
("core", "0029_alter_userprofile_date_of_birth"),
]

operations = [
migrations.CreateModel(
Expand All @@ -20,7 +23,14 @@ class Migration(migrations.Migration):
),
),
("title", models.CharField(max_length=255)),
("file", models.FileField(upload_to="documents/")),
(
"file",
models.FileField(
upload_to="documents/",
validators=[django.core.validators.FileExtensionValidator(["pdf"])],
),
),
("attached_to", models.ManyToManyField(related_name="documents", to="core.event")),
],
),
]
8 changes: 6 additions & 2 deletions ephios/plugins/files/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from django.core.validators import FileExtensionValidator
from django.db import models

from ephios.core.models import Event


class Document(models.Model):
title = models.CharField(max_length=255)
file = models.FileField(upload_to="documents/")
file = models.FileField(upload_to="documents/", validators=[FileExtensionValidator(["pdf"])])
attached_to = models.ManyToManyField(Event, related_name="documents")

def __str__(self):
return self.title
return str(self.title)
41 changes: 41 additions & 0 deletions ephios/plugins/files/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from django.dispatch import receiver
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.translation import gettext as _

from ephios.core.signals import event_forms, event_info, management_settings_sections
from ephios.plugins.files.forms import EventAttachedDocumentForm


@receiver(
management_settings_sections,
dispatch_uid="ephios.plugins.pages.signals.files_settings_section",
)
def files_settings_section(sender, request, **kwargs):
return (
[
{
"label": _("Files"),
"url": reverse("files:settings_document_list"),
"active": request.resolver_match.url_name.startswith("settings_document"),
},
]
if request.user.has_perm("files.add_document")
else []
)


@receiver(
event_forms,
dispatch_uid="ephios.plugins.files.signals.files_event_forms",
)
def guests_event_forms(sender, event, request, **kwargs):
return [EventAttachedDocumentForm(request.POST or None, event=event, request=request)]


@receiver(event_info, dispatch_uid="ephios.plugins.files.signals.event_info")
def display_event_files(event, request, **kwargs):
if event.documents.exists():
return render_to_string(
"files/document_attachement.html", {"documents": event.documents.all()}, request
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div id="attached-documents" class="mb-3">
{% for document in documents %}
<a href="{% url "files:document" document.pk %}"><span class="badge bg-light text-dark"><i class="fas fa-file"></i> {{ document.title }}</span></a>
{% endfor %}
</div>
22 changes: 22 additions & 0 deletions ephios/plugins/files/templates/files/document_confirm_delete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "core/settings/settings_base.html" %}
{% load i18n %}
{% load static %}

{% block title %}
{% translate "Delete file" %}
{% endblock %}

{% block settings_content %}
<div class="page-header">
<h2>{% translate "Delete file" %}</h2>
</div>

<form method="post">{% csrf_token %}
<p>{% blocktranslate trimmed with title=document.title %}
Are you sure you want to delete the file "{{ title }}"?
{% endblocktranslate %}</p>
<a role="button" class="btn btn-secondary" href="{% url "files:settings_document_list" %}">{% translate "Back" %}</a>
<button type="submit" class="btn btn-danger">{% translate "Delete" %}</button>
</form>

{% endblock %}
19 changes: 19 additions & 0 deletions ephios/plugins/files/templates/files/document_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% extends "core/settings/settings_base.html" %}
{% load crispy_forms_filters %}
{% load i18n %}

{% block settings_content %}
<div class="page-header">
{% if page %}
<h2>{% translate "Edit file" %}</h2>
{% else %}
<h2>{% translate "Upload new file" %}</h2>
{% endif %}
</div>

<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" class="btn btn-primary" value="Save">
</form>
{% endblock %}
33 changes: 33 additions & 0 deletions ephios/plugins/files/templates/files/document_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{% extends "core/settings/settings_base.html" %}
{% load i18n %}

{% block settings_content %}
<a class="btn btn-secondary" href="{% url "files:settings_document_create" %}"><span
class="fa fa-plus"></span> {% translate "Add file" %}</a>
<table class="table table-striped display mt-2">
<thead>
<tr>
<th>{% translate "Title" %}</th>
<th>{% translate "Action" %}</th>
</tr>
</thead>
<tbody>
{% for document in document_list %}
<tr>
<td class="break-word">{{ document.title }}</td>
<td class="d-flex">
<a class="btn btn-secondary btn-sm text-nowrap me-1"
href="{% url "files:document" document.pk %}"><span
class="fa fa-download"></span> <span class="d-none d-md-inline">{% translate "Download" %}</span></a>
<a class="btn btn-secondary btn-sm text-nowrap me-1"
href="{% url "files:settings_document_edit" document.pk %}"><span
class="fa fa-edit"></span> <span class="d-none d-md-inline">{% translate "Edit" %}</span></a>
<a class="btn btn-secondary btn-sm text-nowrap me-1"
href="{% url "files:settings_document_delete" document.pk %}"><span
class="fa fa-trash"></span> <span class="d-none d-md-inline">{% translate "Delete" %}</span></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
24 changes: 22 additions & 2 deletions ephios/plugins/files/urls.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
from django.urls import path

from ephios.plugins.files.views import DocumentView
from ephios.plugins.files.views import (
DocumentCreateView,
DocumentDeleteView,
DocumentListView,
DocumentUpdateView,
DocumentView,
)

app_name = "files"
urlpatterns = [
path("documents/<int:pk>/", DocumentView.as_view(), name="document"),
path("document/<int:pk>/", DocumentView.as_view(), name="document"),
path("settings/documents/", DocumentListView.as_view(), name="settings_document_list"),
path(
"settings/documents/create/", DocumentCreateView.as_view(), name="settings_document_create"
),
path(
"settings/documents/<int:pk>/edit/",
DocumentUpdateView.as_view(),
name="settings_document_edit",
),
path(
"settings/documents/<int:pk>/delete/",
DocumentDeleteView.as_view(),
name="settings_document_delete",
),
]
34 changes: 34 additions & 0 deletions ephios/plugins/files/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
from urllib.parse import urlsplit

from django.conf import settings
from django.contrib.messages.views import SuccessMessageMixin
from django.http import FileResponse, HttpResponse
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.views import View
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from guardian.mixins import LoginRequiredMixin

from ephios.extra.mixins import CustomPermissionRequiredMixin
from ephios.plugins.files.forms import DocumentForm
from ephios.plugins.files.models import Document


Expand All @@ -24,3 +30,31 @@ def get(self, request, *args, **kwargs):
"attachment; filename=" + os.path.split(document.file.name)[1]
)
return response


class DocumentListView(CustomPermissionRequiredMixin, ListView):
model = Document
permission_required = "files.add_document"


class DocumentCreateView(CustomPermissionRequiredMixin, SuccessMessageMixin, CreateView):
model = Document
permission_required = "files.add_document"
form_class = DocumentForm
success_url = reverse_lazy("files:settings_document_list")
success_message = _("File saved successfully.")


class DocumentUpdateView(CustomPermissionRequiredMixin, SuccessMessageMixin, UpdateView):
model = Document
permission_required = "files.change_document"
form_class = DocumentForm
success_url = reverse_lazy("files:settings_document_list")
success_message = _("File saved successfully.")


class DocumentDeleteView(CustomPermissionRequiredMixin, SuccessMessageMixin, DeleteView):
model = Document
permission_required = "files.delete_document"
success_url = reverse_lazy("files:settings_document_list")
success_message = _("File deleted successfully.")

0 comments on commit d75dd01

Please sign in to comment.