Compare commits
No commits in common. "f390762c7d433539743ba8386fbf076cb477b769" and "3b036f2c9d8b3d19b64cf70caada502f3e52858e" have entirely different histories.
f390762c7d
...
3b036f2c9d
|
@ -59,7 +59,6 @@ This readme file is used mostly to document project dependencies and conventions
|
|||
- postcss
|
||||
- autoprefixer
|
||||
- eslint-plugin-simple-import-sort
|
||||
- eslint-plugin-react-hooks
|
||||
- eslint-plugin-tsdoc
|
||||
- vite
|
||||
- jest
|
||||
|
|
|
@ -267,51 +267,7 @@ class OperationSchema:
|
|||
self.save(update_fields=['time_update'])
|
||||
return True
|
||||
|
||||
def relocate_down(self, source: RSForm, destination: RSForm, items: list[Constituenta]):
|
||||
''' Move list of constituents to specific schema inheritor. '''
|
||||
self.cache.ensure_loaded()
|
||||
self.cache.insert_schema(source)
|
||||
self.cache.insert_schema(destination)
|
||||
operation = self.cache.get_operation(destination.model.pk)
|
||||
|
||||
self._undo_substitutions_cst(items, operation, destination)
|
||||
|
||||
inheritance_to_delete = [item for item in self.cache.inheritance[operation.pk] if item.parent_id in items]
|
||||
for item in inheritance_to_delete:
|
||||
self.cache.remove_inheritance(item)
|
||||
Inheritance.objects.filter(operation_id=operation.pk, parent__in=items).delete()
|
||||
|
||||
def relocate_up(self, source: RSForm, destination: RSForm, items: list[Constituenta]) -> list[Constituenta]:
|
||||
''' Move list of constituents to specific schema upstream. '''
|
||||
self.cache.ensure_loaded()
|
||||
self.cache.insert_schema(source)
|
||||
self.cache.insert_schema(destination)
|
||||
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
alias_mapping: dict[str, str] = {}
|
||||
for item in self.cache.inheritance[operation.pk]:
|
||||
if item.parent_id in destination.cache.by_id:
|
||||
source_cst = source.cache.by_id[item.child_id]
|
||||
destination_cst = destination.cache.by_id[item.parent_id]
|
||||
alias_mapping[source_cst.alias] = destination_cst.alias
|
||||
|
||||
new_items = destination.insert_copy(items, initial_mapping=alias_mapping)
|
||||
for index, cst in enumerate(new_items):
|
||||
new_inheritance = Inheritance.objects.create(
|
||||
operation=operation,
|
||||
child=items[index],
|
||||
parent=cst
|
||||
)
|
||||
self.cache.insert_inheritance(new_inheritance)
|
||||
self.after_create_cst(destination, new_items, exclude=[operation.pk])
|
||||
|
||||
return new_items
|
||||
|
||||
def after_create_cst(
|
||||
self, source: RSForm,
|
||||
cst_list: list[Constituenta],
|
||||
exclude: Optional[list[int]] = None
|
||||
) -> None:
|
||||
def after_create_cst(self, source: RSForm, cst_list: list[Constituenta]) -> None:
|
||||
''' Trigger cascade resolutions when new constituent is created. '''
|
||||
self.cache.insert_schema(source)
|
||||
inserted_aliases = [cst.alias for cst in cst_list]
|
||||
|
@ -325,7 +281,7 @@ class OperationSchema:
|
|||
if cst is not None:
|
||||
alias_mapping[alias] = cst
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
self._cascade_inherit_cst(operation.pk, source, cst_list, alias_mapping, exclude)
|
||||
self._cascade_inherit_cst(operation.pk, source, cst_list, alias_mapping)
|
||||
|
||||
def after_change_cst_type(self, source: RSForm, target: Constituenta) -> None:
|
||||
''' Trigger cascade resolutions when constituenta type is changed. '''
|
||||
|
@ -388,19 +344,17 @@ class OperationSchema:
|
|||
mapping={}
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments, too-many-positional-arguments
|
||||
def _cascade_inherit_cst(
|
||||
self, target_operation: int,
|
||||
self,
|
||||
target_operation: int,
|
||||
source: RSForm,
|
||||
items: list[Constituenta],
|
||||
mapping: CstMapping,
|
||||
exclude: Optional[list[int]] = None
|
||||
mapping: CstMapping
|
||||
) -> None:
|
||||
children = self.cache.graph.outputs[target_operation]
|
||||
if len(children) == 0:
|
||||
return
|
||||
for child_id in children:
|
||||
if not exclude or child_id not in exclude:
|
||||
self._execute_inherit_cst(child_id, source, items, mapping)
|
||||
|
||||
def _execute_inherit_cst(
|
||||
|
@ -873,10 +827,6 @@ class OssCache:
|
|||
''' Remove substitution from cache. '''
|
||||
self.substitutions[target.operation_id].remove(target)
|
||||
|
||||
def remove_inheritance(self, target: Inheritance) -> None:
|
||||
''' Remove inheritance from cache. '''
|
||||
self.inheritance[target.operation_id].remove(target)
|
||||
|
||||
def unfold_sub(self, sub: Substitution) -> tuple[RSForm, RSForm, Constituenta, Constituenta]:
|
||||
operation = self.operation_by_id[sub.operation_id]
|
||||
parents = self.graph.inputs[operation.pk]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
''' Models: Change propagation facade - managing all changes in OSS. '''
|
||||
from typing import Optional
|
||||
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
|
||||
|
@ -16,53 +14,42 @@ class PropagationFacade:
|
|||
''' Change propagation API. '''
|
||||
|
||||
@staticmethod
|
||||
def after_create_cst(source: RSForm, new_cst: list[Constituenta], exclude: Optional[list[int]] = None) -> None:
|
||||
def after_create_cst(source: RSForm, new_cst: list[Constituenta]) -> None:
|
||||
''' Trigger cascade resolutions when new constituent is created. '''
|
||||
hosts = _get_oss_hosts(source.model)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchema(host).after_create_cst(source, new_cst)
|
||||
|
||||
@staticmethod
|
||||
def after_change_cst_type(source: RSForm, target: Constituenta, exclude: Optional[list[int]] = None) -> None:
|
||||
def after_change_cst_type(source: RSForm, target: Constituenta) -> None:
|
||||
''' Trigger cascade resolutions when constituenta type is changed. '''
|
||||
hosts = _get_oss_hosts(source.model)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchema(host).after_change_cst_type(source, target)
|
||||
|
||||
@staticmethod
|
||||
def after_update_cst(
|
||||
source: RSForm,
|
||||
target: Constituenta,
|
||||
data: dict,
|
||||
old_data: dict,
|
||||
exclude: Optional[list[int]] = None
|
||||
) -> None:
|
||||
def after_update_cst(source: RSForm, target: Constituenta, data: dict, old_data: dict) -> None:
|
||||
''' Trigger cascade resolutions when constituenta data is changed. '''
|
||||
hosts = _get_oss_hosts(source.model)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchema(host).after_update_cst(source, target, data, old_data)
|
||||
|
||||
@staticmethod
|
||||
def before_delete_cst(source: RSForm, target: list[Constituenta], exclude: Optional[list[int]] = None) -> None:
|
||||
def before_delete_cst(source: RSForm, target: list[Constituenta]) -> None:
|
||||
''' Trigger cascade resolutions before constituents are deleted. '''
|
||||
hosts = _get_oss_hosts(source.model)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchema(host).before_delete_cst(source, target)
|
||||
|
||||
@staticmethod
|
||||
def before_substitute(source: RSForm, substitutions: CstSubstitution, exclude: Optional[list[int]] = None) -> None:
|
||||
def before_substitute(source: RSForm, substitutions: CstSubstitution) -> None:
|
||||
''' Trigger cascade resolutions before constituents are substituted. '''
|
||||
hosts = _get_oss_hosts(source.model)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchema(host).before_substitute(source, substitutions)
|
||||
|
||||
@staticmethod
|
||||
def before_delete_schema(item: LibraryItem, exclude: Optional[list[int]] = None) -> None:
|
||||
def before_delete_schema(item: LibraryItem) -> None:
|
||||
''' Trigger cascade resolutions before schema is deleted. '''
|
||||
if item.item_type != LibraryItemType.RSFORM:
|
||||
return
|
||||
|
@ -71,4 +58,4 @@ class PropagationFacade:
|
|||
return
|
||||
|
||||
schema = RSForm(item)
|
||||
PropagationFacade.before_delete_cst(schema, list(schema.constituents().order_by('order')), exclude)
|
||||
PropagationFacade.before_delete_cst(schema, list(schema.constituents().order_by('order')))
|
||||
|
|
|
@ -9,7 +9,6 @@ from .data_access import (
|
|||
OperationSerializer,
|
||||
OperationTargetSerializer,
|
||||
OperationUpdateSerializer,
|
||||
RelocateConstituentsSerializer,
|
||||
SetOperationInputSerializer
|
||||
)
|
||||
from .responses import ConstituentaReferenceResponse, NewOperationResponse, NewSchemaResponse
|
||||
|
|
|
@ -11,7 +11,7 @@ from apps.rsform.models import Constituenta
|
|||
from apps.rsform.serializers import SubstitutionSerializerBase
|
||||
from shared import messages as msg
|
||||
|
||||
from ..models import Argument, Inheritance, Operation, OperationSchema, OperationType
|
||||
from ..models import Argument, Operation, OperationSchema, OperationType
|
||||
from .basics import OperationPositionSerializer, SubstitutionExSerializer
|
||||
|
||||
|
||||
|
@ -118,6 +118,8 @@ class OperationUpdateSerializer(serializers.Serializer):
|
|||
return attrs
|
||||
|
||||
|
||||
|
||||
|
||||
class OperationTargetSerializer(serializers.Serializer):
|
||||
''' Serializer: Target single operation. '''
|
||||
target = PKField(many=False, queryset=Operation.objects.all().only('oss_id', 'result_id'))
|
||||
|
@ -222,62 +224,3 @@ class OperationSchemaSerializer(serializers.ModelSerializer):
|
|||
).order_by('pk'):
|
||||
result['substitutions'].append(substitution)
|
||||
return result
|
||||
|
||||
|
||||
class RelocateConstituentsSerializer(serializers.Serializer):
|
||||
''' Serializer: Relocate constituents. '''
|
||||
destination = PKField(
|
||||
many=False,
|
||||
queryset=LibraryItem.objects.all().only('id')
|
||||
)
|
||||
items = PKField(
|
||||
many=True,
|
||||
allow_empty=False,
|
||||
queryset=Constituenta.objects.all()
|
||||
)
|
||||
|
||||
def validate(self, attrs):
|
||||
attrs['destination'] = attrs['destination'].id
|
||||
attrs['source'] = attrs['items'][0].schema_id
|
||||
|
||||
# TODO: check permissions for editing source and destination
|
||||
|
||||
if attrs['source'] == attrs['destination']:
|
||||
raise serializers.ValidationError({
|
||||
'destination': msg.sourceEqualDestination()
|
||||
})
|
||||
for cst in attrs['items']:
|
||||
if cst.schema_id != attrs['source']:
|
||||
raise serializers.ValidationError({
|
||||
f'{cst.pk}': msg.constituentaNotInRSform(attrs['items'][0].schema.title)
|
||||
})
|
||||
if Inheritance.objects.filter(child__in=attrs['items']).exists():
|
||||
raise serializers.ValidationError({
|
||||
'items': msg.RelocatingInherited()
|
||||
})
|
||||
|
||||
oss = LibraryItem.objects \
|
||||
.filter(operations__result_id=attrs['destination']) \
|
||||
.filter(operations__result_id=attrs['source']).only('id')
|
||||
if not oss.exists():
|
||||
raise serializers.ValidationError({
|
||||
'destination': msg.schemasNotConnected()
|
||||
})
|
||||
attrs['oss'] = oss[0].pk
|
||||
|
||||
if Argument.objects.filter(
|
||||
operation__result_id=attrs['destination'],
|
||||
argument__result_id=attrs['source']
|
||||
).exists():
|
||||
attrs['move_down'] = True
|
||||
elif Argument.objects.filter(
|
||||
operation__result_id=attrs['source'],
|
||||
argument__result_id=attrs['destination']
|
||||
).exists():
|
||||
attrs['move_down'] = False
|
||||
else:
|
||||
raise serializers.ValidationError({
|
||||
'destination': msg.schemasNotConnected()
|
||||
})
|
||||
|
||||
return attrs
|
||||
|
|
|
@ -339,65 +339,3 @@ class TestChangeOperations(EndpointTester):
|
|||
self.ks5.refresh_from_db()
|
||||
self.assertNotEqual(self.operation4.result, None)
|
||||
self.assertEqual(self.ks5.constituents().count(), 8)
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
def test_relocate_constituents_up(self):
|
||||
ks1_old_count = self.ks1.constituents().count()
|
||||
ks4_old_count = self.ks4.constituents().count()
|
||||
operation6 = self.owned.create_operation(
|
||||
alias='6',
|
||||
operation_type=OperationType.SYNTHESIS
|
||||
)
|
||||
self.owned.set_arguments(operation6.pk, [self.operation1, self.operation2])
|
||||
self.owned.execute_operation(operation6)
|
||||
operation6.refresh_from_db()
|
||||
ks6 = RSForm(operation6.result)
|
||||
ks6A1 = ks6.insert_new('A1')
|
||||
ks6_old_count = ks6.constituents().count()
|
||||
|
||||
data = {
|
||||
'destination': self.ks1.model.pk,
|
||||
'items': [ks6A1.pk]
|
||||
}
|
||||
|
||||
self.executeOK(data=data)
|
||||
ks6.refresh_from_db()
|
||||
self.ks1.refresh_from_db()
|
||||
self.ks4.refresh_from_db()
|
||||
|
||||
self.assertEqual(ks6.constituents().count(), ks6_old_count)
|
||||
self.assertEqual(self.ks1.constituents().count(), ks1_old_count + 1)
|
||||
self.assertEqual(self.ks4.constituents().count(), ks4_old_count + 1)
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
def test_relocate_constituents_down(self):
|
||||
ks1_old_count = self.ks1.constituents().count()
|
||||
ks4_old_count = self.ks4.constituents().count()
|
||||
|
||||
operation6 = self.owned.create_operation(
|
||||
alias='6',
|
||||
operation_type=OperationType.SYNTHESIS
|
||||
)
|
||||
self.owned.set_arguments(operation6.pk, [self.operation1, self.operation2])
|
||||
self.owned.execute_operation(operation6)
|
||||
operation6.refresh_from_db()
|
||||
ks6 = RSForm(operation6.result)
|
||||
ks6_old_count = ks6.constituents().count()
|
||||
|
||||
data = {
|
||||
'destination': ks6.model.pk,
|
||||
'items': [self.ks1X2.pk]
|
||||
}
|
||||
|
||||
self.executeOK(data=data)
|
||||
ks6.refresh_from_db()
|
||||
self.ks1.refresh_from_db()
|
||||
self.ks4.refresh_from_db()
|
||||
self.ks4D2.refresh_from_db()
|
||||
self.ks5D4.refresh_from_db()
|
||||
|
||||
self.assertEqual(ks6.constituents().count(), ks6_old_count)
|
||||
self.assertEqual(self.ks1.constituents().count(), ks1_old_count - 1)
|
||||
self.assertEqual(self.ks4.constituents().count(), ks4_old_count - 1)
|
||||
self.assertEqual(self.ks4D2.definition_formal, r'DEL X2 X3 S1 D1')
|
||||
self.assertEqual(self.ks5D4.definition_formal, r'X1 X2 X3 S1 D1 D2 D3')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
''' Testing API: Operation Schema. '''
|
||||
from apps.library.models import AccessPolicy, Editor, LibraryItem, LibraryItemType
|
||||
from apps.oss.models import Operation, OperationSchema, OperationType
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
from apps.rsform.models import RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@ class TestOssViewset(EndpointTester):
|
|||
self.private_id = self.private.model.pk
|
||||
self.invalid_id = self.private.model.pk + 1337
|
||||
|
||||
|
||||
def populateData(self):
|
||||
self.ks1 = RSForm.create(
|
||||
alias='KS1',
|
||||
|
@ -134,6 +135,7 @@ class TestOssViewset(EndpointTester):
|
|||
self.executeForbidden(data=data, item=self.unowned_id)
|
||||
self.executeForbidden(data=data, item=self.private_id)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/{item}/create-operation', method='post')
|
||||
def test_create_operation(self):
|
||||
self.populateData()
|
||||
|
@ -497,87 +499,3 @@ class TestOssViewset(EndpointTester):
|
|||
self.assertEqual(len(items), 1)
|
||||
self.assertEqual(items[0].alias, 'X1')
|
||||
self.assertEqual(items[0].term_resolved, self.ks2X1.term_resolved)
|
||||
|
||||
@decl_endpoint('/api/oss/get-predecessor', method='post')
|
||||
def test_get_predecessor(self):
|
||||
self.populateData()
|
||||
self.ks1X2 = self.ks1.insert_new('X2')
|
||||
|
||||
self.owned.execute_operation(self.operation3)
|
||||
self.operation3.refresh_from_db()
|
||||
self.ks3 = RSForm(self.operation3.result)
|
||||
self.ks3X2 = Constituenta.objects.get(as_child__parent_id=self.ks1X2.pk)
|
||||
|
||||
self.executeBadData(data={'target': self.invalid_id})
|
||||
|
||||
response = self.executeOK(data={'target': self.ks1X1.pk})
|
||||
self.assertEqual(response.data['id'], self.ks1X1.pk)
|
||||
self.assertEqual(response.data['schema'], self.ks1.model.pk)
|
||||
|
||||
response = self.executeOK(data={'target': self.ks3X2.pk})
|
||||
self.assertEqual(response.data['id'], self.ks1X2.pk)
|
||||
self.assertEqual(response.data['schema'], self.ks1.model.pk)
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
def test_relocate_constituents(self):
|
||||
self.populateData()
|
||||
self.ks1X2 = self.ks1.insert_new('X2', convention='test')
|
||||
|
||||
self.owned.execute_operation(self.operation3)
|
||||
self.operation3.refresh_from_db()
|
||||
self.ks3 = RSForm(self.operation3.result)
|
||||
self.ks3X2 = Constituenta.objects.get(as_child__parent_id=self.ks1X2.pk)
|
||||
self.ks3X10 = self.ks3.insert_new('X10', convention='test2')
|
||||
|
||||
# invalid destination
|
||||
data = {
|
||||
'destination': self.invalid_id,
|
||||
'items': []
|
||||
}
|
||||
self.executeBadData(data=data)
|
||||
|
||||
# empty items
|
||||
data = {
|
||||
'destination': self.ks1.model.pk,
|
||||
'items': []
|
||||
}
|
||||
self.executeBadData(data=data)
|
||||
|
||||
# source == destination
|
||||
data = {
|
||||
'destination': self.ks1.model.pk,
|
||||
'items': [self.ks1X1.pk]
|
||||
}
|
||||
self.executeBadData(data=data)
|
||||
|
||||
# moving inherited
|
||||
data = {
|
||||
'destination': self.ks1.model.pk,
|
||||
'items': [self.ks3X2.pk]
|
||||
}
|
||||
self.executeBadData(data=data)
|
||||
|
||||
# source and destination are not connected
|
||||
data = {
|
||||
'destination': self.ks2.model.pk,
|
||||
'items': [self.ks1X1.pk]
|
||||
}
|
||||
self.executeBadData(data=data)
|
||||
|
||||
data = {
|
||||
'destination': self.ks3.model.pk,
|
||||
'items': [self.ks1X2.pk]
|
||||
}
|
||||
self.ks3X2.refresh_from_db()
|
||||
self.assertEqual(self.ks3X2.convention, 'test')
|
||||
self.executeOK(data=data)
|
||||
self.assertFalse(Constituenta.objects.filter(as_child__parent_id=self.ks1X2.pk).exists())
|
||||
|
||||
data = {
|
||||
'destination': self.ks1.model.pk,
|
||||
'items': [self.ks3X10.pk]
|
||||
}
|
||||
self.executeOK(data=data)
|
||||
self.assertTrue(Constituenta.objects.filter(as_parent__child_id=self.ks3X10.pk).exists())
|
||||
self.ks1X3 = Constituenta.objects.get(as_parent__child_id=self.ks3X10.pk)
|
||||
self.assertEqual(self.ks1X3.convention, 'test2')
|
||||
|
|
|
@ -14,7 +14,7 @@ from rest_framework.response import Response
|
|||
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.library.serializers import LibraryItemSerializer
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
from apps.rsform.models import Constituenta
|
||||
from apps.rsform.serializers import CstTargetSerializer
|
||||
from shared import messages as msg
|
||||
from shared import permissions
|
||||
|
@ -42,8 +42,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
'create_input',
|
||||
'set_input',
|
||||
'update_operation',
|
||||
'execute_operation',
|
||||
'relocate_constituents'
|
||||
'execute_operation'
|
||||
]:
|
||||
permission_list = [permissions.ItemEditor]
|
||||
elif self.action in ['details']:
|
||||
|
@ -386,36 +385,3 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
'schema': cst.schema_id
|
||||
}
|
||||
)
|
||||
|
||||
@extend_schema(
|
||||
summary='relocate constituents from one schema to another',
|
||||
tags=['OSS'],
|
||||
request=s.RelocateConstituentsSerializer(),
|
||||
responses={
|
||||
c.HTTP_200_OK: s.OperationSchemaSerializer,
|
||||
c.HTTP_400_BAD_REQUEST: None,
|
||||
c.HTTP_403_FORBIDDEN: None,
|
||||
c.HTTP_404_NOT_FOUND: None
|
||||
}
|
||||
)
|
||||
@action(detail=False, methods=['post'], url_path='relocate-constituents')
|
||||
def relocate_constituents(self, request: Request) -> Response:
|
||||
''' Relocate constituents from one schema to another. '''
|
||||
serializer = s.RelocateConstituentsSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
data = serializer.validated_data
|
||||
oss = m.OperationSchema(LibraryItem.objects.get(pk=data['oss']))
|
||||
source = RSForm(LibraryItem.objects.get(pk=data['source']))
|
||||
destination = RSForm(LibraryItem.objects.get(pk=data['destination']))
|
||||
|
||||
with transaction.atomic():
|
||||
if data['move_down']:
|
||||
oss.relocate_down(source, destination, data['items'])
|
||||
m.PropagationFacade.before_delete_cst(source, data['items'])
|
||||
source.delete_cst(data['items'])
|
||||
else:
|
||||
new_items = oss.relocate_up(source, destination, data['items'])
|
||||
m.PropagationFacade.after_create_cst(destination, new_items, exclude=[oss.model.pk])
|
||||
|
||||
return Response(status=c.HTTP_200_OK)
|
||||
|
|
|
@ -64,7 +64,6 @@ class RSForm:
|
|||
def refresh_from_db(self) -> None:
|
||||
''' Model wrapper. '''
|
||||
self.model.refresh_from_db()
|
||||
self.cache = RSFormCache(self)
|
||||
|
||||
def constituents(self) -> QuerySet[Constituenta]:
|
||||
''' Get QuerySet containing all constituents of current RSForm. '''
|
||||
|
|
|
@ -38,18 +38,6 @@ def operationResultFromAnotherOSS():
|
|||
return 'Схема является результатом другой ОСС'
|
||||
|
||||
|
||||
def schemasNotConnected():
|
||||
return 'Концептуальные схемы не связаны через ОСС'
|
||||
|
||||
|
||||
def sourceEqualDestination():
|
||||
return 'Схема-источник и схема-получатель не могут быть одинаковыми'
|
||||
|
||||
|
||||
def RelocatingInherited():
|
||||
return 'Невозможно переместить наследуемые конституенты'
|
||||
|
||||
|
||||
def operationInputAlreadyConnected():
|
||||
return 'Схема уже подключена к другой операции'
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ import globals from 'globals';
|
|||
import typescriptPlugin from 'typescript-eslint';
|
||||
import typescriptParser from '@typescript-eslint/parser';
|
||||
import reactPlugin from 'eslint-plugin-react';
|
||||
import reactHooksPlugin from 'eslint-plugin-react-hooks';
|
||||
// import { fixupPluginRules } from '@eslint/compat';
|
||||
// import reactHooksPlugin from 'eslint-plugin-react-hooks';
|
||||
|
||||
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
||||
|
||||
|
@ -34,7 +35,7 @@ export default [
|
|||
{
|
||||
plugins: {
|
||||
'react': reactPlugin,
|
||||
'react-hooks': reactHooksPlugin,
|
||||
// 'react-hooks': fixupPluginRules(reactHooksPlugin),
|
||||
'simple-import-sort': simpleImportSort
|
||||
},
|
||||
settings: { react: { version: 'detect' } },
|
||||
|
@ -55,9 +56,7 @@ export default [
|
|||
'react-refresh/only-export-components': ['off', { allowConstantExport: true }],
|
||||
|
||||
'simple-import-sort/imports': 'warn',
|
||||
'simple-import-sort/exports': 'error',
|
||||
|
||||
...reactHooksPlugin.configs.recommended.rules
|
||||
'simple-import-sort/exports': 'error'
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
2873
rsconcept/frontend/package-lock.json
generated
2873
rsconcept/frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -14,22 +14,21 @@
|
|||
"dependencies": {
|
||||
"@lezer/lr": "^1.4.2",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@uiw/codemirror-themes": "^4.23.6",
|
||||
"@uiw/react-codemirror": "^4.23.6",
|
||||
"@uiw/codemirror-themes": "^4.23.5",
|
||||
"@uiw/react-codemirror": "^4.23.5",
|
||||
"axios": "^1.7.7",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"framer-motion": "^11.11.10",
|
||||
"framer-motion": "^11.5.6",
|
||||
"html-to-image": "^1.11.11",
|
||||
"js-file-download": "^0.4.12",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-error-boundary": "^4.1.2",
|
||||
"react-error-boundary": "^4.1.1",
|
||||
"react-icons": "^5.3.0",
|
||||
"react-intl": "^6.8.4",
|
||||
"react-intl": "^6.8.0",
|
||||
"react-loader-spinner": "^6.1.6",
|
||||
"react-router-dom": "^6.27.0",
|
||||
"react-select": "^5.8.2",
|
||||
"react-select": "^5.8.1",
|
||||
"react-tabs": "^6.0.2",
|
||||
"react-toastify": "^10.0.6",
|
||||
"react-tooltip": "^5.28.0",
|
||||
|
@ -40,16 +39,16 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@lezer/generator": "^1.7.1",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^22.8.1",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/jest": "^29.5.13",
|
||||
"@types/node": "^22.7.6",
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
||||
"@typescript-eslint/parser": "^8.0.1",
|
||||
"@vitejs/plugin-react": "^4.3.3",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"eslint": "^9.12.0",
|
||||
"eslint-plugin-react": "^7.37.1",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"globals": "^15.11.0",
|
||||
"jest": "^29.7.0",
|
||||
|
@ -57,8 +56,8 @@
|
|||
"tailwindcss": "^3.4.14",
|
||||
"ts-jest": "^29.2.5",
|
||||
"typescript": "^5.6.3",
|
||||
"typescript-eslint": "^8.11.0",
|
||||
"vite": "^5.4.10"
|
||||
"typescript-eslint": "^8.9.0",
|
||||
"vite": "^5.4.9"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
ICstRelocateData,
|
||||
IInputCreatedResponse,
|
||||
IOperationCreateData,
|
||||
IOperationCreatedResponse,
|
||||
|
@ -77,13 +76,6 @@ export function postExecuteOperation(oss: string, request: FrontExchange<ITarget
|
|||
});
|
||||
}
|
||||
|
||||
export function postRelocateConstituents(request: FrontPush<ICstRelocateData>) {
|
||||
AxiosPost({
|
||||
endpoint: `/api/oss/relocate-constituents`,
|
||||
request: request
|
||||
});
|
||||
}
|
||||
|
||||
export function postFindPredecessor(request: FrontExchange<ITargetCst, IConstituentaReference>) {
|
||||
AxiosPost({
|
||||
endpoint: `/api/oss/get-predecessor`,
|
||||
|
|
|
@ -61,7 +61,7 @@ function PickMultiConstituenta({
|
|||
newGraph.foldNode(item.id);
|
||||
});
|
||||
return newGraph;
|
||||
}, [data, schema.graph, schema.items]);
|
||||
}, [schema.graph, data]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (filtered.length === 0) {
|
||||
|
|
|
@ -63,7 +63,7 @@ function PickSchema({
|
|||
);
|
||||
}
|
||||
setFiltered(newFiltered);
|
||||
}, [filterText, filterLocation, baseFiltered]);
|
||||
}, [filterText, filterLocation]);
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
|
|
|
@ -146,7 +146,7 @@ function DataTable<TData extends RowData>({
|
|||
colSizes[`--col-${header.column.id}-size`] = header.column.getSize();
|
||||
}
|
||||
return colSizes;
|
||||
}, [tableImpl]);
|
||||
}, [tableImpl.getState().columnSizingInfo, tableImpl.getState().columnSizing]);
|
||||
|
||||
return (
|
||||
<div tabIndex={-1} id={id} className={className} style={{ minHeight: fixedSize, maxHeight: fixedSize, ...style }}>
|
||||
|
|
|
@ -18,7 +18,7 @@ function AnimateFade({ style, noFadeIn, noFadeOut, children, hideContent, ...res
|
|||
animate={hideContent ? 'hidden' : 'active'}
|
||||
variants={animateFade.variants}
|
||||
exit={{ ...(!noFadeOut ? animateFade.exit : {}) }}
|
||||
style={{ display: hideContent ? 'none' : '', willChange: 'auto', ...style }}
|
||||
style={{ display: hideContent ? 'none' : '', ...style }}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -238,7 +238,7 @@ export const LibraryState = ({ children }: React.PropsWithChildren) => {
|
|||
});
|
||||
}
|
||||
},
|
||||
[reloadItems]
|
||||
[reloadItems, user]
|
||||
);
|
||||
|
||||
const destroyItem = useCallback(
|
||||
|
@ -254,7 +254,7 @@ export const LibraryState = ({ children }: React.PropsWithChildren) => {
|
|||
})
|
||||
});
|
||||
},
|
||||
[reloadItems]
|
||||
[reloadItems, user]
|
||||
);
|
||||
|
||||
const cloneItem = useCallback(
|
||||
|
@ -291,7 +291,7 @@ export const LibraryState = ({ children }: React.PropsWithChildren) => {
|
|||
})
|
||||
});
|
||||
},
|
||||
[reloadItems]
|
||||
[reloadItems, user]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -17,14 +17,12 @@ import {
|
|||
patchUpdateOperation,
|
||||
patchUpdatePositions,
|
||||
postCreateOperation,
|
||||
postExecuteOperation,
|
||||
postRelocateConstituents
|
||||
postExecuteOperation
|
||||
} from '@/backend/oss';
|
||||
import { type ErrorData } from '@/components/info/InfoError';
|
||||
import { AccessPolicy, ILibraryItem } from '@/models/library';
|
||||
import { ILibraryUpdateData } from '@/models/library';
|
||||
import {
|
||||
ICstRelocateData,
|
||||
IOperationCreateData,
|
||||
IOperationData,
|
||||
IOperationDeleteData,
|
||||
|
@ -67,7 +65,6 @@ interface IOssContext {
|
|||
setInput: (data: IOperationSetInputData, callback?: () => void) => void;
|
||||
updateOperation: (data: IOperationUpdateData, callback?: () => void) => void;
|
||||
executeOperation: (data: ITargetOperation, callback?: () => void) => void;
|
||||
relocateConstituents: (data: ICstRelocateData, callback?: () => void) => void;
|
||||
}
|
||||
|
||||
const OssContext = createContext<IOssContext | null>(null);
|
||||
|
@ -97,7 +94,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
|
||||
useEffect(() => {
|
||||
oss.setID(itemID);
|
||||
}, [itemID, oss]);
|
||||
}, [itemID, oss.setID]);
|
||||
|
||||
const update = useCallback(
|
||||
(data: ILibraryUpdateData, callback?: DataCallback<ILibraryItem>) => {
|
||||
|
@ -118,7 +115,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library, oss]
|
||||
[itemID, model, library.localUpdateItem, oss.setData]
|
||||
);
|
||||
|
||||
const setOwner = useCallback(
|
||||
|
@ -142,7 +139,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library]
|
||||
[itemID, model, library.reloadItems]
|
||||
);
|
||||
|
||||
const setAccessPolicy = useCallback(
|
||||
|
@ -166,7 +163,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library]
|
||||
[itemID, model, library.reloadItems]
|
||||
);
|
||||
|
||||
const setLocation = useCallback(
|
||||
|
@ -190,7 +187,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library]
|
||||
[itemID, model, library.reloadItems]
|
||||
);
|
||||
|
||||
const setEditors = useCallback(
|
||||
|
@ -214,7 +211,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library]
|
||||
[itemID, model, library.reloadItems]
|
||||
);
|
||||
|
||||
const savePositions = useCallback(
|
||||
|
@ -231,7 +228,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, library]
|
||||
[itemID, library.localUpdateTimestamp]
|
||||
);
|
||||
|
||||
const createOperation = useCallback(
|
||||
|
@ -249,7 +246,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, library, oss]
|
||||
[itemID, library.localUpdateTimestamp, oss.setData]
|
||||
);
|
||||
|
||||
const deleteOperation = useCallback(
|
||||
|
@ -268,7 +265,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, library, oss]
|
||||
[itemID, library.reloadItems, oss.setData]
|
||||
);
|
||||
|
||||
const createInput = useCallback(
|
||||
|
@ -287,7 +284,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, library, oss]
|
||||
[itemID, library.reloadItems, oss.setData]
|
||||
);
|
||||
|
||||
const setInput = useCallback(
|
||||
|
@ -309,7 +306,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library, oss]
|
||||
[itemID, model, library.reloadItems, oss.setData]
|
||||
);
|
||||
|
||||
const updateOperation = useCallback(
|
||||
|
@ -331,7 +328,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library, oss]
|
||||
[itemID, model, library.reloadItems, oss.setData]
|
||||
);
|
||||
|
||||
const executeOperation = useCallback(
|
||||
|
@ -353,29 +350,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, model, library, oss]
|
||||
);
|
||||
|
||||
const relocateConstituents = useCallback(
|
||||
(data: ICstRelocateData, callback?: () => void) => {
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
setProcessingError(undefined);
|
||||
postRelocateConstituents({
|
||||
data: data,
|
||||
showError: true,
|
||||
setLoading: setProcessing,
|
||||
onError: setProcessingError,
|
||||
onSuccess: () => {
|
||||
oss.reload();
|
||||
library.reloadItems(() => {
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
[model, library, oss]
|
||||
[itemID, model, library.reloadItems, oss.setData]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -401,8 +376,7 @@ export const OssState = ({ itemID, children }: React.PropsWithChildren<OssStateP
|
|||
createInput,
|
||||
setInput,
|
||||
updateOperation,
|
||||
executeOperation,
|
||||
relocateConstituents
|
||||
executeOperation
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
|
|
@ -151,7 +151,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, setSchema, schema, library, oss]
|
||||
[itemID, setSchema, schema, library.localUpdateItem, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const upload = useCallback(
|
||||
|
@ -172,7 +172,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, setSchema, schema, library]
|
||||
[itemID, setSchema, schema, library.localUpdateItem]
|
||||
);
|
||||
|
||||
const setOwner = useCallback(
|
||||
|
@ -195,7 +195,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, schema, library]
|
||||
[itemID, schema, library.localUpdateItem]
|
||||
);
|
||||
|
||||
const setAccessPolicy = useCallback(
|
||||
|
@ -218,7 +218,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, schema, library]
|
||||
[itemID, schema, library.localUpdateItem]
|
||||
);
|
||||
|
||||
const setLocation = useCallback(
|
||||
|
@ -240,7 +240,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, schema, library]
|
||||
[itemID, schema, library.reloadItems]
|
||||
);
|
||||
|
||||
const setEditors = useCallback(
|
||||
|
@ -283,7 +283,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, schema, user, setSchema, library, oss]
|
||||
[itemID, schema, user, setSchema, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const restoreOrder = useCallback(
|
||||
|
@ -303,7 +303,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, schema, user, setSchema, library]
|
||||
[itemID, schema, user, setSchema, library.localUpdateTimestamp]
|
||||
);
|
||||
|
||||
const produceStructure = useCallback(
|
||||
|
@ -322,7 +322,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[setSchema, itemID, library, oss]
|
||||
[setSchema, itemID, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const download = useCallback(
|
||||
|
@ -354,7 +354,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, setSchema, library, oss]
|
||||
[itemID, setSchema, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const cstDelete = useCallback(
|
||||
|
@ -373,7 +373,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, setSchema, library, oss]
|
||||
[itemID, setSchema, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const cstUpdate = useCallback(
|
||||
|
@ -392,7 +392,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
})
|
||||
});
|
||||
},
|
||||
[itemID, reload, library, oss]
|
||||
[itemID, reload, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const cstRename = useCallback(
|
||||
|
@ -411,7 +411,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[setSchema, itemID, library, oss]
|
||||
[setSchema, itemID, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const cstSubstitute = useCallback(
|
||||
|
@ -430,7 +430,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[setSchema, itemID, library, oss]
|
||||
[setSchema, itemID, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
const cstMoveTo = useCallback(
|
||||
|
@ -448,7 +448,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, setSchema, library]
|
||||
[itemID, setSchema, library.localUpdateTimestamp]
|
||||
);
|
||||
|
||||
const versionCreate = useCallback(
|
||||
|
@ -466,7 +466,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[itemID, setSchema, library]
|
||||
[itemID, setSchema, library.localUpdateTimestamp]
|
||||
);
|
||||
|
||||
const findPredecessor = useCallback((data: ITargetCst, callback: (reference: IConstituentaReference) => void) => {
|
||||
|
@ -537,7 +537,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[setSchema, library]
|
||||
[setSchema, library.localUpdateItem]
|
||||
);
|
||||
|
||||
const inlineSynthesis = useCallback(
|
||||
|
@ -556,7 +556,7 @@ export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChil
|
|||
}
|
||||
});
|
||||
},
|
||||
[setSchema, library, oss]
|
||||
[itemID, setSchema, library.localUpdateTimestamp, oss.invalidateItem]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -44,7 +44,7 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
|
|||
|
||||
const handleTypeChange = useCallback(
|
||||
(target: CstType) => partialUpdate({ cst_type: target, alias: generateAlias(target, schema) }),
|
||||
[partialUpdate, schema]
|
||||
[partialUpdate, schema, generateAlias]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -62,7 +62,6 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
|||
const cache = useRSFormCache();
|
||||
const schemas = useMemo(
|
||||
() => schemasIDs.map(id => cache.getSchema(id)).filter(item => item !== undefined),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[schemasIDs, cache.getSchema]
|
||||
);
|
||||
|
||||
|
@ -91,7 +90,6 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
|||
|
||||
useLayoutEffect(() => {
|
||||
cache.preload(schemasIDs);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [schemasIDs]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
@ -111,7 +109,6 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
|
|||
return true;
|
||||
})
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [schemasIDs, schemas, cache.loading]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
|
|
@ -61,7 +61,7 @@ function DlgInlineSynthesis({ hideWindow, receiver, onInlineSynthesis }: DlgInli
|
|||
<TabSchema selected={donorID} setSelected={setDonorID} receiver={receiver} />
|
||||
</TabPanel>
|
||||
),
|
||||
[donorID, receiver]
|
||||
[donorID]
|
||||
);
|
||||
const itemsPanel = useMemo(
|
||||
() => (
|
||||
|
|
|
@ -30,7 +30,7 @@ function DlgRelocateConstituents({ oss, hideWindow, target, onSubmit }: DlgReloc
|
|||
...node.outputs.map(id => oss.operationByID.get(id)!.result).filter(id => id !== null)
|
||||
];
|
||||
return ids.map(id => library.items.find(item => item.id === id)).filter(item => item !== undefined);
|
||||
}, [oss, library.items, target.id]);
|
||||
}, [oss, library.items]);
|
||||
|
||||
const [destination, setDestination] = useState<ILibraryItem | undefined>(undefined);
|
||||
const [selected, setSelected] = useState<ConstituentaID[]>([]);
|
||||
|
@ -42,7 +42,7 @@ function DlgRelocateConstituents({ oss, hideWindow, target, onSubmit }: DlgReloc
|
|||
}
|
||||
const destinationOperation = oss.items.find(item => item.result === destination.id);
|
||||
return getRelocateCandidates(target.id, destinationOperation!.id, source.schema, oss);
|
||||
}, [destination, target.id, source.schema, oss]);
|
||||
}, [destination, source.schema?.items]);
|
||||
|
||||
const isValid = useMemo(() => !!destination && selected.length > 0, [destination, selected]);
|
||||
|
||||
|
@ -55,15 +55,12 @@ function DlgRelocateConstituents({ oss, hideWindow, target, onSubmit }: DlgReloc
|
|||
}, []);
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
if (!destination) {
|
||||
return;
|
||||
}
|
||||
const data: ICstRelocateData = {
|
||||
destination: destination.id,
|
||||
items: selected
|
||||
destination: target.result ?? 0,
|
||||
items: []
|
||||
};
|
||||
onSubmit(data);
|
||||
}, [destination, onSubmit, selected]);
|
||||
}, [target, onSubmit]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
|
|
@ -15,17 +15,14 @@ function useOssDetails({ target, items }: { target?: string; items: ILibraryItem
|
|||
const [loading, setLoading] = useState(target != undefined);
|
||||
const [error, setError] = useState<ErrorData>(undefined);
|
||||
|
||||
const setSchema = useCallback(
|
||||
(data?: IOperationSchemaData) => {
|
||||
function setSchema(data?: IOperationSchemaData) {
|
||||
if (!data) {
|
||||
setInner(undefined);
|
||||
return;
|
||||
}
|
||||
const newSchema = new OssLoader(data, items).produceOSS();
|
||||
setInner(newSchema);
|
||||
},
|
||||
[items]
|
||||
);
|
||||
}
|
||||
|
||||
const reload = useCallback(
|
||||
(setCustomLoading?: typeof setLoading, callback?: () => void) => {
|
||||
|
@ -46,7 +43,7 @@ function useOssDetails({ target, items }: { target?: string; items: ILibraryItem
|
|||
}
|
||||
});
|
||||
},
|
||||
[target, setSchema]
|
||||
[target]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -76,7 +76,6 @@ function useRSFormCache() {
|
|||
}
|
||||
})
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pending]);
|
||||
|
||||
return { preload, getSchema, getConstituenta, getSchemaByCst, loading, error, setError };
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
'use client';
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
|
||||
function useWindowSize() {
|
||||
const isClient = typeof window === 'object';
|
||||
|
||||
const getSize = useCallback(
|
||||
() => ({
|
||||
function getSize() {
|
||||
return {
|
||||
width: isClient ? window.innerWidth : undefined,
|
||||
height: isClient ? window.innerHeight : undefined,
|
||||
isSmall: isClient && window.innerWidth < PARAMETER.smallScreen
|
||||
}),
|
||||
[isClient]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const [windowSize, setWindowSize] = useState(getSize);
|
||||
|
||||
|
@ -27,7 +26,7 @@ function useWindowSize() {
|
|||
}
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, [isClient, getSize]);
|
||||
}, []);
|
||||
|
||||
return windowSize;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ function LibraryPage() {
|
|||
const toggleVisible = useCallback(() => setIsVisible(prev => toggleTristateFlag(prev)), [setIsVisible]);
|
||||
const toggleOwned = useCallback(() => setIsOwned(prev => toggleTristateFlag(prev)), [setIsOwned]);
|
||||
const toggleEditor = useCallback(() => setIsEditor(prev => toggleTristateFlag(prev)), [setIsEditor]);
|
||||
const toggleFolderMode = useCallback(() => options.setFolderMode(prev => !prev), [options]);
|
||||
const toggleFolderMode = useCallback(() => options.setFolderMode(prev => !prev), [options.setFolderMode]);
|
||||
const toggleSubfolders = useCallback(() => setSubfolders(prev => !prev), [setSubfolders]);
|
||||
|
||||
const resetFilter = useCallback(() => {
|
||||
|
@ -102,7 +102,7 @@ function LibraryPage() {
|
|||
setIsEditor(undefined);
|
||||
setFilterUser(undefined);
|
||||
options.setLocation('');
|
||||
}, [setHead, setIsVisible, setIsOwned, setIsEditor, setFilterUser, options]);
|
||||
}, [setHead, setIsVisible, setIsOwned, setIsEditor, setFilterUser, options.setLocation]);
|
||||
|
||||
const promptRenameLocation = useCallback(() => {
|
||||
setShowRenameLocation(true);
|
||||
|
@ -119,7 +119,7 @@ function LibraryPage() {
|
|||
toast.success(information.locationRenamed);
|
||||
});
|
||||
},
|
||||
[options, library]
|
||||
[location, library]
|
||||
);
|
||||
|
||||
const handleDownloadCSV = useCallback(() => {
|
||||
|
@ -159,15 +159,7 @@ function LibraryPage() {
|
|||
onRenameLocation={promptRenameLocation}
|
||||
/>
|
||||
),
|
||||
[
|
||||
options.location,
|
||||
library.folders,
|
||||
options.setLocation,
|
||||
toggleFolderMode,
|
||||
promptRenameLocation,
|
||||
toggleSubfolders,
|
||||
subfolders
|
||||
]
|
||||
[options.location, library.folders, options.setLocation, toggleFolderMode, subfolders]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -19,13 +19,6 @@ function ManualsPage() {
|
|||
|
||||
const { mainHeight } = useConceptOptions();
|
||||
|
||||
const onSelectTopic = useCallback(
|
||||
(newTopic: HelpTopic) => {
|
||||
router.push(urls.help_topic(newTopic));
|
||||
},
|
||||
[router]
|
||||
);
|
||||
|
||||
if (!Object.values(HelpTopic).includes(activeTopic)) {
|
||||
setTimeout(() => {
|
||||
router.push(urls.page404);
|
||||
|
@ -34,6 +27,13 @@ function ManualsPage() {
|
|||
return null;
|
||||
}
|
||||
|
||||
const onSelectTopic = useCallback(
|
||||
(newTopic: HelpTopic) => {
|
||||
router.push(urls.help_topic(newTopic));
|
||||
},
|
||||
[router]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='flex mx-auto max-w-[80rem]' role='manuals' style={{ minHeight: mainHeight }}>
|
||||
<TopicsList activeTopic={activeTopic} onChangeTopic={topic => onSelectTopic(topic)} />
|
||||
|
|
|
@ -145,6 +145,13 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
|||
[controller, getPositions, flow]
|
||||
);
|
||||
|
||||
const handleDeleteSelected = useCallback(() => {
|
||||
if (controller.selected.length !== 1) {
|
||||
return;
|
||||
}
|
||||
handleDeleteOperation(controller.selected[0]);
|
||||
}, [controller, getPositions]);
|
||||
|
||||
const handleDeleteOperation = useCallback(
|
||||
(target: OperationID) => {
|
||||
if (!controller.canDelete(target)) {
|
||||
|
@ -155,13 +162,6 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
|||
[controller, getPositions]
|
||||
);
|
||||
|
||||
const handleDeleteSelected = useCallback(() => {
|
||||
if (controller.selected.length !== 1) {
|
||||
return;
|
||||
}
|
||||
handleDeleteOperation(controller.selected[0]);
|
||||
}, [controller, handleDeleteOperation]);
|
||||
|
||||
const handleCreateInput = useCallback(
|
||||
(target: OperationID) => {
|
||||
controller.createInput(target, getPositions());
|
||||
|
@ -199,9 +199,9 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
|||
|
||||
const handleRelocateConstituents = useCallback(
|
||||
(target: OperationID) => {
|
||||
controller.promptRelocateConstituents(target, getPositions());
|
||||
controller.promptRelocateConstituents(target);
|
||||
},
|
||||
[controller, getPositions]
|
||||
[controller]
|
||||
);
|
||||
|
||||
const handleFitView = useCallback(() => {
|
||||
|
@ -282,7 +282,7 @@ function OssFlow({ isModified, setIsModified }: OssFlowProps) {
|
|||
handleEditOperation(Number(node.id));
|
||||
}
|
||||
},
|
||||
[handleEditOperation, controller]
|
||||
[handleEditOperation, controller.openOperationSchema]
|
||||
);
|
||||
|
||||
function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||
|
|
|
@ -76,7 +76,7 @@ export interface IOssEditContext extends ILibraryItemEditor {
|
|||
promptEditInput: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
promptEditOperation: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
executeOperation: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
promptRelocateConstituents: (target: OperationID, positions: IOperationPosition[]) => void;
|
||||
promptRelocateConstituents: (target: OperationID) => void;
|
||||
}
|
||||
|
||||
const OssEditContext = createContext<IOssEditContext | null>(null);
|
||||
|
@ -288,11 +288,14 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model]
|
||||
);
|
||||
|
||||
const promptDeleteOperation = useCallback((target: OperationID, positions: IOperationPosition[]) => {
|
||||
const promptDeleteOperation = useCallback(
|
||||
(target: OperationID, positions: IOperationPosition[]) => {
|
||||
setPositions(positions);
|
||||
setTargetOperationID(target);
|
||||
setShowDeleteOperation(true);
|
||||
}, []);
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
const deleteOperation = useCallback(
|
||||
(keepConstituents: boolean, deleteSchema: boolean) => {
|
||||
|
@ -360,19 +363,21 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit
|
|||
[model]
|
||||
);
|
||||
|
||||
const promptRelocateConstituents = useCallback((target: OperationID, positions: IOperationPosition[]) => {
|
||||
setPositions(positions);
|
||||
const promptRelocateConstituents = useCallback(
|
||||
(target: OperationID) => {
|
||||
setTargetOperationID(target);
|
||||
setShowRelocateConstituents(true);
|
||||
}, []);
|
||||
},
|
||||
[model]
|
||||
);
|
||||
|
||||
const handleRelocateConstituents = useCallback(
|
||||
(data: ICstRelocateData) => {
|
||||
model.savePositions({ positions: positions }, () =>
|
||||
model.relocateConstituents(data, () => toast.success(information.changesSaved))
|
||||
);
|
||||
// TODO: implement backed call
|
||||
console.log(data);
|
||||
toast.success('В разработке');
|
||||
},
|
||||
[model, positions]
|
||||
[model]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -169,11 +169,7 @@ function FormConstituenta({
|
|||
) : null}
|
||||
{state ? (
|
||||
<AnimatePresence>
|
||||
<AnimateFade
|
||||
key='cst_expression_fade'
|
||||
hideContent={!state.definition_formal && isElementary}
|
||||
style={{ willChange: 'auto' }}
|
||||
>
|
||||
<AnimateFade key='cst_expression_fade' hideContent={!state.definition_formal && isElementary}>
|
||||
<EditorRSExpression
|
||||
id='cst_expression'
|
||||
label={
|
||||
|
|
|
@ -95,7 +95,8 @@ function EditorRSExpression({
|
|||
});
|
||||
}
|
||||
|
||||
const onShowError = useCallback((error: IRSErrorDescription, prefixLen: number) => {
|
||||
const onShowError = useCallback(
|
||||
(error: IRSErrorDescription, prefixLen: number) => {
|
||||
if (!rsInput.current) {
|
||||
return;
|
||||
}
|
||||
|
@ -108,7 +109,9 @@ function EditorRSExpression({
|
|||
}
|
||||
});
|
||||
rsInput.current?.view?.focus();
|
||||
}, []);
|
||||
},
|
||||
[activeCst]
|
||||
);
|
||||
|
||||
const handleEdit = useCallback((id: TokenID, key?: string) => {
|
||||
if (!rsInput.current?.editor || !rsInput.current.state || !rsInput.current.view) {
|
||||
|
|
|
@ -38,7 +38,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
|
|||
const { accessLevel } = useAccessMode();
|
||||
const intl = useIntl();
|
||||
const router = useConceptNavigation();
|
||||
const { setLocation, setFolderMode } = useConceptOptions();
|
||||
const options = useConceptOptions();
|
||||
|
||||
const ownerSelector = useDropdown();
|
||||
const onSelectUser = useCallback(
|
||||
|
@ -60,11 +60,11 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
|
|||
if (!item) {
|
||||
return;
|
||||
}
|
||||
setLocation(item.location);
|
||||
setFolderMode(true);
|
||||
options.setLocation(item.location);
|
||||
options.setFolderMode(true);
|
||||
router.push(urls.library, event.ctrlKey || event.metaKey);
|
||||
},
|
||||
[setLocation, setFolderMode, item, router]
|
||||
[options.setLocation, options.setFolderMode, item, router]
|
||||
);
|
||||
|
||||
if (!item) {
|
||||
|
|
|
@ -341,7 +341,7 @@ export const RSEditState = ({
|
|||
toast.success(information.newVersion(data.version));
|
||||
});
|
||||
},
|
||||
[model]
|
||||
[model, viewVersion]
|
||||
);
|
||||
|
||||
const handleDeleteVersion = useCallback(
|
||||
|
|
|
@ -8,16 +8,6 @@
|
|||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
*,
|
||||
*::after,
|
||||
*::before {
|
||||
box-sizing: border-box;
|
||||
|
||||
/* Uncomment to debug layering and overflow */
|
||||
/* background: hsla(135, 50%, 50%, 0.05); */
|
||||
/* outline: 2px solid hotpink; */
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-text-size-adjust: none;
|
||||
-moz-text-size-adjust: none;
|
||||
|
@ -52,8 +42,6 @@ body {
|
|||
}
|
||||
|
||||
:root {
|
||||
interpolate-size: allow-keywords;
|
||||
|
||||
font-size: var(--font-size-base);
|
||||
line-height: var(--line-height);
|
||||
font-family: var(--font-main);
|
||||
|
|
Loading…
Reference in New Issue
Block a user