diff --git a/src/documents/migrations/0023_savedview_icon.py b/src/documents/migrations/0023_savedview_icon.py new file mode 100644 index 000000000..6d32d2e5f --- /dev/null +++ b/src/documents/migrations/0023_savedview_icon.py @@ -0,0 +1,56 @@ +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("documents", "0022_add_perf_indexes"), + ] + + operations = [ + migrations.AddField( + model_name="savedview", + name="icon", + field=models.CharField( + choices=[ + ("archive", "Archive"), + ("bell", "Bell"), + ("boxes", "Boxes"), + ("calendar", "Calendar"), + ("card-checklist", "Checklist"), + ("chat-left-text", "Chat"), + ("check-circle", "Check"), + ("clipboard", "Clipboard"), + ("clock-history", "Clock"), + ("download", "Download"), + ("envelope", "Envelope"), + ("exclamation-triangle", "Warning"), + ("file-earmark", "File"), + ("file-earmark-check", "Checked file"), + ("file-earmark-lock", "Locked file"), + ("file-text", "Text file"), + ("files", "Files"), + ("folder", "Folder"), + ("funnel", "Filter"), + ("gear", "Gear"), + ("hash", "Hash"), + ("house", "House"), + ("journals", "Journals"), + ("list-task", "Task list"), + ("people", "People"), + ("person", "Person"), + ("printer", "Printer"), + ("search", "Search"), + ("send", "Send"), + ("stack", "Stack"), + ("stars", "Stars"), + ("tag", "Tag"), + ("tags", "Tags"), + ("upc-scan", "Barcode"), + ], + default="funnel", + max_length=64, + verbose_name="icon", + ), + ), + ] diff --git a/src/documents/models.py b/src/documents/models.py index c9b7109bc..7de60e8fa 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -519,6 +519,42 @@ class Document(SoftDeleteModel, ModelWithOwner): # type: ignore[django-manager- class SavedView(ModelWithOwner): + class Icon(models.TextChoices): + ARCHIVE = ("archive", _("Archive")) + BELL = ("bell", _("Bell")) + BOXES = ("boxes", _("Boxes")) + CALENDAR = ("calendar", _("Calendar")) + CARD_CHECKLIST = ("card-checklist", _("Checklist")) + CHAT_LEFT_TEXT = ("chat-left-text", _("Chat")) + CHECK_CIRCLE = ("check-circle", _("Check")) + CLIPBOARD = ("clipboard", _("Clipboard")) + CLOCK_HISTORY = ("clock-history", _("Clock")) + DOWNLOAD = ("download", _("Download")) + ENVELOPE = ("envelope", _("Envelope")) + EXCLAMATION_TRIANGLE = ("exclamation-triangle", _("Warning")) + FILE_EARMARK = ("file-earmark", _("File")) + FILE_EARMARK_CHECK = ("file-earmark-check", _("Checked file")) + FILE_EARMARK_LOCK = ("file-earmark-lock", _("Locked file")) + FILE_TEXT = ("file-text", _("Text file")) + FILES = ("files", _("Files")) + FOLDER = ("folder", _("Folder")) + FUNNEL = ("funnel", _("Filter")) + GEAR = ("gear", _("Gear")) + HASH = ("hash", _("Hash")) + HOUSE = ("house", _("House")) + JOURNALS = ("journals", _("Journals")) + LIST_TASK = ("list-task", _("Task list")) + PEOPLE = ("people", _("People")) + PERSON = ("person", _("Person")) + PRINTER = ("printer", _("Printer")) + SEARCH = ("search", _("Search")) + SEND = ("send", _("Send")) + STACK = ("stack", _("Stack")) + STARS = ("stars", _("Stars")) + TAG = ("tag", _("Tag")) + TAGS = ("tags", _("Tags")) + UPC_SCAN = ("upc-scan", _("Barcode")) + class DisplayMode(models.TextChoices): TABLE = ("table", _("Table")) SMALL_CARDS = ("smallCards", _("Small Cards")) @@ -541,6 +577,13 @@ class SavedView(ModelWithOwner): name = models.CharField(_("name"), max_length=128) + icon = models.CharField( + _("icon"), + max_length=64, + choices=Icon.choices, + default=Icon.FUNNEL, + ) + sort_field = models.CharField( _("sort field"), max_length=128, diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index add3610af..c0ccae2ba 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -1389,6 +1389,7 @@ class SavedViewSerializer(OwnedObjectSerializer): fields = [ "id", "name", + "icon", "sort_field", "sort_reverse", "filter_rules", diff --git a/src/documents/tests/test_api_documents.py b/src/documents/tests/test_api_documents.py index edd9f3df3..e4226b28e 100644 --- a/src/documents/tests/test_api_documents.py +++ b/src/documents/tests/test_api_documents.py @@ -2880,18 +2880,20 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase): v1 = SavedView.objects.get(name="test") self.assertEqual(v1.sort_field, "created2") + self.assertEqual(v1.icon, SavedView.Icon.FUNNEL) self.assertEqual(v1.filter_rules.count(), 1) self.assertEqual(v1.owner, self.user) response = self.client.patch( f"/api/saved_views/{v1.id}/", - {"sort_reverse": True}, + {"sort_reverse": True, "icon": SavedView.Icon.ARCHIVE}, format="json", ) v1 = SavedView.objects.get(id=v1.id) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertTrue(v1.sort_reverse) + self.assertEqual(v1.icon, SavedView.Icon.ARCHIVE) self.assertEqual(v1.filter_rules.count(), 1) view["filter_rules"] = [{"rule_type": 12, "value": "secret"}] @@ -2911,6 +2913,13 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase): v1 = SavedView.objects.get(id=v1.id) self.assertEqual(v1.filter_rules.count(), 0) + response = self.client.patch( + f"/api/saved_views/{v1.id}/", + {"icon": "not-an-icon"}, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + def test_saved_view_display_options(self) -> None: """ GIVEN: