R: Refactoring caches pt1
This commit is contained in:
parent
b94e643043
commit
41e2df21ef
|
|
@ -67,7 +67,7 @@ class LibraryViewSet(viewsets.ModelViewSet):
|
|||
|
||||
def perform_destroy(self, instance: m.LibraryItem) -> None:
|
||||
if instance.item_type == m.LibraryItemType.RSFORM:
|
||||
PropagationFacade.before_delete_schema(instance)
|
||||
PropagationFacade.before_delete_schema(instance.pk)
|
||||
super().perform_destroy(instance)
|
||||
if instance.item_type == m.LibraryItemType.OPERATION_SCHEMA:
|
||||
schemas = list(OperationSchema.owned_schemasQ(instance))
|
||||
|
|
@ -172,7 +172,7 @@ class LibraryViewSet(viewsets.ModelViewSet):
|
|||
clone.location = data.get('location', m.LocationHead.USER)
|
||||
clone.save()
|
||||
|
||||
RSFormCached(clone).insert_from(item.pk, request.data['items'] if 'items' in request.data else None)
|
||||
RSFormCached(clone.pk).insert_from(item.pk, request.data['items'] if 'items' in request.data else None)
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_201_CREATED,
|
||||
|
|
|
|||
|
|
@ -43,19 +43,18 @@ class OperationSchema:
|
|||
return Layout.objects.get(oss_id=itemID)
|
||||
|
||||
@staticmethod
|
||||
def create_input(oss: LibraryItem, operation: Operation) -> RSFormCached:
|
||||
def create_input(oss_id: int, operation: Operation) -> LibraryItem:
|
||||
''' Create input RSForm for given Operation. '''
|
||||
schema = RSFormCached.create(
|
||||
owner=oss.owner,
|
||||
alias=operation.alias,
|
||||
title=operation.title,
|
||||
description=operation.description,
|
||||
visible=False,
|
||||
access_policy=oss.access_policy,
|
||||
location=oss.location
|
||||
)
|
||||
Editor.set(schema.model.pk, oss.getQ_editors().values_list('pk', flat=True))
|
||||
operation.setQ_result(schema.model)
|
||||
oss = LibraryItem.objects.get(pk=oss_id)
|
||||
schema = LibraryItem.objects.create(item_type=LibraryItemType.RSFORM, owner=oss.owner,
|
||||
alias=operation.alias,
|
||||
title=operation.title,
|
||||
description=operation.description,
|
||||
visible=False,
|
||||
access_policy=oss.access_policy,
|
||||
location=oss.location)
|
||||
Editor.set(schema.pk, oss.getQ_editors().values_list('pk', flat=True))
|
||||
operation.setQ_result(schema)
|
||||
return schema
|
||||
|
||||
def refresh_from_db(self) -> None:
|
||||
|
|
@ -132,7 +131,7 @@ class OperationSchema:
|
|||
if not schemas:
|
||||
return
|
||||
substitutions = operation.getQ_substitutions()
|
||||
receiver = OperationSchema.create_input(self.model, operation)
|
||||
receiver = RSFormCached(OperationSchema.create_input(self.model.pk, operation).pk)
|
||||
|
||||
parents: dict = {}
|
||||
children: dict = {}
|
||||
|
|
@ -149,7 +148,7 @@ class OperationSchema:
|
|||
translated_substitutions.append((original, replacement))
|
||||
receiver.substitute(translated_substitutions)
|
||||
|
||||
for cst in Constituenta.objects.filter(schema=receiver.model).order_by('order'):
|
||||
for cst in Constituenta.objects.filter(schema_id=receiver.pk).order_by('order'):
|
||||
parent = parents.get(cst.pk)
|
||||
assert parent is not None
|
||||
Inheritance.objects.create(
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ from .utils import CstMapping, CstSubstitution, create_dependant_mapping, extrac
|
|||
class OperationSchemaCached:
|
||||
''' Operations schema API with caching. '''
|
||||
|
||||
def __init__(self, model: LibraryItem):
|
||||
self.model = model
|
||||
self.cache = OssCache(model.pk)
|
||||
def __init__(self, item_id: int):
|
||||
self.pk = item_id
|
||||
self.cache = OssCache(item_id)
|
||||
self.engine = PropagationEngine(self.cache)
|
||||
|
||||
def delete_replica(self, target: int, keep_connections: bool = False, keep_constituents: bool = False):
|
||||
|
|
@ -72,12 +72,12 @@ class OperationSchemaCached:
|
|||
has_children = bool(self.cache.extend_graph.outputs[target])
|
||||
old_schema = self.cache.get_schema(operation)
|
||||
if schema is None and old_schema is None or \
|
||||
(schema is not None and old_schema is not None and schema.pk == old_schema.model.pk):
|
||||
(schema is not None and old_schema is not None and schema.pk == old_schema.pk):
|
||||
return
|
||||
|
||||
if old_schema is not None:
|
||||
if has_children:
|
||||
self.before_delete_cst(old_schema.model.pk, [cst.pk for cst in old_schema.cache.constituents])
|
||||
self.before_delete_cst(old_schema.pk, [cst.pk for cst in old_schema.cache.constituents])
|
||||
self.cache.remove_schema(old_schema)
|
||||
|
||||
operation.setQ_result(schema)
|
||||
|
|
@ -88,7 +88,7 @@ class OperationSchemaCached:
|
|||
operation.save(update_fields=['alias', 'title', 'description'])
|
||||
|
||||
if schema is not None and has_children:
|
||||
rsform = RSFormCached(schema)
|
||||
rsform = RSFormCached(schema.pk)
|
||||
self.after_create_cst(rsform, list(rsform.constituentsQ().order_by('order')))
|
||||
|
||||
def set_arguments(self, target: int, arguments: list[Operation]) -> None:
|
||||
|
|
@ -172,7 +172,8 @@ class OperationSchemaCached:
|
|||
if not schemas:
|
||||
return False
|
||||
substitutions = operation.getQ_substitutions()
|
||||
receiver = OperationSchema.create_input(self.model, self.cache.operation_by_id[operation.pk])
|
||||
new_schema = OperationSchema.create_input(self.pk, self.cache.operation_by_id[operation.pk])
|
||||
receiver = RSFormCached(new_schema.pk)
|
||||
self.cache.insert_schema(receiver)
|
||||
|
||||
parents: dict = {}
|
||||
|
|
@ -190,7 +191,7 @@ class OperationSchemaCached:
|
|||
translated_substitutions.append((original, replacement))
|
||||
receiver.substitute(translated_substitutions)
|
||||
|
||||
for cst in Constituenta.objects.filter(schema=receiver.model).order_by('order'):
|
||||
for cst in Constituenta.objects.filter(schema_id=receiver.pk).order_by('order'):
|
||||
parent = parents.get(cst.pk)
|
||||
assert parent is not None
|
||||
Inheritance.objects.create(
|
||||
|
|
@ -204,9 +205,8 @@ class OperationSchemaCached:
|
|||
receiver.resolve_all_text()
|
||||
|
||||
if self.cache.extend_graph.outputs[operation.pk]:
|
||||
receiver_items = list(Constituenta.objects.filter(schema=receiver.model).order_by('order'))
|
||||
receiver_items = list(Constituenta.objects.filter(schema_id=receiver.pk).order_by('order'))
|
||||
self.after_create_cst(receiver, receiver_items)
|
||||
receiver.model.save(update_fields=['time_update'])
|
||||
return True
|
||||
|
||||
def relocate_down(self, source: RSFormCached, destination: RSFormCached, items: list[int]):
|
||||
|
|
@ -214,7 +214,7 @@ class OperationSchemaCached:
|
|||
self.cache.ensure_loaded_subs()
|
||||
self.cache.insert_schema(source)
|
||||
self.cache.insert_schema(destination)
|
||||
operation = self.cache.get_operation(destination.model.pk)
|
||||
operation = self.cache.get_operation(destination.pk)
|
||||
self.engine.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:
|
||||
|
|
@ -228,7 +228,7 @@ class OperationSchemaCached:
|
|||
self.cache.insert_schema(source)
|
||||
self.cache.insert_schema(destination)
|
||||
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
operation = self.cache.get_operation(source.pk)
|
||||
alias_mapping: dict[str, str] = {}
|
||||
for item in self.cache.inheritance[operation.pk]:
|
||||
if item.parent_id in destination.cache.by_id:
|
||||
|
|
@ -236,7 +236,7 @@ class OperationSchemaCached:
|
|||
destination_cst = destination.cache.by_id[item.parent_id]
|
||||
alias_mapping[source_cst.alias] = destination_cst.alias
|
||||
|
||||
new_items = destination.insert_from(source.model.pk, item_ids, alias_mapping)
|
||||
new_items = destination.insert_from(source.pk, item_ids, alias_mapping)
|
||||
for (cst, new_cst) in new_items:
|
||||
new_inheritance = Inheritance.objects.create(
|
||||
operation=operation,
|
||||
|
|
@ -246,7 +246,6 @@ class OperationSchemaCached:
|
|||
self.cache.insert_inheritance(new_inheritance)
|
||||
new_constituents = [item[1] for item in new_items]
|
||||
self.after_create_cst(destination, new_constituents, exclude=[operation.pk])
|
||||
destination.model.save(update_fields=['time_update'])
|
||||
return new_constituents
|
||||
|
||||
def after_create_cst(
|
||||
|
|
@ -257,7 +256,7 @@ class OperationSchemaCached:
|
|||
''' Trigger cascade resolutions when new Constituenta is created. '''
|
||||
self.cache.insert_schema(source)
|
||||
alias_mapping = create_dependant_mapping(source, cst_list)
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
operation = self.cache.get_operation(source.pk)
|
||||
self.engine.on_inherit_cst(operation.pk, source, cst_list, alias_mapping, exclude)
|
||||
|
||||
def after_change_cst_type(self, schemaID: int, target: int, new_type: CstType) -> None:
|
||||
|
|
@ -268,7 +267,7 @@ class OperationSchemaCached:
|
|||
def after_update_cst(self, source: RSFormCached, target: int, data: dict, old_data: dict) -> None:
|
||||
''' Trigger cascade resolutions when Constituenta data is changed. '''
|
||||
self.cache.insert_schema(source)
|
||||
operation = self.cache.get_operation(source.model.pk)
|
||||
operation = self.cache.get_operation(source.pk)
|
||||
depend_aliases = extract_data_references(data, old_data)
|
||||
alias_mapping: CstMapping = {}
|
||||
for alias in depend_aliases:
|
||||
|
|
@ -347,7 +346,7 @@ class OperationSchemaCached:
|
|||
original_cst = schema.cache.by_id[original_id]
|
||||
substitution_cst = schema.cache.by_id[substitution_id]
|
||||
cst_mapping.append((original_cst, substitution_cst))
|
||||
self.before_substitute(schema.model.pk, cst_mapping)
|
||||
self.before_substitute(schema.pk, cst_mapping)
|
||||
schema.substitute(cst_mapping)
|
||||
for sub in added:
|
||||
self.cache.insert_substitution(sub)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class OssCache:
|
|||
if operation.result_id in self._schema_by_id:
|
||||
return self._schema_by_id[operation.result_id]
|
||||
else:
|
||||
schema = RSFormCached.from_id(operation.result_id)
|
||||
schema = RSFormCached(operation.result_id)
|
||||
schema.cache.ensure_loaded()
|
||||
self._insert_new(schema)
|
||||
return schema
|
||||
|
|
@ -77,7 +77,7 @@ class OssCache:
|
|||
if target in self._schema_by_id:
|
||||
return self._schema_by_id[target]
|
||||
else:
|
||||
schema = RSFormCached.from_id(target)
|
||||
schema = RSFormCached(target)
|
||||
schema.cache.ensure_loaded()
|
||||
self._insert_new(schema)
|
||||
return schema
|
||||
|
|
@ -113,7 +113,7 @@ class OssCache:
|
|||
|
||||
def insert_schema(self, schema: RSFormCached) -> None:
|
||||
''' Insert new schema. '''
|
||||
if not self._schema_by_id.get(schema.model.pk):
|
||||
if not self._schema_by_id.get(schema.pk):
|
||||
schema.cache.ensure_loaded()
|
||||
self._insert_new(schema)
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ class OssCache:
|
|||
def remove_schema(self, schema: RSFormCached) -> None:
|
||||
''' Remove schema from cache. '''
|
||||
self._schemas.remove(schema)
|
||||
del self._schema_by_id[schema.model.pk]
|
||||
del self._schema_by_id[schema.pk]
|
||||
|
||||
def remove_operation(self, operation: int) -> None:
|
||||
''' Remove operation from cache. '''
|
||||
|
|
@ -185,4 +185,4 @@ class OssCache:
|
|||
|
||||
def _insert_new(self, schema: RSFormCached) -> None:
|
||||
self._schemas.append(schema)
|
||||
self._schema_by_id[schema.model.pk] = schema
|
||||
self._schema_by_id[schema.pk] = schema
|
||||
|
|
|
|||
|
|
@ -1,28 +1,42 @@
|
|||
''' Models: Change propagation facade - managing all changes in OSS. '''
|
||||
from typing import Optional
|
||||
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.library.models import LibraryItem
|
||||
from apps.rsform.models import Attribution, Constituenta, CstType, RSFormCached
|
||||
|
||||
from .OperationSchemaCached import CstSubstitution, OperationSchemaCached
|
||||
|
||||
|
||||
def _get_oss_hosts(schemaID: int) -> list[LibraryItem]:
|
||||
''' Get all hosts for LibraryItem. '''
|
||||
return list(LibraryItem.objects.filter(operations__result_id=schemaID).only('pk').distinct())
|
||||
def _get_oss_hosts(schemaID: int) -> list[int]:
|
||||
''' Get all hosts for schema. '''
|
||||
return list(LibraryItem.objects.filter(operations__result_id=schemaID).values_list('pk', flat=True))
|
||||
|
||||
|
||||
class PropagationFacade:
|
||||
''' Change propagation API. '''
|
||||
|
||||
_oss: dict[int, OperationSchemaCached] = {}
|
||||
|
||||
@staticmethod
|
||||
def get_oss(schemaID: int) -> OperationSchemaCached:
|
||||
''' Get OperationSchemaCached for schemaID. '''
|
||||
if schemaID not in PropagationFacade._oss:
|
||||
PropagationFacade._oss[schemaID] = OperationSchemaCached(schemaID)
|
||||
return PropagationFacade._oss[schemaID]
|
||||
|
||||
@staticmethod
|
||||
def reset_cache() -> None:
|
||||
''' Reset cache. '''
|
||||
PropagationFacade._oss = {}
|
||||
|
||||
@staticmethod
|
||||
def after_create_cst(source: RSFormCached, new_cst: list[Constituenta],
|
||||
exclude: Optional[list[int]] = None) -> None:
|
||||
''' Trigger cascade resolutions when new constituenta is created. '''
|
||||
hosts = _get_oss_hosts(source.model.pk)
|
||||
hosts = _get_oss_hosts(source.pk)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).after_create_cst(source, new_cst)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).after_create_cst(source, new_cst)
|
||||
|
||||
@staticmethod
|
||||
def after_change_cst_type(sourceID: int, target: int, new_type: CstType,
|
||||
|
|
@ -30,8 +44,8 @@ class PropagationFacade:
|
|||
''' Trigger cascade resolutions when constituenta type is changed. '''
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).after_change_cst_type(sourceID, target, new_type)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).after_change_cst_type(sourceID, target, new_type)
|
||||
|
||||
@staticmethod
|
||||
def after_update_cst(
|
||||
|
|
@ -42,10 +56,10 @@ class PropagationFacade:
|
|||
exclude: Optional[list[int]] = None
|
||||
) -> None:
|
||||
''' Trigger cascade resolutions when constituenta data is changed. '''
|
||||
hosts = _get_oss_hosts(source.model.pk)
|
||||
hosts = _get_oss_hosts(source.pk)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).after_update_cst(source, target, data, old_data)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).after_update_cst(source, target, data, old_data)
|
||||
|
||||
@staticmethod
|
||||
def before_delete_cst(sourceID: int, target: list[int],
|
||||
|
|
@ -53,8 +67,8 @@ class PropagationFacade:
|
|||
''' Trigger cascade resolutions before constituents are deleted. '''
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).before_delete_cst(sourceID, target)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).before_delete_cst(sourceID, target)
|
||||
|
||||
@staticmethod
|
||||
def before_substitute(sourceID: int, substitutions: CstSubstitution,
|
||||
|
|
@ -64,31 +78,31 @@ class PropagationFacade:
|
|||
return
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).before_substitute(sourceID, substitutions)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).before_substitute(sourceID, substitutions)
|
||||
|
||||
@staticmethod
|
||||
def before_delete_schema(item: LibraryItem, exclude: Optional[list[int]] = None) -> None:
|
||||
def before_delete_schema(target: int, exclude: Optional[list[int]] = None) -> None:
|
||||
''' Trigger cascade resolutions before schema is deleted. '''
|
||||
if item.item_type != LibraryItemType.RSFORM:
|
||||
return
|
||||
hosts = _get_oss_hosts(item.pk)
|
||||
hosts = _get_oss_hosts(target)
|
||||
if not hosts:
|
||||
return
|
||||
|
||||
ids = list(Constituenta.objects.filter(schema=item).order_by('order').values_list('pk', flat=True))
|
||||
ids = list(Constituenta.objects.filter(schema_id=target).order_by('order').values_list('pk', flat=True))
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).before_delete_cst(item.pk, ids)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).before_delete_cst(target, ids)
|
||||
del PropagationFacade._oss[host]
|
||||
|
||||
@staticmethod
|
||||
def after_create_attribution(sourceID: int, attributions: list[Attribution],
|
||||
def after_create_attribution(sourceID: int,
|
||||
attributions: list[Attribution],
|
||||
exclude: Optional[list[int]] = None) -> None:
|
||||
''' Trigger cascade resolutions when Attribution is created. '''
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).after_create_attribution(sourceID, attributions)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).after_create_attribution(sourceID, attributions)
|
||||
|
||||
@staticmethod
|
||||
def before_delete_attribution(sourceID: int,
|
||||
|
|
@ -97,5 +111,5 @@ class PropagationFacade:
|
|||
''' Trigger cascade resolutions before Attribution is deleted. '''
|
||||
hosts = _get_oss_hosts(sourceID)
|
||||
for host in hosts:
|
||||
if exclude is None or host.pk not in exclude:
|
||||
OperationSchemaCached(host).before_delete_attribution(sourceID, attributions)
|
||||
if exclude is None or host not in exclude:
|
||||
PropagationFacade.get_oss(host).before_delete_attribution(sourceID, attributions)
|
||||
|
|
|
|||
|
|
@ -625,15 +625,6 @@ class RelocateConstituentsSerializer(StrictSerializer):
|
|||
'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']
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
''' Testing API: Change attributes of OSS and RSForms. '''
|
||||
from apps.library.models import AccessPolicy, Editor, LibraryItem, LocationHead
|
||||
from apps.oss.models import Operation, OperationSchema, OperationType
|
||||
from apps.oss.models import OperationSchema, OperationType, PropagationFacade
|
||||
from apps.rsform.models import RSForm
|
||||
from apps.users.models import User
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
|
@ -11,6 +11,7 @@ class TestChangeAttributes(EndpointTester):
|
|||
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.user3 = User.objects.create(
|
||||
username='UserTest3',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
''' Testing API: Change constituents in OSS. '''
|
||||
|
||||
from apps.oss.models import OperationSchema, OperationType
|
||||
from apps.oss.models import OperationSchema, OperationType, PropagationFacade
|
||||
from apps.rsform.models import Attribution, Constituenta, CstType, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ class TestChangeConstituents(EndpointTester):
|
|||
''' Testing Constituents change propagation in OSS. '''
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(
|
||||
title='Test',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
''' Testing API: Change substitutions in OSS. '''
|
||||
|
||||
from apps.oss.models import OperationSchema, OperationType
|
||||
from apps.rsform.models import Constituenta, CstType, RSForm
|
||||
from apps.oss.models import OperationSchema, OperationType, PropagationFacade
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ class TestChangeOperations(EndpointTester):
|
|||
''' Testing Operations change propagation in OSS. '''
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(
|
||||
title='Test',
|
||||
|
|
@ -388,7 +389,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks5.constituentsQ().count(), 8)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
@decl_endpoint('/api/oss/{item}/relocate-constituents', method='post')
|
||||
def test_relocate_constituents_up(self):
|
||||
ks1_old_count = self.ks1.constituentsQ().count()
|
||||
ks4_old_count = self.ks4.constituentsQ().count()
|
||||
|
|
@ -408,7 +409,7 @@ class TestChangeOperations(EndpointTester):
|
|||
'items': [ks6A1.pk]
|
||||
}
|
||||
|
||||
self.executeOK(data)
|
||||
self.executeOK(data, item=self.owned_id)
|
||||
ks6.model.refresh_from_db()
|
||||
self.ks1.model.refresh_from_db()
|
||||
self.ks4.model.refresh_from_db()
|
||||
|
|
@ -418,7 +419,7 @@ class TestChangeOperations(EndpointTester):
|
|||
self.assertEqual(self.ks4.constituentsQ().count(), ks4_old_count + 1)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
@decl_endpoint('/api/oss/{item}/relocate-constituents', method='post')
|
||||
def test_relocate_constituents_down(self):
|
||||
ks1_old_count = self.ks1.constituentsQ().count()
|
||||
ks4_old_count = self.ks4.constituentsQ().count()
|
||||
|
|
@ -438,7 +439,7 @@ class TestChangeOperations(EndpointTester):
|
|||
'items': [self.ks1X2.pk]
|
||||
}
|
||||
|
||||
self.executeOK(data)
|
||||
self.executeOK(data, item=self.owned_id)
|
||||
ks6.model.refresh_from_db()
|
||||
self.ks1.model.refresh_from_db()
|
||||
self.ks4.model.refresh_from_db()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
''' Testing API: Propagate changes through references in OSS. '''
|
||||
|
||||
from apps.oss.models import Inheritance, OperationSchema, OperationType
|
||||
from apps.oss.models import Inheritance, OperationSchema, OperationType, PropagationFacade
|
||||
from apps.rsform.models import Constituenta, CstType, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ class ReferencePropagationTestCase(EndpointTester):
|
|||
''' Test propagation through references in OSS. '''
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
|
||||
self.owned = OperationSchema.create(
|
||||
|
|
@ -163,7 +164,7 @@ class ReferencePropagationTestCase(EndpointTester):
|
|||
@decl_endpoint('/api/rsforms/{schema}/delete-multiple-cst', method='patch')
|
||||
def test_delete_constituenta(self):
|
||||
data = {'items': [self.ks1X1.pk]}
|
||||
response = self.executeOK(data, schema=self.ks1.model.pk)
|
||||
self.executeOK(data, schema=self.ks1.model.pk)
|
||||
self.ks4D2.refresh_from_db()
|
||||
self.ks5D4.refresh_from_db()
|
||||
self.ks6D2.refresh_from_db()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
''' Testing API: Change substitutions in OSS. '''
|
||||
|
||||
from apps.oss.models import OperationSchema, OperationType
|
||||
from apps.rsform.models import Constituenta, CstType, RSForm
|
||||
from apps.oss.models import OperationSchema, OperationType, PropagationFacade
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
||||
|
|
@ -10,6 +10,7 @@ class TestChangeSubstitutions(EndpointTester):
|
|||
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(
|
||||
title='Test',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
''' Testing API: Operation Schema - blocks manipulation. '''
|
||||
from apps.library.models import AccessPolicy, Editor, LibraryItem, LibraryItemType
|
||||
from apps.oss.models import Operation, OperationSchema, OperationType
|
||||
from apps.oss.models import OperationSchema, OperationType, PropagationFacade
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
||||
|
|
@ -9,6 +8,7 @@ class TestOssBlocks(EndpointTester):
|
|||
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.model.pk
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
''' Testing API: Operation Schema - operations manipulation. '''
|
||||
from apps.library.models import Editor, LibraryItem
|
||||
from apps.oss.models import Argument, Operation, OperationSchema, OperationType, Replica
|
||||
from apps.oss.models import (
|
||||
Argument,
|
||||
Operation,
|
||||
OperationSchema,
|
||||
OperationType,
|
||||
PropagationFacade,
|
||||
Replica
|
||||
)
|
||||
from apps.rsform.models import Attribution, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
|
@ -10,6 +17,7 @@ class TestOssOperations(EndpointTester):
|
|||
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.model.pk
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
''' Testing API: Operation Schema. '''
|
||||
from apps.library.models import AccessPolicy, LibraryItemType
|
||||
from apps.oss.models import OperationSchema, OperationType
|
||||
from apps.oss.models import OperationSchema, OperationType, PropagationFacade
|
||||
from apps.rsform.models import Constituenta, RSForm
|
||||
from shared.EndpointTester import EndpointTester, decl_endpoint
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ class TestOssViewset(EndpointTester):
|
|||
''' Testing OSS view. '''
|
||||
|
||||
def setUp(self):
|
||||
PropagationFacade.reset_cache()
|
||||
super().setUp()
|
||||
self.owned = OperationSchema.create(title='Test', alias='T1', owner=self.user)
|
||||
self.owned_id = self.owned.model.pk
|
||||
|
|
@ -220,8 +221,9 @@ class TestOssViewset(EndpointTester):
|
|||
self.executeBadData(data)
|
||||
|
||||
|
||||
@decl_endpoint('/api/oss/relocate-constituents', method='post')
|
||||
@decl_endpoint('/api/oss/{item}/relocate-constituents', method='post')
|
||||
def test_relocate_constituents(self):
|
||||
self.set_params(item=self.owned_id)
|
||||
self.populateData()
|
||||
self.ks1X2 = self.ks1.insert_last('X2', convention='test')
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from rest_framework.response import Response
|
|||
|
||||
from apps.library.models import LibraryItem, LibraryItemType
|
||||
from apps.library.serializers import LibraryItemSerializer
|
||||
from apps.oss.models import PropagationFacade
|
||||
from apps.rsform.models import Constituenta, RSFormCached
|
||||
from apps.rsform.serializers import CstTargetSerializer
|
||||
from shared import messages as msg
|
||||
|
|
@ -291,7 +292,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
'height': position['height']
|
||||
})
|
||||
m.Layout.update_data(pk, layout)
|
||||
m.OperationSchema.create_input(item, new_operation)
|
||||
m.OperationSchema.create_input(item.pk, new_operation)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
|
|
@ -420,7 +421,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
schema_clone.access_policy = item.access_policy
|
||||
schema_clone.location = item.location
|
||||
schema_clone.save()
|
||||
RSFormCached(schema_clone).insert_from(prototype.pk)
|
||||
RSFormCached(schema_clone.pk).insert_from(prototype.pk)
|
||||
|
||||
new_operation.result = schema_clone
|
||||
new_operation.save(update_fields=["result"])
|
||||
|
|
@ -544,7 +545,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
operation: m.Operation = cast(m.Operation, serializer.validated_data['target'])
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss = PropagationFacade.get_oss(item.pk)
|
||||
if 'layout' in serializer.validated_data:
|
||||
layout = serializer.validated_data['layout']
|
||||
m.Layout.update_data(pk, layout)
|
||||
|
|
@ -599,12 +600,12 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
layout = [x for x in layout if x['nodeID'] != 'o' + str(operation.pk)]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss = PropagationFacade.get_oss(item.pk)
|
||||
oss.delete_operation(operation.pk, serializer.validated_data['keep_constituents'])
|
||||
m.Layout.update_data(pk, layout)
|
||||
if old_schema is not None:
|
||||
if serializer.validated_data['delete_schema']:
|
||||
m.PropagationFacade.before_delete_schema(old_schema)
|
||||
m.PropagationFacade.before_delete_schema(old_schema.pk)
|
||||
old_schema.delete()
|
||||
elif old_schema.is_synced(item):
|
||||
old_schema.visible = True
|
||||
|
|
@ -640,7 +641,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
layout = [x for x in layout if x['nodeID'] != 'o' + str(operation.pk)]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss = PropagationFacade.get_oss(item.pk)
|
||||
m.Layout.update_data(pk, layout)
|
||||
oss.delete_replica(operation.pk, keep_connections, keep_constituents)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
|
@ -680,13 +681,13 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
|
||||
with transaction.atomic():
|
||||
m.Layout.update_data(pk, layout)
|
||||
schema = m.OperationSchema.create_input(item, operation)
|
||||
schema = m.OperationSchema.create_input(item.pk, operation)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data={
|
||||
'new_schema': LibraryItemSerializer(schema.model).data,
|
||||
'new_schema': LibraryItemSerializer(schema).data,
|
||||
'oss': s.OperationSchemaSerializer(item).data
|
||||
}
|
||||
)
|
||||
|
|
@ -726,7 +727,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
old_schema = target_operation.result
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss = PropagationFacade.get_oss(item.pk)
|
||||
if old_schema is not None:
|
||||
if old_schema.is_synced(item):
|
||||
old_schema.visible = True
|
||||
|
|
@ -769,7 +770,7 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
layout = serializer.validated_data['layout']
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(item)
|
||||
oss = PropagationFacade.get_oss(item.pk)
|
||||
oss.execute_operation(operation)
|
||||
m.Layout.update_data(pk, layout)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
|
@ -823,24 +824,26 @@ class OssViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retriev
|
|||
c.HTTP_404_NOT_FOUND: None
|
||||
}
|
||||
)
|
||||
@action(detail=False, methods=['post'], url_path='relocate-constituents')
|
||||
def relocate_constituents(self, request: Request) -> Response:
|
||||
@action(detail=True, methods=['post'], url_path='relocate-constituents')
|
||||
def relocate_constituents(self, request: Request, pk) -> Response:
|
||||
''' Relocate constituents from one schema to another. '''
|
||||
item = self._get_item()
|
||||
serializer = s.RelocateConstituentsSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
data = serializer.validated_data
|
||||
ids = [cst.pk for cst in data['items']]
|
||||
|
||||
with transaction.atomic():
|
||||
oss = m.OperationSchemaCached(LibraryItem.objects.get(pk=data['oss']))
|
||||
source = RSFormCached(LibraryItem.objects.get(pk=data['source']))
|
||||
destination = RSFormCached(LibraryItem.objects.get(pk=data['destination']))
|
||||
oss = PropagationFacade.get_oss(item.pk)
|
||||
source = RSFormCached(data['source'])
|
||||
destination = RSFormCached(data['destination'])
|
||||
if data['move_down']:
|
||||
oss.relocate_down(source, destination, ids)
|
||||
m.PropagationFacade.before_delete_cst(data['source'], ids)
|
||||
m.PropagationFacade.before_delete_cst(source.pk, ids)
|
||||
source.delete_cst(ids)
|
||||
else:
|
||||
new_items = oss.relocate_up(source, destination, ids)
|
||||
m.PropagationFacade.after_create_cst(destination, new_items, exclude=[oss.model.pk])
|
||||
m.PropagationFacade.after_create_cst(destination, new_items, exclude=[oss.pk])
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(status=c.HTTP_200_OK)
|
||||
|
|
|
|||
|
|
@ -20,21 +20,15 @@ from .RSForm import DELETED_ALIAS, RSForm
|
|||
class RSFormCached:
|
||||
''' RSForm cached. Caching allows to avoid querying for each method call. '''
|
||||
|
||||
def __init__(self, model: LibraryItem):
|
||||
self.model = model
|
||||
def __init__(self, item_id: int):
|
||||
self.pk = item_id
|
||||
self.cache: _RSFormCache = _RSFormCache(self)
|
||||
|
||||
@staticmethod
|
||||
def create(**kwargs) -> 'RSFormCached':
|
||||
''' Create LibraryItem via RSForm. '''
|
||||
model = LibraryItem.objects.create(item_type=LibraryItemType.RSFORM, **kwargs)
|
||||
return RSFormCached(model)
|
||||
|
||||
@staticmethod
|
||||
def from_id(pk: int) -> 'RSFormCached':
|
||||
''' Get LibraryItem by pk. '''
|
||||
model = LibraryItem.objects.get(pk=pk)
|
||||
return RSFormCached(model)
|
||||
return RSFormCached(model.pk)
|
||||
|
||||
def get_dependant(self, target: Iterable[int]) -> set[int]:
|
||||
''' Get list of constituents depending on target (only 1st degree). '''
|
||||
|
|
@ -51,7 +45,7 @@ class RSFormCached:
|
|||
|
||||
def constituentsQ(self) -> QuerySet[Constituenta]:
|
||||
''' Get QuerySet containing all constituents of current RSForm. '''
|
||||
return Constituenta.objects.filter(schema=self.model)
|
||||
return Constituenta.objects.filter(schema_id=self.pk)
|
||||
|
||||
def insert_last(
|
||||
self,
|
||||
|
|
@ -62,9 +56,9 @@ class RSFormCached:
|
|||
''' Insert new constituenta at last position. '''
|
||||
if cst_type is None:
|
||||
cst_type = guess_type(alias)
|
||||
position = Constituenta.objects.filter(schema=self.model).count()
|
||||
position = Constituenta.objects.filter(schema_id=self.pk).count()
|
||||
result = Constituenta.objects.create(
|
||||
schema=self.model,
|
||||
schema_id=self.pk,
|
||||
order=position,
|
||||
alias=alias,
|
||||
cst_type=cst_type,
|
||||
|
|
@ -83,7 +77,7 @@ class RSFormCached:
|
|||
RSForm.shift_positions(position, 1, self.cache.constituents)
|
||||
|
||||
result = Constituenta.objects.create(
|
||||
schema=self.model,
|
||||
schema_id=self.pk,
|
||||
order=position,
|
||||
alias=data['alias'],
|
||||
cst_type=data['cst_type'],
|
||||
|
|
@ -160,7 +154,7 @@ class RSFormCached:
|
|||
new_constituents = deepcopy(items)
|
||||
for cst in new_constituents:
|
||||
cst.pk = None
|
||||
cst.schema = self.model
|
||||
cst.schema_id = self.pk
|
||||
cst.order = position
|
||||
if mapping_alias:
|
||||
cst.alias = mapping_alias[cst.alias]
|
||||
|
|
@ -263,7 +257,7 @@ class RSFormCached:
|
|||
deleted.append(original)
|
||||
replacements.append(substitution.pk)
|
||||
|
||||
attributions = list(Attribution.objects.filter(container__schema=self.model))
|
||||
attributions = list(Attribution.objects.filter(container__schema_id=self.pk))
|
||||
if attributions:
|
||||
orig_to_sub = {original.pk: substitution.pk for original, substitution in substitutions}
|
||||
orig_pks = set(orig_to_sub.keys())
|
||||
|
|
@ -374,7 +368,7 @@ class RSFormCached:
|
|||
prefix = get_type_prefix(cst_type)
|
||||
for text in expressions:
|
||||
new_item = Constituenta.objects.create(
|
||||
schema=self.model,
|
||||
schema_id=self.pk,
|
||||
order=position,
|
||||
alias=f'{prefix}{free_index}',
|
||||
definition_formal=text,
|
||||
|
|
@ -392,7 +386,7 @@ class RSFormCached:
|
|||
cst_list: Iterable[Constituenta] = []
|
||||
if not self.cache.is_loaded:
|
||||
cst_list = Constituenta.objects \
|
||||
.filter(schema=self.model, cst_type=cst_type) \
|
||||
.filter(schema_id=self.pk, cst_type=cst_type) \
|
||||
.only('alias')
|
||||
else:
|
||||
cst_list = [cst for cst in self.cache.constituents if cst.cst_type == cst_type]
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class RSFormTRSSerializer(serializers.Serializer):
|
|||
result['description'] = data.get('description', '')
|
||||
if 'id' in data:
|
||||
result['id'] = data['id']
|
||||
self.instance = RSFormCached.from_id(result['id'])
|
||||
self.instance = RSFormCached(result['id'])
|
||||
return result
|
||||
|
||||
def validate(self, attrs: dict):
|
||||
|
|
@ -151,7 +151,7 @@ class RSFormTRSSerializer(serializers.Serializer):
|
|||
for cst_data in validated_data['items']:
|
||||
cst = Constituenta(
|
||||
alias=cst_data['alias'],
|
||||
schema=self.instance.model,
|
||||
schema_id=self.instance.pk,
|
||||
order=order,
|
||||
cst_type=cst_data['cstType'],
|
||||
)
|
||||
|
|
@ -163,12 +163,13 @@ class RSFormTRSSerializer(serializers.Serializer):
|
|||
|
||||
@transaction.atomic
|
||||
def update(self, instance: RSFormCached, validated_data) -> RSFormCached:
|
||||
model = LibraryItem.objects.get(pk=instance.pk)
|
||||
if 'alias' in validated_data:
|
||||
instance.model.alias = validated_data['alias']
|
||||
model.alias = validated_data['alias']
|
||||
if 'title' in validated_data:
|
||||
instance.model.title = validated_data['title']
|
||||
model.title = validated_data['title']
|
||||
if 'description' in validated_data:
|
||||
instance.model.description = validated_data['description']
|
||||
model.description = validated_data['description']
|
||||
|
||||
order = 0
|
||||
prev_constituents = instance.constituentsQ()
|
||||
|
|
@ -185,7 +186,7 @@ class RSFormTRSSerializer(serializers.Serializer):
|
|||
else:
|
||||
cst = Constituenta(
|
||||
alias=cst_data['alias'],
|
||||
schema=instance.model,
|
||||
schema_id=instance.pk,
|
||||
order=order,
|
||||
cst_type=cst_data['cstType'],
|
||||
)
|
||||
|
|
@ -199,7 +200,7 @@ class RSFormTRSSerializer(serializers.Serializer):
|
|||
prev_cst.delete()
|
||||
|
||||
instance.resolve_all_text()
|
||||
instance.model.save()
|
||||
model.save()
|
||||
return instance
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
insert_after = data['insert_after']
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSFormCached(item)
|
||||
schema = m.RSFormCached(item.pk)
|
||||
new_cst = schema.create_cst(data, insert_after)
|
||||
PropagationFacade.after_create_cst(schema, [new_cst])
|
||||
item.save(update_fields=['time_update'])
|
||||
|
|
@ -125,7 +125,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
data = serializer.validated_data['item_data']
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSFormCached(item)
|
||||
schema = m.RSFormCached(item.pk)
|
||||
old_data = schema.update_cst(cst.pk, data)
|
||||
PropagationFacade.after_update_cst(schema, cst.pk, data, old_data)
|
||||
if 'alias' in data and data['alias'] != cst.alias:
|
||||
|
|
@ -208,7 +208,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
)
|
||||
|
||||
with transaction.atomic():
|
||||
schema = m.RSFormCached(item)
|
||||
schema = m.RSFormCached(item.pk)
|
||||
new_cst = schema.produce_structure(cst, cst_parse)
|
||||
PropagationFacade.after_create_cst(schema, new_cst)
|
||||
item.save(update_fields=['time_update'])
|
||||
|
|
@ -456,7 +456,7 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
|
|||
item = self._get_item()
|
||||
|
||||
with transaction.atomic():
|
||||
m.OrderManager(m.RSFormCached(item)).restore_order()
|
||||
m.OrderManager(m.RSFormCached(item.pk)).restore_order()
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
|
|
@ -731,7 +731,8 @@ def inline_synthesis(request: Request) -> HttpResponse:
|
|||
serializer = s.InlineSynthesisSerializer(data=request.data, context={'user': request.user})
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
receiver = m.RSFormCached(serializer.validated_data['receiver'])
|
||||
item = cast(LibraryItem, serializer.validated_data['receiver'])
|
||||
receiver = m.RSFormCached(item.pk)
|
||||
target_cst = cast(list[m.Constituenta], serializer.validated_data['items'])
|
||||
source = cast(LibraryItem, serializer.validated_data['source'])
|
||||
target_ids = [item.pk for item in target_cst] if target_cst else None
|
||||
|
|
@ -752,11 +753,11 @@ def inline_synthesis(request: Request) -> HttpResponse:
|
|||
replacement = mapping_ids[replacement.pk]
|
||||
substitutions.append((original, replacement))
|
||||
|
||||
PropagationFacade.before_substitute(receiver.model.pk, substitutions)
|
||||
PropagationFacade.before_substitute(receiver.pk, substitutions)
|
||||
receiver.substitute(substitutions)
|
||||
receiver.model.save(update_fields=['time_update'])
|
||||
item.save(update_fields=['time_update'])
|
||||
|
||||
return Response(
|
||||
status=c.HTTP_200_OK,
|
||||
data=s.RSFormParseSerializer(receiver.model).data
|
||||
data=s.RSFormParseSerializer(item).data
|
||||
)
|
||||
|
|
|
|||
|
|
@ -215,9 +215,9 @@ export const ossApi = {
|
|||
}
|
||||
}),
|
||||
|
||||
relocateConstituents: (data: IRelocateConstituentsDTO) =>
|
||||
relocateConstituents: ({ itemID, data }: { itemID: number; data: IRelocateConstituentsDTO }) =>
|
||||
axiosPost<IRelocateConstituentsDTO>({
|
||||
endpoint: `/api/oss/relocate-constituents`,
|
||||
endpoint: `/api/oss/${itemID}/relocate-constituents`,
|
||||
request: {
|
||||
data: data,
|
||||
successMessage: infoMsg.changesSaved
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ export const useRelocateConstituents = () => {
|
|||
onError: () => client.invalidateQueries()
|
||||
});
|
||||
return {
|
||||
relocateConstituents: (data: IRelocateConstituentsDTO) => mutation.mutateAsync(data)
|
||||
relocateConstituents: (data: { itemID: number; data: IRelocateConstituentsDTO }) => mutation.mutateAsync(data)
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -106,13 +106,13 @@ export function DlgRelocateConstituents() {
|
|||
function onSubmit(data: IRelocateConstituentsDTO) {
|
||||
data.items = moveTarget;
|
||||
if (!layout || JSON.stringify(layout) === JSON.stringify(oss.layout)) {
|
||||
return relocateConstituents(data);
|
||||
return relocateConstituents({ itemID: oss.id, data: data });
|
||||
} else {
|
||||
return updatePositions({
|
||||
isSilent: true,
|
||||
itemID: oss.id,
|
||||
data: layout
|
||||
}).then(() => relocateConstituents(data));
|
||||
}).then(() => relocateConstituents({ itemID: oss.id, data: data }));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user