Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Elementary report template management.
WIP File uploads not handled properly yet.
- Loading branch information
Showing
20 changed files
with
739 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from django.contrib import admin | ||
|
||
# from .models import HgmdPublicLocus | ||
|
||
# Register your models here. | ||
# admin.site.register(HgmdPublicLocus) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class ReportsConfig(AppConfig): | ||
name = "reports" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import hashlib | ||
|
||
from django import forms | ||
from django.core.exceptions import ValidationError | ||
from django.core.validators import RegexValidator | ||
|
||
from .models import ReportTemplate | ||
|
||
|
||
class ReportTemplateForm(forms.ModelForm): | ||
class Meta: | ||
model = ReportTemplate | ||
fields = ("title", "filename") | ||
|
||
title = forms.CharField( | ||
label="Template Title", help_text="Leave empty to use file name", required=False | ||
) | ||
|
||
payload = forms.FileField( | ||
label="Template File", help_text="Upload a .docx file to use for the template." | ||
) | ||
|
||
filename = forms.CharField( | ||
required=False, | ||
help_text="Specify the file name to override the file name of the uploaded file", | ||
validators=[ | ||
RegexValidator(r"(^$)|(\.docx$)", message="File name must be blank or end in .docx"), | ||
RegexValidator( | ||
r"^[a-zA-Z0-9\._-]*$", | ||
message="File name must only consist of alphanumeric characters, spaces, dots, hyphens, and underscores", | ||
), | ||
], | ||
) | ||
|
||
def __init__(self, project, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
self.project = project | ||
if self.instance.pk: | ||
self.fields["payload"].required = False | ||
|
||
def clean(self): | ||
cleaned_data = self.cleaned_data | ||
if "payload" in cleaned_data and cleaned_data["payload"]: | ||
import pdb | ||
|
||
pdb.set_trace() | ||
cleaned_data["title"] = cleaned_data["title"] or cleaned_data["payload"].name | ||
cleaned_data["filename"] = cleaned_data["filename"] or cleaned_data["payload"].name | ||
ctx = hashlib.sha256() | ||
if cleaned_data["payload"].multiple_chunks(): | ||
for data in cleaned_data["payload"].chunks(): | ||
ctx.update(data) | ||
else: | ||
ctx.update(cleaned_data["payload"].read()) | ||
cleaned_data["filehash"] = "sha256:%s" % ctx.hexdigest() | ||
cleaned_data["filesize"] = cleaned_data["payload"].size | ||
|
||
if not cleaned_data["filename"].endswith(".docx"): | ||
raise ValidationError("The file name must end in .docx") | ||
|
||
qs = ReportTemplate.objects.filter(project=self.project, filename=cleaned_data["filename"]) | ||
if self.instance.pk: | ||
qs = qs.exclude(pk=self.instance.pk) | ||
if qs: | ||
raise ValidationError( | ||
"There already exists a report template with file name %s in this project!" | ||
% cleaned_data["filename"] | ||
) | ||
|
||
return cleaned_data | ||
|
||
def save(self, commit=True): | ||
super().save(commit=False) | ||
if "filehash" in self.cleaned_data: | ||
self.instance.filehash = self.cleaned_data["filehash"] | ||
if "filesize" in self.cleaned_data: | ||
self.instance.filesize = self.cleaned_data["filesize"] | ||
self.instance.project = self.project | ||
self.instance.save() | ||
return self.instance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# -*- coding: utf-8 -*- | ||
# Generated by Django 1.11.29 on 2021-04-07 15:27 | ||
from __future__ import unicode_literals | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import uuid | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [ | ||
("projectroles", "0017_project_full_title"), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="ReportTemplate", | ||
fields=[ | ||
( | ||
"id", | ||
models.AutoField( | ||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||
), | ||
), | ||
( | ||
"date_created", | ||
models.DateTimeField(auto_now_add=True, help_text="DateTime of creation"), | ||
), | ||
( | ||
"date_modified", | ||
models.DateTimeField(auto_now=True, help_text="DateTime of last modification"), | ||
), | ||
("title", models.CharField(max_length=512)), | ||
("filename", models.CharField(max_length=512)), | ||
("filesize", models.IntegerField(default=0)), | ||
("filehash", models.CharField(max_length=128)), | ||
( | ||
"sodar_uuid", | ||
models.UUIDField(default=uuid.uuid4, help_text="Case SODAR UUID", unique=True), | ||
), | ||
( | ||
"project", | ||
models.ForeignKey( | ||
help_text="Project in which this objects belongs", | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to="projectroles.Project", | ||
), | ||
), | ||
], | ||
options={"ordering": ("title",),}, | ||
), | ||
migrations.AlterUniqueTogether( | ||
name="reporttemplate", unique_together=set([("project", "filename")]), | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import uuid as uuid_object | ||
|
||
from django.db import models | ||
from django.conf import settings | ||
from django.urls import reverse | ||
from projectroles.models import Project | ||
|
||
#: Django user model. | ||
AUTH_USER_MODEL = getattr(settings, "AUTH_USER_MODEL", "auth.User") | ||
|
||
|
||
class ReportTemplate(models.Model): | ||
"""A report template.""" | ||
|
||
#: DateTime of creation | ||
date_created = models.DateTimeField(auto_now_add=True, help_text="DateTime of creation") | ||
#: DateTime of last modification | ||
date_modified = models.DateTimeField(auto_now=True, help_text="DateTime of last modification") | ||
|
||
#: UUID used for identification throughout SODAR. | ||
sodar_uuid = models.UUIDField( | ||
default=uuid_object.uuid4, unique=True, help_text="Case SODAR UUID" | ||
) | ||
|
||
#: The project containing this case. | ||
project = models.ForeignKey(Project, help_text="Project in which this objects belongs") | ||
|
||
#: Title of the report. | ||
title = models.CharField(max_length=512) | ||
#: File name of the report. | ||
filename = models.CharField(max_length=512) | ||
|
||
#: File size in bytes. | ||
filesize = models.IntegerField(default=0) | ||
#: File hash. | ||
filehash = models.CharField(max_length=128) | ||
|
||
class Meta: | ||
unique_together = (("project", "filename"),) | ||
ordering = ("title",) | ||
|
||
def get_absolute_url(self): | ||
return reverse( | ||
"reports:template-view", | ||
kwargs={"project": self.project.sodar_uuid, "template": self.sodar_uuid}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from projectroles.plugins import ProjectAppPluginPoint | ||
|
||
from .urls import urlpatterns | ||
|
||
|
||
class ProjectAppPlugin(ProjectAppPluginPoint): | ||
"""Plugin for registering app with Projectroles""" | ||
|
||
name = "reports" | ||
title = "Reports" | ||
urls = urlpatterns | ||
# ... | ||
|
||
icon = "file-text-o" | ||
|
||
entry_point_url_id = "reports:template-list" | ||
|
||
description = "Generate reports on word processing templates" | ||
|
||
#: Required permission for accessing the app | ||
app_permission = "reports.view_data" | ||
|
||
#: Enable or disable general search from project title bar | ||
search_enable = False | ||
|
||
#: List of search object types for the app | ||
search_types = [] | ||
|
||
#: No settings for this app. | ||
app_settings = {} | ||
|
||
def get_object_link(self, model_str, uuid): | ||
""" | ||
Return URL for referring to a object used by the app, along with a | ||
label to be shown to the user for linking. | ||
:param model_str: Object class (string) | ||
:param uuid: sodar_uuid of the referred object | ||
:return: Dict or None if not found | ||
""" | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import rules | ||
from projectroles import rules as pr_rules | ||
|
||
|
||
rules.add_perm( | ||
"reports.view_data", | ||
rules.is_superuser | ||
| pr_rules.is_project_owner | ||
| pr_rules.is_project_delegate | ||
| pr_rules.is_project_contributor | ||
| pr_rules.is_project_guest, | ||
) | ||
|
||
rules.add_perm( | ||
"reports.add_data", | ||
rules.is_superuser | ||
| pr_rules.is_project_owner | ||
| pr_rules.is_project_delegate | ||
| pr_rules.is_project_contributor, | ||
) | ||
rules.add_perm( | ||
"reports.delete_data", | ||
rules.is_superuser | ||
| pr_rules.is_project_owner | ||
| pr_rules.is_project_delegate | ||
| pr_rules.is_project_contributor, | ||
) | ||
rules.add_perm( | ||
"reports.update_data", | ||
rules.is_superuser | ||
| pr_rules.is_project_owner | ||
| pr_rules.is_project_delegate | ||
| pr_rules.is_project_contributor, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{% load rules %} | ||
|
||
{% has_perm 'reports.update_data' request.user as can_update_data %} | ||
{% has_perm 'reports.delete_data' request.user as can_delete_data %} | ||
|
||
<div class="btn-group sodar-list-btn-group pull-right"> | ||
<button class="btn btn-secondary dropdown-toggle sodar-list-dropdown" | ||
type="button" data-toggle="dropdown" aria-expanded="false"> | ||
<i class="fa fa-cog"></i> | ||
</button> | ||
<div class="dropdown-menu dropdown-menu-right"> | ||
<a class="dropdown-item" href="{% url 'reports:template-view' project=project.sodar_uuid template=object.sodar_uuid %}"> | ||
<i class="fa fa-fw fa-eye"></i> | ||
View | ||
</a> | ||
{% if can_update_data %} | ||
<a class="dropdown-item" href="{% url 'reports:template-update' project=project.sodar_uuid template=object.sodar_uuid %}"> | ||
<i class="fa fa-fw fa-pencil"></i> | ||
Edit | ||
</a> | ||
{% endif %} | ||
{% if can_delete_data %} | ||
<a class="dropdown-item" href="{% url 'reports:template-delete' project=project.sodar_uuid template=object.sodar_uuid %}"> | ||
<i class="fa fa-fw fa-eraser"></i> | ||
Delete | ||
</a> | ||
{% endif %} | ||
</div> | ||
</div> |
35 changes: 35 additions & 0 deletions
35
reports/templates/reports/reporttemplate_confirm_delete.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{% extends 'projectroles/base.html' %} | ||
|
||
{% load rules %} | ||
{% load crispy_forms_filters %} | ||
{% load projectroles_common_tags %} | ||
|
||
{% block title %}Confirm Removal of Report Template{% endblock %} | ||
|
||
{% block projectroles %} | ||
|
||
<div class="row sodar-subtitle-container"> | ||
<h2>Confirm Removal of Report Template</h2> | ||
</div> | ||
|
||
<div class="container-fluid sodar-page-container"> | ||
<div class="alert alert-warning" role="alert"> | ||
Do you really want to remove the report template "<strong>{{ object.title }}</strong>" file file name "<strong>{{ object.filename }}</strong>"? | ||
<strong>This action cannot be reverted!</strong> | ||
</div> | ||
|
||
<form method="post"> | ||
{% csrf_token %} | ||
<div class="btn-group pull-right"> | ||
<a role="button" class="btn btn-secondary" | ||
href="{% url 'reports:template-view' project=project.sodar_uuid template=object.sodar_uuid %}" | ||
<i class="fa fa-arrow-circle-left"></i> Cancel | ||
</a> | ||
<button type="submit" class="btn btn-danger"> | ||
<i class="fa fa-times"></i> Remove | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
|
||
{% endblock projectroles %} |
Oops, something went wrong.