Skip to content

Commit

Permalink
Merge pull request #2 from scieloorg/infrastructure_directory
Browse files Browse the repository at this point in the history
Adiciona a aplicação infrastructure_directory para acomodar o modelo de Diretório de infraestrutura.
  • Loading branch information
gitnnolabs authored Jul 5, 2022
2 parents a919d82 + 4db2175 commit 15ec7ae
Show file tree
Hide file tree
Showing 20 changed files with 2,365 additions and 0 deletions.
574 changes: 574 additions & 0 deletions core/libs/chkcsv.py

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import os

from django.db import models
from django.contrib.auth import get_user_model
from django.utils.translation import gettext as _

User = get_user_model()


class CommonControlField(models.Model):
"""
Class with common control fields.
Fields:
created: Date time when the record was created
updated: Date time with the last update date
creator: The creator of the record
updated_by: Store the last updator of the record
"""

# Creation date
created = models.DateTimeField(
verbose_name=_("Creation date"), auto_now_add=True
)

# Update date
updated = models.DateTimeField(
verbose_name=_("Last update date"), auto_now=True
)

# Creator user
creator = models.ForeignKey(
User,
verbose_name=_("Creator"),
related_name="%(class)s_creator",
editable=False,
on_delete=models.CASCADE,
)

# Last modifier user
updated_by = models.ForeignKey(
User,
verbose_name=_("Updater"),
related_name="%(class)s_last_mod_user",
editable=False,
null=True,
blank=True,
on_delete=models.CASCADE,
)

class Meta:
abstract = True
Empty file.
3 changes: 3 additions & 0 deletions infrastructure_directory/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions infrastructure_directory/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class InfrastructureDirectoryConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'infrastructure_directory'
47 changes: 47 additions & 0 deletions infrastructure_directory/button_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from django.utils.translation import gettext as _
from wagtail.contrib.modeladmin.helpers import ButtonHelper

from django.urls import reverse


class InfrastructureDirectoryHelper(ButtonHelper):

# Define classes for our button, here we can set an icon for example
validate_button_classnames = ["button-small", "icon",]
import_button_classnames = ["button-small", "icon",]

def validate_button(self, obj):
# Define a label for our button
text = _("Validate")
return {
"url": reverse("infrastructure_directory:validate") + "?file_id=%s" % str(obj.id),
"label": text,
"classname": self.finalise_classname(self.validate_button_classnames),
"title": text,
}

def import_button(self, obj):
# Define a label for our button
text = _("Import")
return {
"url": reverse("infrastructure_directory:import_file") + "?file_id=%s" % str(obj.id),
"label": text,
"classname": self.finalise_classname(self.import_button_classnames),
"title": text,
}

def get_buttons_for_obj(
self, obj, exclude=None, classnames_add=None, classnames_exclude=None
):
"""
This function is used to gather all available buttons.
We append our custom button to the btns list.
"""
btns = super().get_buttons_for_obj(
obj, exclude, classnames_add, classnames_exclude
)
if "validate" not in (exclude or []):
btns.append(self.validate_button(obj))
if "import" not in (exclude or []):
btns.append(self.import_button(obj))
return btns
11 changes: 11 additions & 0 deletions infrastructure_directory/chkcsvfmt.fmt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Title]
data_required=True
type=String

[Link]
data_required=False
type=String

[Description]
data_required=False
type=String
2 changes: 2 additions & 0 deletions infrastructure_directory/example_infra.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Title,Link,Description
FAPESP,http://www.fapesp.com.br,primary
31 changes: 31 additions & 0 deletions infrastructure_directory/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from wagtail.admin.forms import WagtailAdminModelForm


class InfrastructureDirectoryForm(WagtailAdminModelForm):

def save_all(self, user):
structure_directory = super().save(commit=False)

if self.instance.pk is not None:
structure_directory.updated_by = user
else:
structure_directory.creator = user

self.save()

return structure_directory


class InfrastructureDirectoryFileForm(WagtailAdminModelForm):

def save_all(self, user):
structure_directory_file = super().save(commit=False)

if self.instance.pk is not None:
structure_directory_file.updated_by = user
else:
structure_directory_file.creator = user

self.save()

return structure_directory_file
50 changes: 50 additions & 0 deletions infrastructure_directory/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Generated by Django 3.2.12 on 2022-06-28 14:10

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('wagtaildocs', '0012_uploadeddocument'),
]

operations = [
migrations.CreateModel(
name='InfrastructureDirectoryFile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')),
('is_valid', models.BooleanField(blank=True, default=False, null=True, verbose_name='Is valid?')),
('line_count', models.IntegerField(blank=True, default=0, null=True, verbose_name='Number of lines')),
('attachment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtaildocs.document', verbose_name='Attachement')),
('creator', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='infrastructuredirectoryfile_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')),
('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='infrastructuredirectoryfile_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='InfrastructureDirectory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Last update date')),
('name', models.CharField(max_length=255, verbose_name='Nome')),
('link', models.URLField(verbose_name='Link')),
('description', models.CharField(blank=True, max_length=255, null=True, verbose_name='Description')),
('creator', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='infrastructuredirectory_creator', to=settings.AUTH_USER_MODEL, verbose_name='Creator')),
('updated_by', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='infrastructuredirectory_last_mod_user', to=settings.AUTH_USER_MODEL, verbose_name='Updater')),
],
options={
'abstract': False,
},
),
]
28 changes: 28 additions & 0 deletions infrastructure_directory/migrations/0002_auto_20220628_1757.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.2.12 on 2022-06-28 17:57

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('infrastructure_directory', '0001_initial'),
]

operations = [
migrations.RemoveField(
model_name='infrastructuredirectory',
name='name',
),
migrations.AddField(
model_name='infrastructuredirectory',
name='title',
field=models.CharField(default=None, max_length=255, verbose_name='Título'),
preserve_default=False,
),
migrations.AlterField(
model_name='infrastructuredirectory',
name='description',
field=models.TextField(blank=True, max_length=255, null=True, verbose_name='Description'),
),
]
Empty file.
50 changes: 50 additions & 0 deletions infrastructure_directory/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import os
from django.db import models
from django.utils.translation import gettext as _

from wagtail.admin.edit_handlers import FieldPanel
from wagtail.documents.edit_handlers import DocumentChooserPanel

from core.models import CommonControlField
from .forms import InfrastructureDirectoryForm, InfrastructureDirectoryFileForm


class InfrastructureDirectory(CommonControlField):
class Meta:
verbose_name_plural = _('Infraestructure Directory')

title = models.CharField(_("Title"), max_length=255, null=False, blank=False)
link = models.URLField(_("Link"), null=False, blank=False)
description = models.TextField(_("Description"), max_length=255,
null=True, blank=True)

panels = [
FieldPanel('title'),
FieldPanel('link'),
FieldPanel('description')
]
base_form_class = InfrastructureDirectoryForm

class InfrastructureDirectoryFile(CommonControlField):
class Meta:
verbose_name_plural = _('Infraestructure Directory Upload')

attachment = models.ForeignKey(
'wagtaildocs.Document',
verbose_name=_("Attachement"),
null=True, blank=False,
on_delete=models.SET_NULL,
related_name='+'
)
is_valid = models.BooleanField(_("Is valid?"), default=False, blank=True,
null=True)
line_count = models.IntegerField(_("Number of lines"), default=0,
blank=True, null=True)

def filename(self):
return os.path.basename(self.attachment.name)

panels = [
DocumentChooserPanel('attachment')
]
base_form_class = InfrastructureDirectoryFileForm
3 changes: 3 additions & 0 deletions infrastructure_directory/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
9 changes: 9 additions & 0 deletions infrastructure_directory/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import path

from .views import import_file, validate

app_name = "infrastructure_directory"
urlpatterns = [
path("validate", view=validate, name="validate"),
path("import", view=import_file, name="import_file"),
]
84 changes: 84 additions & 0 deletions infrastructure_directory/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import os
import csv
from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import gettext as _

from wagtail.admin import messages

from core.libs import chkcsv

from .models import InfrastructureDirectoryFile, InfrastructureDirectory


def validate(request):
"""
This view function validade a csv file based on a pre definition os the fmt
file.
The check_csv_file function check that all of the required columns and data
are present in the CSV file, and that the data conform to the appropriate
type and other specifications, when it is not valid return a list with the
errors.
"""
errorlist = []
file_id = request.GET.get("file_id", None)

if file_id:
file_upload = get_object_or_404(InfrastructureDirectoryFile, pk=file_id)

if request.method == 'GET':
try:
upload_path = file_upload.attachment.file.path
cols = chkcsv.read_format_specs(
os.path.dirname(os.path.abspath(__file__)) + "/chkcsvfmt.fmt", True, False)
errorlist = chkcsv.check_csv_file(upload_path, cols, True, True, True, False)
if errorlist:
raise Exception(_("Valication error"))
else:
file_upload.is_valid = True
fp = open(upload_path)
file_upload.line_count = len(fp.readlines())
file_upload.save()
except Exception as ex:
messages.error(request, _("Valication error: %s") % errorlist)
else:
messages.success(request, _("File successfully validated!"))

return redirect(request.META.get('HTTP_REFERER'))


def import_file(request):
"""
This view function import the data from a CSV file.
Something like this:
Title,Link,Description
FAPESP,http://www.fapesp.com.br,primary
TODO: This function must be a task.
"""
file_id = request.GET.get("file_id", None)

if file_id:
file_upload = get_object_or_404(InfrastructureDirectoryFile, pk=file_id)

file_path = file_upload.attachment.file.path

try:
with open(file_path, 'r') as csvfile:
data = csv.DictReader(csvfile)

for row in data:
isd = InfrastructureDirectory()
isd.title = row['Title']
isd.link = row['Link']
isd.description = row['Description']
isd.creator = request.user
isd.save()
except Exception as ex:
messages.error(request, _("Import error: %s") % ex)
else:
messages.success(request, _("File imported successfully!"))

return redirect(request.META.get('HTTP_REFERER'))
Loading

0 comments on commit 15ec7ae

Please sign in to comment.