From d01968ba9afd2d2ae017f039fdf12b3d102ddf9c Mon Sep 17 00:00:00 2001 From: Erwan Rouchet <rouchet@teklia.com> Date: Mon, 10 May 2021 17:05:11 +0200 Subject: [PATCH] Allow updating a file import process' element --- arkindex/dataimport/serializers/imports.py | 36 +++++++++++++++------- arkindex/dataimport/tests/test_imports.py | 23 +++++++++++++- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/arkindex/dataimport/serializers/imports.py b/arkindex/dataimport/serializers/imports.py index bbc009fd62..b5c5b4adeb 100644 --- a/arkindex/dataimport/serializers/imports.py +++ b/arkindex/dataimport/serializers/imports.py @@ -21,7 +21,7 @@ class DataImportLightSerializer(serializers.ModelSerializer): Serialize a data importing workflow """ - state = EnumField(State) + state = EnumField(State, read_only=True) mode = EnumField(DataImportMode, read_only=True) creator = serializers.HiddenField(default=serializers.CurrentUserDefault()) workflow = serializers.HyperlinkedRelatedField(read_only=True, view_name='ponos:workflow-details') @@ -44,11 +44,16 @@ class DataImportSerializer(DataImportLightSerializer): """ Serialize a data importing workflow with its settings """ - - # Redefine state as writable - state = EnumField(State, read_only=True) revision = RevisionSerializer(read_only=True) element = ElementSlimSerializer(read_only=True) + element_id = serializers.PrimaryKeyRelatedField( + queryset=Element.objects.none(), + default=None, + allow_null=True, + write_only=True, + source='element', + style={'base_template': 'input.html'}, + ) folder_type = serializers.SlugField(source='folder_type.slug', default=None, read_only=True) element_type = serializers.SlugRelatedField(queryset=ElementType.objects.none(), slug_field='slug', allow_null=True) element_name_contains = serializers.CharField( @@ -59,18 +64,12 @@ class DataImportSerializer(DataImportLightSerializer): ) activity_state = EnumField(ActivityState, read_only=True) - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - dataimport = self.context.get('dataimport') - if not dataimport or not dataimport.corpus: - return - self.fields['element_type'].queryset = ElementType.objects.filter(corpus=dataimport.corpus) - class Meta(DataImportLightSerializer.Meta): fields = DataImportLightSerializer.Meta.fields + ( 'files', 'revision', 'element', + 'element_id', 'folder_type', 'element_type', 'element_name_contains', @@ -87,6 +86,14 @@ class DataImportSerializer(DataImportLightSerializer): 'activity_state', ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + dataimport = self.context.get('dataimport') + if not dataimport or not dataimport.corpus: + return + self.fields['element_type'].queryset = ElementType.objects.filter(corpus=dataimport.corpus) + self.fields['element_id'].queryset = dataimport.corpus.elements.all() + def validate(self, data): data = super().validate(data) # Editing a dataimport name only is always allowed @@ -95,10 +102,17 @@ class DataImportSerializer(DataImportLightSerializer): if not self.instance: return + + # Allow editing the element ID on file imports at any time + if self.instance.mode in (DataImportMode.Images, DataImportMode.PDF, DataImportMode.IIIF) and set(data.keys()) == {'element'}: + return data + if self.instance.state == State.Running: raise serializers.ValidationError({'__all__': ['Cannot edit a workflow while it is running']}) + if self.instance.mode != DataImportMode.Workers: raise serializers.ValidationError({'__all__': [f'Only processes of mode {DataImportMode.Workers} can be updated']}) + return data diff --git a/arkindex/dataimport/tests/test_imports.py b/arkindex/dataimport/tests/test_imports.py index 1f5fc64954..52037bf2d9 100644 --- a/arkindex/dataimport/tests/test_imports.py +++ b/arkindex/dataimport/tests/test_imports.py @@ -488,6 +488,27 @@ class TestImports(FixtureAPITestCase): self.elts_process.refresh_from_db() self.assertEqual(self.elts_process.name, 'newName') + def test_update_file_import_element(self): + """ + A file import's element can be updated even while it is running + """ + self.client.force_login(self.user) + process = self.corpus.imports.create(mode=DataImportMode.PDF, creator=self.user) + process.start() + process.workflow.tasks.update(state=State.Running) + self.assertIsNone(self.elts_process.element) + + element = self.corpus.elements.first() + with self.assertNumQueries(14): + response = self.client.patch( + reverse('api:import-details', kwargs={'pk': process.id}), + {'element_id': str(element.id)}, + format='json' + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + process.refresh_from_db() + self.assertEqual(process.element, element) + def test_update_process_no_permission(self): """ A user cannot update a dataimport linked to a corpus he has no admin access to @@ -659,7 +680,7 @@ class TestImports(FixtureAPITestCase): }, format='json' ) - self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.status_code, status.HTTP_200_OK, response.json()) self.assertEqual(response.json(), { 'name': 'newName', 'element_name_contains': 'AAA', -- GitLab