From 83b80cd7b030f50507db453eadd8ee8eac347c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Sun, 9 Feb 2025 14:44:54 +0100 Subject: [PATCH] Create a repository app for documents, first step --- ram/bookshelf/admin.py | 2 +- ram/metadata/admin.py | 47 ---- ram/ram/settings.py | 1 + ram/repository/__init__.py | 0 ram/repository/admin.py | 83 +++++++ ram/repository/apps.py | 6 + ram/repository/migrations/0001_initial.py | 260 ++++++++++++++++++++++ ram/repository/migrations/__init__.py | 0 ram/repository/models.py | 59 +++++ ram/repository/tests.py | 3 + ram/repository/views.py | 3 + ram/roster/admin.py | 38 +--- 12 files changed, 418 insertions(+), 84 deletions(-) create mode 100644 ram/repository/__init__.py create mode 100644 ram/repository/admin.py create mode 100644 ram/repository/apps.py create mode 100644 ram/repository/migrations/0001_initial.py create mode 100644 ram/repository/migrations/__init__.py create mode 100644 ram/repository/models.py create mode 100644 ram/repository/tests.py create mode 100644 ram/repository/views.py diff --git a/ram/bookshelf/admin.py b/ram/bookshelf/admin.py index 72cece5..ae9392c 100644 --- a/ram/bookshelf/admin.py +++ b/ram/bookshelf/admin.py @@ -8,10 +8,10 @@ from adminsortable2.admin import SortableAdminBase, SortableInlineAdminMixin from ram.admin import publish, unpublish from ram.utils import generate_csv from portal.utils import get_site_conf +from repository.models import BaseBookDocument from bookshelf.models import ( BaseBookProperty, BaseBookImage, - BaseBookDocument, Book, Author, Publisher, diff --git a/ram/metadata/admin.py b/ram/metadata/admin.py index 4592d4c..cfed7b3 100644 --- a/ram/metadata/admin.py +++ b/ram/metadata/admin.py @@ -2,7 +2,6 @@ from django.contrib import admin from django.utils.html import format_html from adminsortable2.admin import SortableAdminMixin -from ram.admin import publish, unpublish from metadata.models import ( Property, Decoder, @@ -13,7 +12,6 @@ from metadata.models import ( Company, Tag, RollingStockType, - GenericDocument, ) @@ -88,51 +86,6 @@ class RollingStockTypeAdmin(SortableAdminMixin, admin.ModelAdmin): search_fields = ("type", "category") -@admin.register(GenericDocument) -class GenericDocumentAdmin(admin.ModelAdmin): - readonly_fields = ("size", "creation_time", "updated_time") - list_display = ( - "__str__", - "description", - "private", - "size", - "download", - ) - search_fields = ( - "description", - "file", - ) - fieldsets = ( - ( - None, - { - "fields": ( - "private", - "description", - "file", - "size", - "tags", - ) - }, - ), - ( - "Notes", - {"classes": ("collapse",), "fields": ("notes",)}, - ), - ( - "Audit", - { - "classes": ("collapse",), - "fields": ( - "creation_time", - "updated_time", - ), - }, - ), - ) - actions = [publish, unpublish] - - @admin.register(Shop) class ShopAdmin(admin.ModelAdmin): list_display = ("name", "on_line", "active") diff --git a/ram/ram/settings.py b/ram/ram/settings.py index 4b7a20b..5071c9d 100644 --- a/ram/ram/settings.py +++ b/ram/ram/settings.py @@ -50,6 +50,7 @@ INSTALLED_APPS = [ "portal", # "driver", # uncomment this to enable the "driver" API "metadata", + "repository", "roster", "consist", "bookshelf", diff --git a/ram/repository/__init__.py b/ram/repository/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ram/repository/admin.py b/ram/repository/admin.py new file mode 100644 index 0000000..8f61627 --- /dev/null +++ b/ram/repository/admin.py @@ -0,0 +1,83 @@ +from django.contrib import admin + +from ram.admin import publish, unpublish +from repository.models import GenericDocument, RollingStockDocument + + +@admin.register(GenericDocument) +class GenericDocumentAdmin(admin.ModelAdmin): + readonly_fields = ("size", "creation_time", "updated_time") + list_display = ( + "__str__", + "description", + "private", + "size", + "download", + ) + search_fields = ( + "description", + "file", + ) + fieldsets = ( + ( + None, + { + "fields": ( + "private", + "description", + "file", + "size", + "tags", + ) + }, + ), + ( + "Notes", + {"classes": ("collapse",), "fields": ("notes",)}, + ), + ( + "Audit", + { + "classes": ("collapse",), + "fields": ( + "creation_time", + "updated_time", + ), + }, + ), + ) + actions = [publish, unpublish] + + +@admin.register(RollingStockDocument) +class RollingStockDocumentAdmin(admin.ModelAdmin): + readonly_fields = ("size",) + list_display = ( + "__str__", + "rolling_stock", + "description", + "private", + "size", + "download", + ) + search_fields = ( + "rolling_stock__rolling_class__identifier", + "rolling_stock__item_number", + "description", + "file", + ) + autocomplete_fields = ("rolling_stock",) + fieldsets = ( + ( + None, + { + "fields": ( + "private", + "rolling_stock", + "description", + "file", + "size", + ) + }, + ), + ) diff --git a/ram/repository/apps.py b/ram/repository/apps.py new file mode 100644 index 0000000..10bc534 --- /dev/null +++ b/ram/repository/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class RepositoryConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "repository" diff --git a/ram/repository/migrations/0001_initial.py b/ram/repository/migrations/0001_initial.py new file mode 100644 index 0000000..4ac6917 --- /dev/null +++ b/ram/repository/migrations/0001_initial.py @@ -0,0 +1,260 @@ +# Generated by Django 5.1.4 on 2025-02-09 13:04 + +import django.db.models.deletion +import ram.utils +import tinymce.models +from django.db import migrations, models + + +def migrate_document(apps, schema_editor): + document = apps.get_model("metadata", "GenericDocument") + document_new = apps.get_model("repository", "GenericDocument") + for d in document.objects.all(): + n = document_new.objects.create( + notes=d.notes, + description=d.description, + file=d.file, + private=d.private, + creation_time=d.creation_time, + updated_time=d.updated_time, + ) + for t in d.tags.all(): + n.tags.add(t) + + +def migrate_decoder(apps, schema_editor): + dcc_document = apps.get_model("metadata", "DecoderDocument") + dcc_document_new = apps.get_model("repository", "DecoderDocument") + for d in dcc_document.objects.all(): + dcc_document_new.objects.create( + decoder=d.decoder, + description=d.description, + file=d.file, + private=d.private, + creation_time=d.creation_time, + updated_time=d.updated_time, + ) + + +def migrate_rollingstock(apps, schema_editor): + rs_document = apps.get_model("roster", "RollingStockDocument") + rs_document_new = apps.get_model("repository", "RollingStockDocument") + for d in rs_document.objects.all(): + rs_document_new.objects.create( + rolling_stock=d.rolling_stock, + description=d.description, + file=d.file, + private=d.private, + creation_time=d.creation_time, + updated_time=d.updated_time, + ) + + +def migrate_book(apps, schema_editor): + book_document = apps.get_model("bookshelf", "BaseBookDocument") + book_document_new = apps.get_model("repository", "BaseBookDocument") + for d in book_document.objects.all(): + book_document_new.objects.create( + book=d.book, + description=d.description, + file=d.file, + private=d.private, + creation_time=d.creation_time, + updated_time=d.updated_time, + ) + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("bookshelf", "0022_basebook_shop"), + ("metadata", "0023_shop"), + ("roster", "0035_alter_rollingstock_shop"), + ] + + operations = [ + migrations.CreateModel( + name="BaseBookDocument", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("description", models.CharField(blank=True, max_length=128)), + ( + "file", + models.FileField( + storage=ram.utils.DeduplicatedStorage(), upload_to="files/" + ), + ), + ( + "private", + models.BooleanField( + default=False, + help_text="Document will be visible only to logged users", + ), + ), + ("creation_time", models.DateTimeField(auto_now_add=True)), + ("updated_time", models.DateTimeField(auto_now=True)), + ( + "book", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="new_document", + to="bookshelf.basebook", + ), + ), + ], + options={ + "verbose_name_plural": "Documents", + "abstract": False, + }, + ), + migrations.CreateModel( + name="GenericDocument", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("description", models.CharField(blank=True, max_length=128)), + ( + "file", + models.FileField( + storage=ram.utils.DeduplicatedStorage(), upload_to="files/" + ), + ), + ( + "private", + models.BooleanField( + default=False, + help_text="Document will be visible only to logged users", + ), + ), + ("creation_time", models.DateTimeField(auto_now_add=True)), + ("updated_time", models.DateTimeField(auto_now=True)), + ("notes", tinymce.models.HTMLField(blank=True)), + ( + "tags", + models.ManyToManyField( + blank=True, related_name="new_document", to="metadata.tag" + ), + ), + ], + options={ + "verbose_name_plural": "Generic Documents", + }, + ), + migrations.CreateModel( + name="RollingStockDocument", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("description", models.CharField(blank=True, max_length=128)), + ( + "file", + models.FileField( + storage=ram.utils.DeduplicatedStorage(), upload_to="files/" + ), + ), + ( + "private", + models.BooleanField( + default=False, + help_text="Document will be visible only to logged users", + ), + ), + ("creation_time", models.DateTimeField(auto_now_add=True)), + ("updated_time", models.DateTimeField(auto_now=True)), + ( + "rolling_stock", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="new_document", + to="roster.rollingstock", + ), + ), + ], + options={ + "verbose_name_plural": "Documents", + "abstract": False, + }, + ), + migrations.CreateModel( + name="DecoderDocument", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("description", models.CharField(blank=True, max_length=128)), + ( + "file", + models.FileField( + storage=ram.utils.DeduplicatedStorage(), upload_to="files/" + ), + ), + ( + "private", + models.BooleanField( + default=False, + help_text="Document will be visible only to logged users", + ), + ), + ("creation_time", models.DateTimeField(auto_now_add=True)), + ("updated_time", models.DateTimeField(auto_now=True)), + ( + "decoder", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="new_document", + to="metadata.decoder", + ), + ), + ], + options={ + "verbose_name_plural": "Documents", + "abstract": False, + }, + ), + migrations.RunPython( + migrate_document, + reverse_code=migrations.RunPython.noop + ), + migrations.RunPython( + migrate_decoder, + reverse_code=migrations.RunPython.noop + ), + migrations.RunPython( + migrate_rollingstock, + reverse_code=migrations.RunPython.noop + ), + migrations.RunPython( + migrate_book, + reverse_code=migrations.RunPython.noop + ), + ] diff --git a/ram/repository/migrations/__init__.py b/ram/repository/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ram/repository/models.py b/ram/repository/models.py new file mode 100644 index 0000000..9a33207 --- /dev/null +++ b/ram/repository/models.py @@ -0,0 +1,59 @@ +from django.db import models + +from tinymce import models as tinymce + +from ram.models import Document +from metadata.models import Decoder, Tag +from roster.models import RollingStock +from bookshelf.models import BaseBook + + +class GenericDocument(Document): + notes = tinymce.HTMLField(blank=True) + tags = models.ManyToManyField(Tag, blank=True, related_name="new_document") + + class Meta: + verbose_name_plural = "Generic Documents" + + +class DecoderDocument(Document): + decoder = models.ForeignKey( + Decoder, on_delete=models.CASCADE, related_name="new_document" + ) + + # class Meta: + # constraints = [ + # models.UniqueConstraint( + # fields=["decoder", "file"], + # name="unique_decoder_file" + # ) + # ] + + +class BaseBookDocument(Document): + book = models.ForeignKey( + BaseBook, on_delete=models.CASCADE, related_name="new_document" + ) + + # class Meta: + # verbose_name_plural = "Documents" + # constraints = [ + # models.UniqueConstraint( + # fields=["book", "file"], + # name="unique_book_file" + # ) + # ] + + +class RollingStockDocument(Document): + rolling_stock = models.ForeignKey( + RollingStock, on_delete=models.CASCADE, related_name="new_document" + ) + + # class Meta: + # constraints = [ + # models.UniqueConstraint( + # fields=["rolling_stock", "file"], + # name="unique_stock_file" + # ) + # ] diff --git a/ram/repository/tests.py b/ram/repository/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/ram/repository/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/ram/repository/views.py b/ram/repository/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/ram/repository/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/ram/roster/admin.py b/ram/roster/admin.py index 86e52c7..fc665fb 100644 --- a/ram/roster/admin.py +++ b/ram/roster/admin.py @@ -9,12 +9,12 @@ from adminsortable2.admin import SortableAdminBase, SortableInlineAdminMixin from ram.admin import publish, unpublish from ram.utils import generate_csv from portal.utils import get_site_conf +from repository.models import RollingStockDocument from roster.models import ( RollingClass, RollingClassProperty, RollingStock, RollingStockImage, - RollingStockDocument, RollingStockProperty, RollingStockJournal, ) @@ -76,42 +76,8 @@ class RollingStockJournalInline(admin.TabularInline): classes = ["collapse"] -@admin.register(RollingStockDocument) -class RollingStockDocumentAdmin(admin.ModelAdmin): - readonly_fields = ("size",) - list_display = ( - "__str__", - "rolling_stock", - "description", - "private", - "size", - "download", - ) - search_fields = ( - "rolling_stock__rolling_class__identifier", - "rolling_stock__item_number", - "description", - "file", - ) - autocomplete_fields = ("rolling_stock",) - fieldsets = ( - ( - None, - { - "fields": ( - "private", - "rolling_stock", - "description", - "file", - "size", - ) - }, - ), - ) - - @admin.register(RollingStockJournal) -class RollingJournalDocumentAdmin(admin.ModelAdmin): +class RollingJournalAdmin(admin.ModelAdmin): list_display = ( "__str__", "date",