diff --git a/arkindex/documents/migrations/0007_elementtype_color.py b/arkindex/documents/migrations/0007_elementtype_color.py new file mode 100644 index 0000000000000000000000000000000000000000..8e1bd4578b864a7f2015d2a22dff394e10861825 --- /dev/null +++ b/arkindex/documents/migrations/0007_elementtype_color.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.7 on 2023-07-06 14:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('documents', '0006_index_cleanup'), + ] + + operations = [ + migrations.AddField( + model_name='elementtype', + name='color', + field=models.CharField(default='28b62c', max_length=6), + ), + ] diff --git a/arkindex/documents/models.py b/arkindex/documents/models.py index a497f2815233ea726e830b643cb92f6f028cac7c..0ddd5d524c072f9894c3921725273e72d2f2f1c0 100644 --- a/arkindex/documents/models.py +++ b/arkindex/documents/models.py @@ -78,6 +78,7 @@ class ElementType(models.Model): display_name = models.CharField(max_length=250) folder = models.BooleanField(default=False) indexable = models.BooleanField(default=False) + color = models.CharField(max_length=6, default='28b62c') class Meta: constraints = [ diff --git a/arkindex/documents/serializers/light.py b/arkindex/documents/serializers/light.py index 999c55bbe46394a6ea857b4317ccff833611d418..00a8b3d4b8d2b5def6300eac3d257b3f7955aa64 100644 --- a/arkindex/documents/serializers/light.py +++ b/arkindex/documents/serializers/light.py @@ -80,6 +80,7 @@ class ElementTypeLightSerializer(serializers.ModelSerializer): 'slug', 'display_name', 'folder', + 'color', ) def validate(self, data): diff --git a/arkindex/documents/tests/test_corpus.py b/arkindex/documents/tests/test_corpus.py index 00402a92e00444329b4157f0af71895aebe7a3a1..6af0b9be0b10674812bdc49e2be3105f1f985dfe 100644 --- a/arkindex/documents/tests/test_corpus.py +++ b/arkindex/documents/tests/test_corpus.py @@ -20,31 +20,37 @@ EXPECTED_CORPUS_TYPES = [ 'slug': 'volume', 'display_name': 'Volume', 'folder': True, + 'color': '28b62c' }, { 'slug': 'page', 'display_name': 'Page', 'folder': False, + 'color': '28b62c' }, { 'slug': 'act', 'display_name': 'Act', 'folder': False, + 'color': '28b62c' }, { 'slug': 'surface', 'display_name': 'Surface', 'folder': False, + 'color': '28b62c' }, { 'slug': 'text_line', 'display_name': 'Line', 'folder': False, + 'color': '28b62c' }, { 'slug': 'word', 'display_name': 'Word', 'folder': False, + 'color': '28b62c' } ] @@ -295,6 +301,7 @@ class TestCorpus(FixtureAPITestCase): 'slug', 'display_name', 'folder', + 'color', )), [{ 'folder': False, diff --git a/arkindex/documents/tests/test_element_type.py b/arkindex/documents/tests/test_element_type.py index be7589fe305c2cf21963fe44139e6ca7d9160b65..98e344afa16b3ffd606d8d323411af7ff83522c5 100644 --- a/arkindex/documents/tests/test_element_type.py +++ b/arkindex/documents/tests/test_element_type.py @@ -53,12 +53,38 @@ class TestElementType(FixtureAPITestCase): def test_create(self): self.client.force_login(self.superuser) - response = self.client.post(reverse('api:element-type-create'), { - 'corpus': self.corpus.id, - 'slug': 'New_element_type', - 'display_name': 'New element type', - }, format='json') - self.assertEqual(response.status_code, status.HTTP_201_CREATED) + with self.assertNumQueries(5): + response = self.client.post(reverse('api:element-type-create'), { + 'corpus': self.corpus.id, + 'slug': 'New_element_type', + 'display_name': 'New element type', + }, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + data = response.json() + self.assertIn('id', data) + element_type = ElementType.objects.get(id=data['id']) + self.assertDictEqual( + data, + { + 'id': str(element_type.id), + 'corpus': str(element_type.corpus.id), + 'slug': element_type.slug, + 'display_name': element_type.display_name, + 'folder': element_type.folder, + 'color': '28b62c' + } + ) + + def test_create_with_color(self): + self.client.force_login(self.superuser) + with self.assertNumQueries(5): + response = self.client.post(reverse('api:element-type-create'), { + 'corpus': self.corpus.id, + 'slug': 'New_element_type', + 'display_name': 'New element type', + 'color': 'd90dc4' + }, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) data = response.json() self.assertIn('id', data) element_type = ElementType.objects.get(id=data['id']) @@ -69,10 +95,23 @@ class TestElementType(FixtureAPITestCase): 'corpus': str(element_type.corpus.id), 'slug': element_type.slug, 'display_name': element_type.display_name, - 'folder': element_type.folder + 'folder': element_type.folder, + 'color': 'd90dc4' } ) + def test_create_with_color_valid_length(self): + self.client.force_login(self.superuser) + with self.assertNumQueries(3): + response = self.client.post(reverse('api:element-type-create'), { + 'corpus': self.corpus.id, + 'slug': 'New_element_type', + 'display_name': 'New element type', + 'color': 'chouquette' + }, format='json') + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertDictEqual(response.json(), {'color': ['Ensure this field has no more than 6 characters.']}) + def test_partial_update_requires_login(self): response = self.client.post(reverse('api:element-type', kwargs={'pk': self.element_type.id}), { 'slug': 'New_element_type', @@ -108,16 +147,28 @@ class TestElementType(FixtureAPITestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertDictEqual(response.json(), {'slug': ['Slug must be unique']}) + def test_partial_update_color_valid_length(self): + self.client.force_login(self.superuser) + with self.assertNumQueries(3): + response = self.client.patch( + reverse('api:element-type', kwargs={'pk': self.element_type.id}), + {'color': 'chouquette'}, format='json' + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertDictEqual(response.json(), {'color': ['Ensure this field has no more than 6 characters.']}) + def test_partial_update(self): self.client.force_login(self.superuser) cases = [ {'slug': 'new_element_type'}, {'display_name': 'New element type'}, {'folder': True}, + {'color': '4287f5'}, { 'slug': 'new_element_type', 'display_name': 'New element type', 'folder': False, + 'color': '4287f5' }, { 'slug': 'new_element_type', @@ -126,7 +177,7 @@ class TestElementType(FixtureAPITestCase): ] for update_data in cases: - with self.subTest(**update_data): + with self.subTest(**update_data) and self.assertNumQueries(7): response = self.client.patch( reverse('api:element-type', kwargs={'pk': self.element_type.id}), update_data, @@ -142,7 +193,8 @@ class TestElementType(FixtureAPITestCase): 'id': str(self.element_type.id), 'slug': self.element_type.slug, 'display_name': self.element_type.display_name, - 'folder': self.element_type.folder + 'folder': self.element_type.folder, + 'color': self.element_type.color } ) @@ -182,13 +234,30 @@ class TestElementType(FixtureAPITestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertDictEqual(response.json(), {'slug': ['Slug must be unique']}) + def test_update_color_valid_length(self): + self.client.force_login(self.superuser) + with self.assertNumQueries(3): + response = self.client.put( + reverse('api:element-type', kwargs={'pk': self.element_type.id}), + { + 'slug': 'New_element_type', + 'display_name': 'New element type', + 'color': 'chouquette' + }, + format='json' + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertDictEqual(response.json(), {'color': ['Ensure this field has no more than 6 characters.']}) + def test_update(self): self.client.force_login(self.superuser) - response = self.client.put(reverse('api:element-type', kwargs={'pk': self.element_type.id}), { - 'slug': 'New_element_type', - 'display_name': 'New element type', - }, format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) + with self.assertNumQueries(6): + response = self.client.put(reverse('api:element-type', kwargs={'pk': self.element_type.id}), { + 'slug': 'New_element_type', + 'display_name': 'New element type', + 'color': '4287f5' + }, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.element_type.refresh_from_db() self.assertIn('id', data) @@ -198,7 +267,8 @@ class TestElementType(FixtureAPITestCase): 'id': str(self.element_type.id), 'slug': self.element_type.slug, 'display_name': self.element_type.display_name, - 'folder': self.element_type.folder + 'folder': self.element_type.folder, + 'color': '4287f5' } ) diff --git a/arkindex/process/tests/test_transkribus_import.py b/arkindex/process/tests/test_transkribus_import.py index 1c8d37382542cbdb5b12873546db6796b34d8a77..7c2a6f75d6f06d2ee5e9ac44279d6b2ce7c62c09 100644 --- a/arkindex/process/tests/test_transkribus_import.py +++ b/arkindex/process/tests/test_transkribus_import.py @@ -124,6 +124,7 @@ class TestTranskribusImport(FixtureAPITestCase): "slug", "display_name", "folder", + "color", )), [{ "folder": False, diff --git a/arkindex/project/default_corpus.py b/arkindex/project/default_corpus.py index a8fd62ee6fbf6074642a0a041d97d4b59d3da4b6..691fe36012ae3e05e840eba14bb634d0d1dc1009 100644 --- a/arkindex/project/default_corpus.py +++ b/arkindex/project/default_corpus.py @@ -9,26 +9,32 @@ DEFAULT_CORPUS_TYPES = [ 'slug': 'folder', 'display_name': 'Folder', 'folder': True, + 'color': '28b62c', }, { 'slug': 'page', 'display_name': 'Page', + 'color': '28b62c', }, { 'slug': 'text_line', 'display_name': 'Text line', + 'color': '115eed', }, { 'slug': 'text_zone', 'display_name': 'Text zone', + 'color': '0ac4be' }, { 'slug': 'word', 'display_name': 'Word', + 'color': 'a0c704', }, { 'slug': 'paragraph', 'display_name': 'Paragraph', + 'color': '642aeb' } ] @@ -37,17 +43,21 @@ DEFAULT_TRANSKRIBUS_TYPES = [ 'slug': 'volume', 'display_name': 'Volume', 'folder': True, + 'color': '28b62c', }, { 'slug': 'page', 'display_name': 'Page', + 'color': '28b62c', }, { 'slug': 'text_line', 'display_name': 'Text line', + 'color': '115eed', }, { 'slug': 'paragraph', 'display_name': 'Paragraph', + 'color': '642aeb' } ] diff --git a/arkindex/sql_validation/process_elements_filter_type.sql b/arkindex/sql_validation/process_elements_filter_type.sql index 9d48f344920c7cfc67dd97120b864d49580ba7ac..4046f2f61dd132dbbddf4a5985156ab28e7c4300 100644 --- a/arkindex/sql_validation/process_elements_filter_type.sql +++ b/arkindex/sql_validation/process_elements_filter_type.sql @@ -68,7 +68,8 @@ SELECT "documents_elementtype"."id", "documents_elementtype"."slug", "documents_elementtype"."display_name", "documents_elementtype"."folder", - "documents_elementtype"."indexable" + "documents_elementtype"."indexable", + "documents_elementtype"."color" FROM "documents_elementtype" WHERE "documents_elementtype"."id" = '{type_id}'::uuid LIMIT 21; diff --git a/arkindex/users/tests/test_registration.py b/arkindex/users/tests/test_registration.py index a910d494389ab9ae1220172c9683b0c0fef2af14..0277e1be03aba4203d8539b5e17580744daa6100 100644 --- a/arkindex/users/tests/test_registration.py +++ b/arkindex/users/tests/test_registration.py @@ -150,6 +150,7 @@ class TestRegistration(FixtureAPITestCase): 'slug', 'display_name', 'folder', + 'color', )), [{ 'folder': False,