diff --git a/rsconcept/backend/apps/library/models/LibraryItem.py b/rsconcept/backend/apps/library/models/LibraryItem.py index e72757ae..798a0776 100644 --- a/rsconcept/backend/apps/library/models/LibraryItem.py +++ b/rsconcept/backend/apps/library/models/LibraryItem.py @@ -140,7 +140,7 @@ class LibraryItem(Model): def _update_connected_operations(self): # using method level import to prevent circular dependency from apps.oss.models import Operation # pylint: disable=import-outside-toplevel - operations = Operation.objects.filter(result__pk=self.pk, sync_text=True) + operations = Operation.objects.filter(result__pk=self.pk) if not operations.exists(): return for operation in operations: diff --git a/rsconcept/backend/apps/oss/admin.py b/rsconcept/backend/apps/oss/admin.py index 78759597..288616b2 100644 --- a/rsconcept/backend/apps/oss/admin.py +++ b/rsconcept/backend/apps/oss/admin.py @@ -21,7 +21,7 @@ class ArgumentAdmin(admin.ModelAdmin): class SynthesisSubstitutionAdmin(admin.ModelAdmin): ''' Admin model: Substitutions as part of Synthesis operation. ''' ordering = ['operation'] - list_display = ['id', 'operation', 'original', 'substitution', 'transfer_term'] + list_display = ['id', 'operation', 'original', 'substitution'] search_fields = ['id', 'operation', 'original', 'substitution'] diff --git a/rsconcept/backend/apps/oss/migrations/0003_remove_operation_sync_text.py b/rsconcept/backend/apps/oss/migrations/0003_remove_operation_sync_text.py new file mode 100644 index 00000000..7db7a9c4 --- /dev/null +++ b/rsconcept/backend/apps/oss/migrations/0003_remove_operation_sync_text.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.7 on 2024-07-30 07:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('oss', '0002_inheritance'), + ] + + operations = [ + migrations.RemoveField( + model_name='operation', + name='sync_text', + ), + ] diff --git a/rsconcept/backend/apps/oss/migrations/0004_remove_substitution_transfer_term.py b/rsconcept/backend/apps/oss/migrations/0004_remove_substitution_transfer_term.py new file mode 100644 index 00000000..ddbaa49c --- /dev/null +++ b/rsconcept/backend/apps/oss/migrations/0004_remove_substitution_transfer_term.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0.7 on 2024-07-30 07:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('oss', '0003_remove_operation_sync_text'), + ] + + operations = [ + migrations.RemoveField( + model_name='substitution', + name='transfer_term', + ), + ] diff --git a/rsconcept/backend/apps/oss/models/Operation.py b/rsconcept/backend/apps/oss/models/Operation.py index 0185a4b8..9eb95531 100644 --- a/rsconcept/backend/apps/oss/models/Operation.py +++ b/rsconcept/backend/apps/oss/models/Operation.py @@ -2,7 +2,6 @@ from django.db.models import ( CASCADE, SET_NULL, - BooleanField, CharField, FloatField, ForeignKey, @@ -43,10 +42,6 @@ class Operation(Model): on_delete=SET_NULL, related_name='producer' ) - sync_text: BooleanField = BooleanField( - verbose_name='Синхронизация', - default=True - ) alias: CharField = CharField( verbose_name='Шифр', diff --git a/rsconcept/backend/apps/oss/models/OperationSchema.py b/rsconcept/backend/apps/oss/models/OperationSchema.py index b94e6963..ec6ff667 100644 --- a/rsconcept/backend/apps/oss/models/OperationSchema.py +++ b/rsconcept/backend/apps/oss/models/OperationSchema.py @@ -134,12 +134,8 @@ class OperationSchema: if len(subs) == 0: changed = True current.delete() - continue - if current.transfer_term != subs[0]['transfer_term']: - current.transfer_term = subs[0]['transfer_term'] - current.save() - continue - processed.append(subs[0]) + else: + processed.append(subs[0]) for sub in substitutes: if sub not in processed: @@ -147,8 +143,7 @@ class OperationSchema: Substitution.objects.create( operation=target, original=sub['original'], - substitution=sub['substitution'], - transfer_term=sub['transfer_term'] + substitution=sub['substitution'] ) if not changed: diff --git a/rsconcept/backend/apps/oss/models/Substitution.py b/rsconcept/backend/apps/oss/models/Substitution.py index 589041f6..6fdab8b5 100644 --- a/rsconcept/backend/apps/oss/models/Substitution.py +++ b/rsconcept/backend/apps/oss/models/Substitution.py @@ -1,5 +1,5 @@ ''' Models: Synthesis Substitution. ''' -from django.db.models import CASCADE, BooleanField, ForeignKey, Model +from django.db.models import CASCADE, ForeignKey, Model class Substitution(Model): @@ -22,10 +22,6 @@ class Substitution(Model): on_delete=CASCADE, related_name='as_substitute' ) - transfer_term: BooleanField = BooleanField( - verbose_name='Перенос термина', - default=False - ) class Meta: ''' Model metadata. ''' diff --git a/rsconcept/backend/apps/oss/serializers/basics.py b/rsconcept/backend/apps/oss/serializers/basics.py index f0ea8d3b..9d2328be 100644 --- a/rsconcept/backend/apps/oss/serializers/basics.py +++ b/rsconcept/backend/apps/oss/serializers/basics.py @@ -21,7 +21,6 @@ class SubstitutionExSerializer(serializers.Serializer): operation = serializers.IntegerField() original = serializers.IntegerField() substitution = serializers.IntegerField() - transfer_term = serializers.BooleanField() original_alias = serializers.CharField() original_term = serializers.CharField() substitution_alias = serializers.CharField() diff --git a/rsconcept/backend/apps/oss/serializers/data_access.py b/rsconcept/backend/apps/oss/serializers/data_access.py index 7da7973c..cf74bde1 100644 --- a/rsconcept/backend/apps/oss/serializers/data_access.py +++ b/rsconcept/backend/apps/oss/serializers/data_access.py @@ -34,7 +34,7 @@ class ArgumentSerializer(serializers.ModelSerializer): class OperationCreateSerializer(serializers.Serializer): ''' Serializer: Operation creation. ''' - class OperationData(serializers.ModelSerializer): + class OperationCreateData(serializers.ModelSerializer): ''' Serializer: Operation creation data. ''' alias = serializers.CharField() operation_type = serializers.ChoiceField(OperationType.choices) @@ -43,11 +43,11 @@ class OperationCreateSerializer(serializers.Serializer): ''' serializer metadata. ''' model = Operation fields = \ - 'alias', 'operation_type', 'title', 'sync_text', \ + 'alias', 'operation_type', 'title', \ 'comment', 'result', 'position_x', 'position_y' create_schema = serializers.BooleanField(default=False, required=False) - item_data = OperationData() + item_data = OperationCreateData() arguments = PKField(many=True, queryset=Operation.objects.all(), required=False) positions = serializers.ListField( @@ -58,15 +58,15 @@ class OperationCreateSerializer(serializers.Serializer): class OperationUpdateSerializer(serializers.Serializer): ''' Serializer: Operation creation. ''' - class OperationData(serializers.ModelSerializer): + class OperationUpdateData(serializers.ModelSerializer): ''' Serializer: Operation creation data. ''' class Meta: ''' serializer metadata. ''' model = Operation - fields = 'alias', 'title', 'sync_text', 'comment' + fields = 'alias', 'title', 'comment' target = PKField(many=False, queryset=Operation.objects.all()) - item_data = OperationData() + item_data = OperationUpdateData() arguments = PKField(many=True, queryset=Operation.objects.all(), required=False) substitutions = serializers.ListField( child=SubstitutionSerializerBase(), @@ -145,7 +145,6 @@ class SetOperationInputSerializer(serializers.Serializer): allow_null=True, default=None ) - sync_text = serializers.BooleanField(default=False, required=False) positions = serializers.ListField( child=OperationPositionSerializer(), default=[] @@ -196,7 +195,6 @@ class OperationSchemaSerializer(serializers.ModelSerializer): 'operation', 'original', 'substitution', - 'transfer_term', original_alias=F('original__alias'), original_term=F('original__term_resolved'), substitution_alias=F('substitution__alias'), diff --git a/rsconcept/backend/apps/oss/tests/s_models/t_Operation.py b/rsconcept/backend/apps/oss/tests/s_models/t_Operation.py index 213337ca..7e875482 100644 --- a/rsconcept/backend/apps/oss/tests/s_models/t_Operation.py +++ b/rsconcept/backend/apps/oss/tests/s_models/t_Operation.py @@ -29,7 +29,6 @@ class TestOperation(TestCase): self.assertEqual(self.operation.alias, 'KS1') self.assertEqual(self.operation.title, '') self.assertEqual(self.operation.comment, '') - self.assertEqual(self.operation.sync_text, True) self.assertEqual(self.operation.position_x, 0) self.assertEqual(self.operation.position_y, 0) @@ -50,15 +49,6 @@ class TestOperation(TestCase): self.assertEqual(self.operation.title, schema.model.title) self.assertEqual(self.operation.comment, schema.model.comment) - self.operation.sync_text = False - self.operation.save() - - schema.model.alias = 'KS3' - schema.save() - self.operation.refresh_from_db() - self.assertEqual(self.operation.result, schema.model) - self.assertNotEqual(self.operation.alias, schema.model.alias) - def test_sync_from_library_item(self): schema = LibraryItem.objects.create(alias=self.operation.alias, item_type=LibraryItemType.RSFORM) self.operation.result = schema diff --git a/rsconcept/backend/apps/oss/tests/s_models/t_Substitution.py b/rsconcept/backend/apps/oss/tests/s_models/t_Substitution.py index a81b5d49..1c5d0527 100644 --- a/rsconcept/backend/apps/oss/tests/s_models/t_Substitution.py +++ b/rsconcept/backend/apps/oss/tests/s_models/t_Substitution.py @@ -47,8 +47,7 @@ class TestSynthesisSubstitution(TestCase): self.substitution = Substitution.objects.create( operation=self.operation3, original=self.ks1x1, - substitution=self.ks2x1, - transfer_term=False + substitution=self.ks2x1 ) diff --git a/rsconcept/backend/apps/oss/tests/s_views/t_oss.py b/rsconcept/backend/apps/oss/tests/s_views/t_oss.py index 332e9483..ee78abfd 100644 --- a/rsconcept/backend/apps/oss/tests/s_views/t_oss.py +++ b/rsconcept/backend/apps/oss/tests/s_views/t_oss.py @@ -44,8 +44,7 @@ class TestOssViewset(EndpointTester): self.owned.set_arguments(self.operation3, [self.operation1, self.operation2]) self.owned.set_substitutions(self.operation3, [{ 'original': self.ks1x1, - 'substitution': self.ks2x1, - 'transfer_term': False + 'substitution': self.ks2x1 }]) @decl_endpoint('/api/oss/{item}/details', method='get') @@ -71,7 +70,6 @@ class TestOssViewset(EndpointTester): self.assertEqual(sub['operation'], self.operation3.pk) self.assertEqual(sub['original'], self.ks1x1.pk) self.assertEqual(sub['substitution'], self.ks2x1.pk) - self.assertEqual(sub['transfer_term'], False) self.assertEqual(sub['original_alias'], self.ks1x1.alias) self.assertEqual(sub['original_term'], self.ks1x1.term_resolved) self.assertEqual(sub['substitution_alias'], self.ks2x1.alias) @@ -134,7 +132,6 @@ class TestOssViewset(EndpointTester): 'alias': 'Test3', 'title': 'Test title', 'comment': 'Тест кириллицы', - 'sync_text': False, 'position_x': 1, 'position_y': 1, }, @@ -159,7 +156,6 @@ class TestOssViewset(EndpointTester): self.assertEqual(new_operation['comment'], data['item_data']['comment']) self.assertEqual(new_operation['position_x'], data['item_data']['position_x']) self.assertEqual(new_operation['position_y'], data['item_data']['position_y']) - self.assertEqual(new_operation['sync_text'], data['item_data']['sync_text']) self.assertEqual(new_operation['result'], None) self.operation1.refresh_from_db() self.assertEqual(self.operation1.position_x, data['positions'][0]['position_x']) @@ -274,13 +270,11 @@ class TestOssViewset(EndpointTester): self.operation1.result = None self.operation1.comment = 'TestComment' self.operation1.title = 'TestTitle' - self.operation1.sync_text = False self.operation1.save() response = self.executeOK(data=data) self.operation1.refresh_from_db() new_schema = response.data['new_schema'] - self.assertEqual(self.operation1.sync_text, True) self.assertEqual(new_schema['id'], self.operation1.result.pk) self.assertEqual(new_schema['alias'], self.operation1.alias) self.assertEqual(new_schema['title'], self.operation1.title) @@ -295,7 +289,6 @@ class TestOssViewset(EndpointTester): self.executeBadData(item=self.owned_id) data = { - 'sync_text': True, 'positions': [] } self.executeBadData(data=data) @@ -312,7 +305,6 @@ class TestOssViewset(EndpointTester): self.login() response = self.executeOK(data=data) self.operation1.refresh_from_db() - self.assertEqual(self.operation1.sync_text, True) self.assertEqual(self.operation1.result, None) data['input'] = self.ks1.model.pk @@ -322,7 +314,6 @@ class TestOssViewset(EndpointTester): self.ks1.save() response = self.executeOK(data=data) self.operation1.refresh_from_db() - self.assertEqual(self.operation1.sync_text, True) self.assertEqual(self.operation1.result, self.ks1.model) self.assertEqual(self.operation1.alias, self.ks1.model.alias) self.assertEqual(self.operation1.title, self.ks1.model.title) @@ -334,14 +325,12 @@ class TestOssViewset(EndpointTester): self.operation2.result = None data = { - 'sync_text': True, 'positions': [], 'target': self.operation1.pk, 'input': self.ks2.model.pk } response = self.executeOK(data=data, item=self.owned_id) self.operation2.refresh_from_db() - self.assertEqual(self.operation2.sync_text, True) self.assertEqual(self.operation2.result, self.ks2.model) @decl_endpoint('/api/oss/{item}/update-operation', method='patch') @@ -357,16 +346,14 @@ class TestOssViewset(EndpointTester): 'item_data': { 'alias': 'Test3 mod', 'title': 'Test title mod', - 'comment': 'Comment mod', - 'sync_text': True + 'comment': 'Comment mod' }, 'positions': [], 'arguments': [self.operation1.pk, self.operation2.pk], 'substitutions': [ { 'original': self.ks1x1.pk, - 'substitution': ks3x1.pk, - 'transfer_term': False + 'substitution': ks3x1.pk } ] } @@ -381,7 +368,6 @@ class TestOssViewset(EndpointTester): self.login() response = self.executeOK(data=data) self.operation3.refresh_from_db() - self.assertEqual(self.operation3.sync_text, data['item_data']['sync_text']) self.assertEqual(self.operation3.alias, data['item_data']['alias']) self.assertEqual(self.operation3.title, data['item_data']['title']) self.assertEqual(self.operation3.comment, data['item_data']['comment']) @@ -389,7 +375,6 @@ class TestOssViewset(EndpointTester): sub = self.operation3.getSubstitutions()[0] self.assertEqual(sub.original.pk, data['substitutions'][0]['original']) self.assertEqual(sub.substitution.pk, data['substitutions'][0]['substitution']) - self.assertEqual(sub.transfer_term, data['substitutions'][0]['transfer_term']) @decl_endpoint('/api/oss/{item}/update-operation', method='patch') def test_update_operation_sync(self): @@ -401,15 +386,13 @@ class TestOssViewset(EndpointTester): 'item_data': { 'alias': 'Test3 mod', 'title': 'Test title mod', - 'comment': 'Comment mod', - 'sync_text': True + 'comment': 'Comment mod' }, 'positions': [], } response = self.executeOK(data=data) self.operation1.refresh_from_db() - self.assertEqual(self.operation1.sync_text, data['item_data']['sync_text']) self.assertEqual(self.operation1.alias, data['item_data']['alias']) self.assertEqual(self.operation1.title, data['item_data']['title']) self.assertEqual(self.operation1.comment, data['item_data']['comment']) diff --git a/rsconcept/backend/apps/oss/views/oss.py b/rsconcept/backend/apps/oss/views/oss.py index 44aed8d3..40a52495 100644 --- a/rsconcept/backend/apps/oss/views/oss.py +++ b/rsconcept/backend/apps/oss/views/oss.py @@ -209,7 +209,6 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev ) Editor.set(schema, oss.model.editors()) operation.result = schema - operation.sync_text = True operation.save() oss.refresh_from_db() @@ -247,8 +246,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev with transaction.atomic(): oss.update_positions(serializer.validated_data['positions']) operation.result = result - operation.sync_text = serializer.validated_data['sync_text'] - if result is not None and operation.sync_text: + if result is not None: operation.title = result.title operation.comment = result.comment operation.alias = result.alias @@ -289,10 +287,9 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev operation.alias = serializer.validated_data['item_data']['alias'] operation.title = serializer.validated_data['item_data']['title'] operation.comment = serializer.validated_data['item_data']['comment'] - operation.sync_text = serializer.validated_data['item_data']['sync_text'] operation.save() - if operation.sync_text and operation.result is not None: + if operation.result is not None: can_edit = permissions.can_edit_item(request.user, operation.result) if can_edit: operation.result.alias = operation.alias diff --git a/rsconcept/backend/apps/rsform/models/RSForm.py b/rsconcept/backend/apps/rsform/models/RSForm.py index 06531b90..8718f724 100644 --- a/rsconcept/backend/apps/rsform/models/RSForm.py +++ b/rsconcept/backend/apps/rsform/models/RSForm.py @@ -241,18 +241,12 @@ class RSForm: def substitute( self, original: Constituenta, - substitution: Constituenta, - transfer_term: bool + substitution: Constituenta ): ''' Execute constituenta substitution. ''' assert original.pk != substitution.pk mapping = {original.alias: substitution.alias} self.apply_mapping(mapping) - if transfer_term: - substitution.term_raw = original.term_raw - substitution.term_forms = original.term_forms - substitution.term_resolved = original.term_resolved - substitution.save() original.delete() self.on_term_change([substitution.id]) diff --git a/rsconcept/backend/apps/rsform/serializers/data_access.py b/rsconcept/backend/apps/rsform/serializers/data_access.py index e8c27a9b..4791c0bb 100644 --- a/rsconcept/backend/apps/rsform/serializers/data_access.py +++ b/rsconcept/backend/apps/rsform/serializers/data_access.py @@ -274,7 +274,6 @@ class SubstitutionSerializerBase(serializers.Serializer): ''' Serializer: Basic substitution. ''' original = PKField(many=False, queryset=Constituenta.objects.all()) substitution = PKField(many=False, queryset=Constituenta.objects.all()) - transfer_term = serializers.BooleanField(required=False, default=False) class CstSubstituteSerializer(serializers.Serializer): diff --git a/rsconcept/backend/apps/rsform/tests/s_views/t_operations.py b/rsconcept/backend/apps/rsform/tests/s_views/t_operations.py index dc0e3eb9..8188bcc5 100644 --- a/rsconcept/backend/apps/rsform/tests/s_views/t_operations.py +++ b/rsconcept/backend/apps/rsform/tests/s_views/t_operations.py @@ -57,13 +57,11 @@ class TestInlineSynthesis(EndpointTester): 'substitutions': [ { 'original': ks1_x1.pk, - 'substitution': ks2_s1.pk, - 'transfer_term': False + 'substitution': ks2_s1.pk }, { 'original': ks2_x1.pk, - 'substitution': ks1_s1.pk, - 'transfer_term': True + 'substitution': ks1_s1.pk } ] } diff --git a/rsconcept/backend/apps/rsform/tests/s_views/t_rsforms.py b/rsconcept/backend/apps/rsform/tests/s_views/t_rsforms.py index f8f76fc5..054e1d43 100644 --- a/rsconcept/backend/apps/rsform/tests/s_views/t_rsforms.py +++ b/rsconcept/backend/apps/rsform/tests/s_views/t_rsforms.py @@ -272,43 +272,6 @@ class TestRSFormViewset(EndpointTester): self.assertEqual(x1.cst_type, CstType.TERM) - @decl_endpoint('/api/rsforms/{item}/substitute', method='patch') - def test_substitute_single(self): - x1 = self.owned.insert_new( - alias='X1', - term_raw='Test1', - term_resolved='Test1', - term_forms=[{'text': 'form1', 'tags': 'sing,datv'}] - ) - x2 = self.owned.insert_new( - alias='X2', - term_raw='Test2' - ) - unowned = self.unowned.insert_new('X2') - - data = {'substitutions': [{'original': x1.pk, 'substitution': unowned.pk, 'transfer_term': True}]} - self.executeForbidden(data=data, item=self.unowned_id) - self.executeBadData(data=data, item=self.owned_id) - - data = {'substitutions': [{'original': unowned.pk, 'substitution': x1.pk, 'transfer_term': True}]} - self.executeBadData(data=data, item=self.owned_id) - - data = {'substitutions': [{'original': x1.pk, 'substitution': x1.pk, 'transfer_term': True}]} - self.executeBadData(data=data, item=self.owned_id) - - d1 = self.owned.insert_new( - alias='D1', - term_raw='@{X2|sing,datv}', - definition_formal='X1' - ) - data = {'substitutions': [{'original': x1.pk, 'substitution': x2.pk, 'transfer_term': True}]} - response = self.executeOK(data=data, item=self.owned_id) - d1.refresh_from_db() - x2.refresh_from_db() - self.assertEqual(x2.term_raw, 'Test1') - self.assertEqual(d1.term_resolved, 'form1') - self.assertEqual(d1.definition_formal, 'X2') - @decl_endpoint('/api/rsforms/{item}/substitute', method='patch') def test_substitute_multiple(self): self.set_params(item=self.owned_id) @@ -327,13 +290,11 @@ class TestRSFormViewset(EndpointTester): data = {'substitutions': [ { 'original': x1.pk, - 'substitution': d1.pk, - 'transfer_term': True + 'substitution': d1.pk }, { 'original': x1.pk, - 'substitution': d2.pk, - 'transfer_term': True + 'substitution': d2.pk } ]} self.executeBadData(data=data) @@ -341,13 +302,11 @@ class TestRSFormViewset(EndpointTester): data = {'substitutions': [ { 'original': x1.pk, - 'substitution': d1.pk, - 'transfer_term': True + 'substitution': d1.pk }, { 'original': x2.pk, - 'substitution': d2.pk, - 'transfer_term': True + 'substitution': d2.pk } ]} response = self.executeOK(data=data, item=self.owned_id) diff --git a/rsconcept/backend/apps/rsform/views/operations.py b/rsconcept/backend/apps/rsform/views/operations.py index 5b2a01a4..6fa68d8a 100644 --- a/rsconcept/backend/apps/rsform/views/operations.py +++ b/rsconcept/backend/apps/rsform/views/operations.py @@ -41,7 +41,7 @@ def inline_synthesis(request: Request): else: index = next(i for (i, cst) in enumerate(items) if cst == replacement) replacement = new_items[index] - receiver.substitute(original, replacement, substitution['transfer_term']) + receiver.substitute(original, replacement) receiver.restore_order() return Response( diff --git a/rsconcept/backend/apps/rsform/views/rsforms.py b/rsconcept/backend/apps/rsform/views/rsforms.py index 0c7908f8..0666256a 100644 --- a/rsconcept/backend/apps/rsform/views/rsforms.py +++ b/rsconcept/backend/apps/rsform/views/rsforms.py @@ -174,7 +174,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr ) @extend_schema( - summary='substitute constituenta', + summary='execute substitutions', tags=['RSForm'], request=s.CstSubstituteSerializer, responses={ @@ -198,7 +198,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr for substitution in serializer.validated_data['substitutions']: original = cast(m.Constituenta, substitution['original']) replacement = cast(m.Constituenta, substitution['substitution']) - m.RSForm(schema).substitute(original, replacement, substitution['transfer_term']) + m.RSForm(schema).substitute(original, replacement) schema.refresh_from_db() return Response( diff --git a/rsconcept/frontend/src/components/Icons.tsx b/rsconcept/frontend/src/components/Icons.tsx index b7da3088..6dac71f8 100644 --- a/rsconcept/frontend/src/components/Icons.tsx +++ b/rsconcept/frontend/src/components/Icons.tsx @@ -89,8 +89,6 @@ export { BiHelpCircle as IconStatusUnknown } from 'react-icons/bi'; export { BiPauseCircle as IconStatusIncalculable } from 'react-icons/bi'; export { LuPower as IconKeepAliasOn } from 'react-icons/lu'; export { LuPowerOff as IconKeepAliasOff } from 'react-icons/lu'; -export { LuFlag as IconKeepTermOn } from 'react-icons/lu'; -export { LuFlagOff as IconKeepTermOff } from 'react-icons/lu'; // ===== Domain actions ===== export { BiUpvote as IconMoveUp } from 'react-icons/bi'; diff --git a/rsconcept/frontend/src/components/select/PickInlineSubstitutions.tsx b/rsconcept/frontend/src/components/select/PickInlineSubstitutions.tsx deleted file mode 100644 index fcf9c5dc..00000000 --- a/rsconcept/frontend/src/components/select/PickInlineSubstitutions.tsx +++ /dev/null @@ -1,273 +0,0 @@ -'use client'; - -import { useCallback, useMemo, useState } from 'react'; - -import BadgeConstituenta from '@/components/info/BadgeConstituenta'; -import SelectConstituenta from '@/components/select/SelectConstituenta'; -import DataTable, { createColumnHelper } from '@/components/ui/DataTable'; -import Label from '@/components/ui/Label'; -import MiniButton from '@/components/ui/MiniButton'; -import { useConceptOptions } from '@/context/ConceptOptionsContext'; -import { IBinarySubstitution, IConstituenta, IRSForm } from '@/models/rsform'; -import { describeConstituenta } from '@/utils/labels'; - -import { - IconKeepAliasOff, - IconKeepAliasOn, - IconKeepTermOff, - IconKeepTermOn, - IconPageFirst, - IconPageLast, - IconPageLeft, - IconPageRight, - IconRemove, - IconReplace -} from '../Icons'; -import NoData from '../ui/NoData'; - -interface PickInlineSubstitutionsProps { - prefixID: string; - rows?: number; - - schema1?: IRSForm; - schema2?: IRSForm; - filter1?: (cst: IConstituenta) => boolean; - filter2?: (cst: IConstituenta) => boolean; - - items: IBinarySubstitution[]; - setItems: React.Dispatch>; -} - -function SubstitutionIcon({ item }: { item: IBinarySubstitution }) { - if (item.deleteRight) { - if (item.takeLeftTerm) { - return ; - } else { - return ; - } - } else { - if (item.takeLeftTerm) { - return ; - } else { - return ; - } - } -} - -const columnHelper = createColumnHelper(); - -function PickInlineSubstitutions({ - items, - schema1, - schema2, - filter1, - filter2, - rows, - setItems, - prefixID -}: PickInlineSubstitutionsProps) { - const { colors } = useConceptOptions(); - - const [leftCst, setLeftCst] = useState(undefined); - const [rightCst, setRightCst] = useState(undefined); - const [deleteRight, setDeleteRight] = useState(true); - const [takeLeftTerm, setTakeLeftTerm] = useState(true); - - const toggleDelete = () => setDeleteRight(prev => !prev); - const toggleTerm = () => setTakeLeftTerm(prev => !prev); - - function addSubstitution() { - if (!leftCst || !rightCst) { - return; - } - const newSubstitution: IBinarySubstitution = { - leftCst: leftCst, - rightCst: rightCst, - deleteRight: deleteRight, - takeLeftTerm: takeLeftTerm - }; - setItems([ - newSubstitution, - ...items.filter( - item => - (!item.deleteRight && item.leftCst.id !== leftCst.id) || - (item.deleteRight && item.rightCst.id !== rightCst.id) - ) - ]); - } - - const handleDeleteRow = useCallback( - (row: number) => { - setItems(prev => { - const newItems: IBinarySubstitution[] = []; - prev.forEach((item, index) => { - if (index !== row) { - newItems.push(item); - } - }); - return newItems; - }); - }, - [setItems] - ); - - const columns = useMemo( - () => [ - columnHelper.accessor(item => describeConstituenta(item.leftCst), { - id: 'left_text', - header: 'Описание', - size: 1000, - cell: props =>
{props.getValue()}
- }), - columnHelper.accessor(item => item.leftCst.alias, { - id: 'left_alias', - header: () => Имя, - size: 65, - cell: props => ( - - ) - }), - columnHelper.display({ - id: 'status', - header: '', - size: 40, - cell: props => - }), - columnHelper.accessor(item => item.rightCst.alias, { - id: 'right_alias', - header: () => Имя, - size: 65, - cell: props => ( - - ) - }), - columnHelper.accessor(item => describeConstituenta(item.rightCst), { - id: 'right_text', - header: 'Описание', - minSize: 1000, - cell: props =>
{props.getValue()}
- }), - columnHelper.display({ - id: 'actions', - cell: props => ( - } - onClick={() => handleDeleteRow(props.row.index)} - /> - ) - }) - ], - [handleDeleteRow, colors, prefixID] - ); - - return ( -
-
-
-
-
- !filter1 || filter1(cst))} - value={leftCst} - onSelectValue={setLeftCst} - /> -
- - } - disabled={!leftCst || !rightCst || leftCst === rightCst} - onClick={addSubstitution} - /> - -
-
-
- !filter2 || filter2(cst))} - value={rightCst} - onSelectValue={setRightCst} - /> -
-
- - -

Список пуст

-

Добавьте отождествление

- - } - /> -
- ); -} - -export default PickInlineSubstitutions; diff --git a/rsconcept/frontend/src/components/select/PickSubstitutions.tsx b/rsconcept/frontend/src/components/select/PickSubstitutions.tsx index a0603001..76e73d1b 100644 --- a/rsconcept/frontend/src/components/select/PickSubstitutions.tsx +++ b/rsconcept/frontend/src/components/select/PickSubstitutions.tsx @@ -7,109 +7,96 @@ import SelectConstituenta from '@/components/select/SelectConstituenta'; import DataTable, { createColumnHelper } from '@/components/ui/DataTable'; import MiniButton from '@/components/ui/MiniButton'; import { useConceptOptions } from '@/context/ConceptOptionsContext'; -import { LibraryItemID } from '@/models/library'; -import { ICstSubstitute, IMultiSubstitution, IOperation } from '@/models/oss'; +import { ILibraryItem } from '@/models/library'; +import { ICstSubstitute, IMultiSubstitution } from '@/models/oss'; import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform'; -import { - IconKeepAliasOff, - IconKeepAliasOn, - IconKeepTermOff, - IconKeepTermOn, - IconPageLast, - IconPageRight, - IconRemove, - IconReplace -} from '../Icons'; +import { IconPageLeft, IconPageRight, IconRemove, IconReplace } from '../Icons'; import NoData from '../ui/NoData'; -import SelectOperation from './SelectOperation'; - -function SubstitutionIcon({ item, className }: { item: IMultiSubstitution; className?: string }) { - if (!item.transfer_term) { - return ; - } else { - return ; - } -} +import SelectLibraryItem from './SelectLibraryItem'; interface PickSubstitutionsProps { - prefixID: string; - rows?: number; - - operations: IOperation[]; - getSchema: (id: LibraryItemID) => IRSForm | undefined; - getConstituenta: (id: ConstituentaID) => IConstituenta | undefined; - getSchemaByCst: (id: ConstituentaID) => IRSForm | undefined; substitutions: ICstSubstitute[]; setSubstitutions: React.Dispatch>; + + prefixID: string; + rows?: number; + allowSelfSubstitution?: boolean; + + schemas: IRSForm[]; + filter?: (cst: IConstituenta) => boolean; } const columnHelper = createColumnHelper(); function PickSubstitutions({ + substitutions, + setSubstitutions, prefixID, rows, - operations, - getSchema, - getConstituenta, - getSchemaByCst, - substitutions, - setSubstitutions + schemas, + filter, + allowSelfSubstitution }: PickSubstitutionsProps) { const { colors } = useConceptOptions(); - const [leftArgument, setLeftArgument] = useState(undefined); - const [rightArgument, setRightArgument] = useState(undefined); - const leftSchema = useMemo( - () => (leftArgument?.result ? getSchema(leftArgument.result) : undefined), - [leftArgument, getSchema] + const [leftArgument, setLeftArgument] = useState( + schemas.length === 1 ? schemas[0] : undefined + ); + const [rightArgument, setRightArgument] = useState( + schemas.length === 1 && allowSelfSubstitution ? schemas[0] : undefined ); - const rightSchema = useMemo( - () => (rightArgument?.result ? getSchema(rightArgument.result) : undefined), - [rightArgument, getSchema] - ); const [leftCst, setLeftCst] = useState(undefined); const [rightCst, setRightCst] = useState(undefined); const [deleteRight, setDeleteRight] = useState(true); - const [takeLeftTerm, setTakeLeftTerm] = useState(true); + const toggleDelete = () => setDeleteRight(prev => !prev); - const operationByConstituenta = useCallback( - (cst: ConstituentaID): IOperation | undefined => { - const schema = getSchemaByCst(cst); - if (!schema) { - return undefined; + const getSchemaByCst = useCallback( + (id: ConstituentaID): IRSForm | undefined => { + for (const schema of schemas) { + const cst = schema.cstByID.get(id); + if (cst) { + return schema; + } } - const cstOperations = operations.filter(item => item.result === schema.id); - return cstOperations.length === 1 ? cstOperations[0] : undefined; + return undefined; }, - [getSchemaByCst, operations] + [schemas] + ); + + const getConstituenta = useCallback( + (id: ConstituentaID): IConstituenta | undefined => { + for (const schema of schemas) { + const cst = schema.cstByID.get(id); + if (cst) { + return cst; + } + } + return undefined; + }, + [schemas] ); const substitutionData: IMultiSubstitution[] = useMemo( () => substitutions.map(item => ({ - original_operation: operationByConstituenta(item.original), + original_source: getSchemaByCst(item.original), original: getConstituenta(item.original), substitution: getConstituenta(item.substitution), - substitution_operation: operationByConstituenta(item.substitution), - transfer_term: item.transfer_term + substitution_source: getSchemaByCst(item.substitution) })), - [getConstituenta, operationByConstituenta, substitutions] + [getConstituenta, getSchemaByCst, substitutions] ); - const toggleDelete = () => setDeleteRight(prev => !prev); - const toggleTerm = () => setTakeLeftTerm(prev => !prev); - function addSubstitution() { if (!leftCst || !rightCst) { return; } const newSubstitution: ICstSubstitute = { original: deleteRight ? rightCst.id : leftCst.id, - substitution: deleteRight ? leftCst.id : rightCst.id, - transfer_term: deleteRight != takeLeftTerm + substitution: deleteRight ? leftCst.id : rightCst.id }; setSubstitutions(prev => [...prev, newSubstitution]); setLeftCst(undefined); @@ -133,11 +120,11 @@ function PickSubstitutions({ const columns = useMemo( () => [ - columnHelper.accessor(item => item.substitution_operation?.alias ?? 'N/A', { + columnHelper.accessor(item => item.substitution_source?.alias ?? 'N/A', { id: 'left_schema', header: 'Операция', size: 100, - cell: props =>
{props.getValue()}
+ cell: props =>
{props.getValue()}
}), columnHelper.accessor(item => item.substitution?.alias ?? 'N/A', { id: 'left_alias', @@ -154,7 +141,7 @@ function PickSubstitutions({ id: 'status', header: '', size: 40, - cell: props => + cell: () => }), columnHelper.accessor(item => item.original?.alias ?? 'N/A', { id: 'right_alias', @@ -167,7 +154,7 @@ function PickSubstitutions({ 'N/A' ) }), - columnHelper.accessor(item => item.original_operation?.alias ?? 'N/A', { + columnHelper.accessor(item => item.original_source?.alias ?? 'N/A', { id: 'right_schema', header: 'Операция', size: 100, @@ -194,96 +181,60 @@ function PickSubstitutions({
-
- - ) : ( - - ) - } - /> - - ) : ( - - ) - } - /> -
- item.id !== rightArgument?.id)} + items={allowSelfSubstitution ? schemas : schemas.filter(item => item.id !== rightArgument?.id)} value={leftArgument} onSelectValue={setLeftArgument} /> !substitutions.find(item => item.original === cst.id))} + items={(leftArgument as IRSForm)?.items.filter( + cst => !substitutions.find(item => item.original === cst.id) && (!filter || filter(cst)) + )} value={leftCst} onSelectValue={setLeftCst} />
+
+ + ) : ( + + ) + } + /> - } - disabled={!leftCst || !rightCst || leftCst === rightCst} - onClick={addSubstitution} - /> + } + disabled={!leftCst || !rightCst || leftCst === rightCst} + onClick={addSubstitution} + /> +
-
- - ) : ( - - ) - } - /> - - ) : ( - - ) - } - /> -
- item.id !== leftArgument?.id)} + items={allowSelfSubstitution ? schemas : schemas.filter(item => item.id !== leftArgument?.id)} value={rightArgument} onSelectValue={setRightArgument} /> !substitutions.find(item => item.original === cst.id))} + items={(rightArgument as IRSForm)?.items.filter( + cst => !substitutions.find(item => item.original === cst.id) && (!filter || filter(cst)) + )} value={rightCst} onSelectValue={setRightCst} /> diff --git a/rsconcept/frontend/src/components/select/SelectLibraryItem.tsx b/rsconcept/frontend/src/components/select/SelectLibraryItem.tsx new file mode 100644 index 00000000..afc43229 --- /dev/null +++ b/rsconcept/frontend/src/components/select/SelectLibraryItem.tsx @@ -0,0 +1,60 @@ +'use client'; + +import clsx from 'clsx'; +import { useCallback, useMemo } from 'react'; + +import { ILibraryItem, LibraryItemID } from '@/models/library'; +import { matchLibraryItem } from '@/models/libraryAPI'; + +import { CProps } from '../props'; +import SelectSingle from '../ui/SelectSingle'; + +interface SelectLibraryItemProps extends CProps.Styling { + items?: ILibraryItem[]; + value?: ILibraryItem; + onSelectValue: (newValue?: ILibraryItem) => void; + + placeholder?: string; + noBorder?: boolean; +} + +function SelectLibraryItem({ + className, + items, + value, + onSelectValue, + placeholder = 'Выберите схему', + ...restProps +}: SelectLibraryItemProps) { + const options = useMemo(() => { + return ( + items?.map(cst => ({ + value: cst.id, + label: `${cst.alias}: ${cst.title}` + })) ?? [] + ); + }, [items]); + + const filter = useCallback( + (option: { value: LibraryItemID | undefined; label: string }, inputValue: string) => { + const item = items?.find(item => item.id === option.value); + return !item ? false : matchLibraryItem(item, inputValue); + }, + [items] + ); + + return ( + onSelectValue(items?.find(cst => cst.id === data?.value))} + // @ts-expect-error: TODO: use type definitions from react-select in filter object + filterOption={filter} + placeholder={placeholder} + {...restProps} + /> + ); +} + +export default SelectLibraryItem; diff --git a/rsconcept/frontend/src/dialogs/DlgChangeInputSchema.tsx b/rsconcept/frontend/src/dialogs/DlgChangeInputSchema.tsx index 44069114..62e7e407 100644 --- a/rsconcept/frontend/src/dialogs/DlgChangeInputSchema.tsx +++ b/rsconcept/frontend/src/dialogs/DlgChangeInputSchema.tsx @@ -5,7 +5,6 @@ import { useCallback, useMemo, useState } from 'react'; import { IconReset } from '@/components/Icons'; import PickSchema from '@/components/select/PickSchema'; -import Checkbox from '@/components/ui/Checkbox'; import Label from '@/components/ui/Label'; import MiniButton from '@/components/ui/MiniButton'; import Modal, { ModalProps } from '@/components/ui/Modal'; @@ -15,12 +14,11 @@ import { IOperation, IOperationSchema } from '@/models/oss'; interface DlgChangeInputSchemaProps extends Pick { oss: IOperationSchema; target: IOperation; - onSubmit: (newSchema: LibraryItemID | undefined, syncText: boolean) => void; + onSubmit: (newSchema: LibraryItemID | undefined) => void; } function DlgChangeInputSchema({ oss, hideWindow, target, onSubmit }: DlgChangeInputSchemaProps) { const [selected, setSelected] = useState(target.result ?? undefined); - const [syncText, setSyncText] = useState(target.sync_text); const baseFilter = useCallback( (item: ILibraryItem) => !oss.schemas.includes(item.id) || item.id === selected || item.id === target.result, @@ -34,7 +32,7 @@ function DlgChangeInputSchema({ oss, hideWindow, target, onSubmit }: DlgChangeIn }, []); function handleSubmit() { - onSubmit(selected, syncText); + onSubmit(selected); } return ( @@ -66,12 +64,6 @@ function DlgChangeInputSchema({ oss, hideWindow, target, onSubmit }: DlgChangeIn rows={8} baseFilter={baseFilter} /> - ); } diff --git a/rsconcept/frontend/src/dialogs/DlgCreateOperation/DlgCreateOperation.tsx b/rsconcept/frontend/src/dialogs/DlgCreateOperation/DlgCreateOperation.tsx index 994de931..6fb90496 100644 --- a/rsconcept/frontend/src/dialogs/DlgCreateOperation/DlgCreateOperation.tsx +++ b/rsconcept/frontend/src/dialogs/DlgCreateOperation/DlgCreateOperation.tsx @@ -38,7 +38,6 @@ function DlgCreateOperation({ hideWindow, oss, onCreate }: DlgCreateOperationPro const [comment, setComment] = useState(''); const [inputs, setInputs] = useState([]); const [attachedID, setAttachedID] = useState(undefined); - const [syncText, setSyncText] = useState(true); const [createSchema, setCreateSchema] = useState(false); const isValid = useMemo( @@ -65,7 +64,6 @@ function DlgCreateOperation({ hideWindow, oss, onCreate }: DlgCreateOperationPro alias: alias, title: title, comment: comment, - sync_text: activeTab === TabID.INPUT ? syncText : true, operation_type: activeTab === TabID.INPUT ? OperationType.INPUT : OperationType.SYNTHESIS, result: activeTab === TabID.INPUT ? attachedID ?? null : null }, @@ -89,14 +87,12 @@ function DlgCreateOperation({ hideWindow, oss, onCreate }: DlgCreateOperationPro setTitle={setTitle} attachedID={attachedID} setAttachedID={setAttachedID} - syncText={syncText} - setSyncText={setSyncText} createSchema={createSchema} setCreateSchema={setCreateSchema} /> ), - [alias, comment, title, attachedID, syncText, oss, createSchema] + [alias, comment, title, attachedID, oss, createSchema] ); const synthesisPanel = useMemo( diff --git a/rsconcept/frontend/src/dialogs/DlgCreateOperation/TabInputOperation.tsx b/rsconcept/frontend/src/dialogs/DlgCreateOperation/TabInputOperation.tsx index c23fd2b2..2edf7691 100644 --- a/rsconcept/frontend/src/dialogs/DlgCreateOperation/TabInputOperation.tsx +++ b/rsconcept/frontend/src/dialogs/DlgCreateOperation/TabInputOperation.tsx @@ -5,7 +5,6 @@ import { useCallback, useEffect } from 'react'; import { IconReset } from '@/components/Icons'; import PickSchema from '@/components/select/PickSchema'; import Checkbox from '@/components/ui/Checkbox'; -import FlexColumn from '@/components/ui/FlexColumn'; import Label from '@/components/ui/Label'; import MiniButton from '@/components/ui/MiniButton'; import TextArea from '@/components/ui/TextArea'; @@ -25,8 +24,6 @@ interface TabInputOperationProps { setComment: React.Dispatch>; attachedID: LibraryItemID | undefined; setAttachedID: React.Dispatch>; - syncText: boolean; - setSyncText: React.Dispatch>; createSchema: boolean; setCreateSchema: React.Dispatch>; } @@ -41,8 +38,6 @@ function TabInputOperation({ setComment, attachedID, setAttachedID, - syncText, - setSyncText, createSchema, setCreateSchema }: TabInputOperationProps) { @@ -51,9 +46,8 @@ function TabInputOperation({ useEffect(() => { if (createSchema) { setAttachedID(undefined); - setSyncText(true); } - }, [createSchema, setAttachedID, setSyncText]); + }, [createSchema, setAttachedID]); return ( @@ -62,27 +56,19 @@ function TabInputOperation({ label='Полное название' value={title} onChange={event => setTitle(event.target.value)} - disabled={syncText && attachedID !== undefined} + disabled={attachedID !== undefined} />
- - setAlias(event.target.value)} - disabled={syncText && attachedID !== undefined} - /> - - + setAlias(event.target.value)} + disabled={attachedID !== undefined} + />