fixes to make the last commit work (asside from applying changes)
This commit is contained in:
parent
174866c2fd
commit
f2f0b9fdae
7 changed files with 32 additions and 18 deletions
|
@ -4,7 +4,8 @@ from django.apps import apps
|
||||||
|
|
||||||
from c3nav.api.schema import BaseSchema
|
from c3nav.api.schema import BaseSchema
|
||||||
from c3nav.editor.operations import DatabaseOperationCollection, CreateObjectOperation, UpdateObjectOperation, \
|
from c3nav.editor.operations import DatabaseOperationCollection, CreateObjectOperation, UpdateObjectOperation, \
|
||||||
DeleteObjectOperation, ClearManyToManyOperation, FieldValuesDict, ObjectReference, PreviousObjectCollection
|
DeleteObjectOperation, ClearManyToManyOperation, FieldValuesDict, ObjectReference, PreviousObjectCollection, \
|
||||||
|
DatabaseOperation
|
||||||
from c3nav.mapdata.fields import I18nField
|
from c3nav.mapdata.fields import I18nField
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,14 +34,18 @@ class ChangedObjectCollection(BaseSchema):
|
||||||
objects: dict[str, dict[int, ChangedObject]] = {}
|
objects: dict[str, dict[int, ChangedObject]] = {}
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
yield from chain(*(objects.keys() for model, objects in self.objects.items()))
|
yield from chain(*(objects.values() for model, objects in self.objects.items()))
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return sum(len(v) for v in self.objects.values())
|
||||||
|
|
||||||
def add_operations(self, operations: DatabaseOperationCollection):
|
def add_operations(self, operations: DatabaseOperationCollection):
|
||||||
"""
|
"""
|
||||||
Add the given operations, creating/updating changed objects to represent the resulting state.
|
Add the given operations, creating/updating changed objects to represent the resulting state.
|
||||||
"""
|
"""
|
||||||
# todo: merge prev
|
# todo: if something is being changed back, remove it from thingy?
|
||||||
for operation in operations.operations:
|
self.prev.add_other(operations.prev)
|
||||||
|
for operation in operations:
|
||||||
changed_object = self.objects.setdefault(operation.obj.model, {}).get(operation.obj.id, None)
|
changed_object = self.objects.setdefault(operation.obj.model, {}).get(operation.obj.id, None)
|
||||||
if changed_object is None:
|
if changed_object is None:
|
||||||
changed_object = ChangedObject(obj=operation.obj,
|
changed_object = ChangedObject(obj=operation.obj,
|
||||||
|
|
|
@ -43,7 +43,8 @@ class ChangeSet(models.Model):
|
||||||
related_name='assigned_changesets', verbose_name=_('assigned to'))
|
related_name='assigned_changesets', verbose_name=_('assigned to'))
|
||||||
map_update = models.OneToOneField(MapUpdate, null=True, related_name='changeset',
|
map_update = models.OneToOneField(MapUpdate, null=True, related_name='changeset',
|
||||||
verbose_name=_('map update'), on_delete=models.PROTECT)
|
verbose_name=_('map update'), on_delete=models.PROTECT)
|
||||||
changes: ChangedObjectCollection = SchemaField(schema=ChangedObjectCollection, default=ChangedObjectCollection)
|
changes: ChangedObjectCollection = SchemaField(schema=ChangedObjectCollection,
|
||||||
|
default=lambda: ChangedObjectCollection)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('Change Set')
|
verbose_name = _('Change Set')
|
||||||
|
@ -164,7 +165,7 @@ class ChangeSet(models.Model):
|
||||||
return self.can_edit(request) and self.state == 'unproposed'
|
return self.can_edit(request) and self.state == 'unproposed'
|
||||||
|
|
||||||
def can_propose(self, request):
|
def can_propose(self, request):
|
||||||
return self.can_edit(request) and not self.proposed and self.changes.operations
|
return self.can_edit(request) and not self.proposed and self.changes
|
||||||
|
|
||||||
def can_unpropose(self, request):
|
def can_unpropose(self, request):
|
||||||
return self.author_id == request.user.pk and self.state in ('proposed', 'reproposed')
|
return self.author_id == request.user.pk and self.state in ('proposed', 'reproposed')
|
||||||
|
@ -347,8 +348,7 @@ class ChangeSet(models.Model):
|
||||||
"""
|
"""
|
||||||
Get the number of changed objects.
|
Get the number of changed objects.
|
||||||
"""
|
"""
|
||||||
return len([changed_object for changed_object in self.changes.changed_objects
|
return len(self.changes)
|
||||||
if changed_object.obj.model != "locationredirect"])
|
|
||||||
|
|
||||||
def get_changed_objects_by_model(self, model):
|
def get_changed_objects_by_model(self, model):
|
||||||
if isinstance(model, str):
|
if isinstance(model, str):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Annotated, Literal, Union, TypeAlias, Any
|
from typing import Annotated, Literal, Union, TypeAlias, Any, Self
|
||||||
from uuid import UUID, uuid4
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
@ -70,6 +70,10 @@ class PreviousObjectCollection(BaseSchema):
|
||||||
titles=titles,
|
titles=titles,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def add_other(self, other: Self):
|
||||||
|
for key in set(self.objects.keys()) | set(other.objects.keys()):
|
||||||
|
self.objects[key] = {**other.objects.get(key, {}), **self.objects.get(key, {})}
|
||||||
|
|
||||||
|
|
||||||
class BaseOperation(BaseSchema):
|
class BaseOperation(BaseSchema):
|
||||||
obj: ObjectReference
|
obj: ObjectReference
|
||||||
|
@ -194,10 +198,16 @@ class DatabaseOperationCollection(BaseSchema):
|
||||||
Iterable as a list of DatabaseOperation instances.
|
Iterable as a list of DatabaseOperation instances.
|
||||||
"""
|
"""
|
||||||
prev: PreviousObjectCollection = PreviousObjectCollection()
|
prev: PreviousObjectCollection = PreviousObjectCollection()
|
||||||
operations: list[DatabaseOperation] = []
|
_operations: list[DatabaseOperation] = []
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
yield from self.operations
|
yield from self._operations
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._operations)
|
||||||
|
|
||||||
|
def append(self, item: DatabaseOperation):
|
||||||
|
self._operations.append(item)
|
||||||
|
|
||||||
def prefetch(self) -> "PrefetchedDatabaseOperationCollection":
|
def prefetch(self) -> "PrefetchedDatabaseOperationCollection":
|
||||||
return PrefetchedDatabaseOperationCollection(operations=self, instances=self.prev.get_instances())
|
return PrefetchedDatabaseOperationCollection(operations=self, instances=self.prev.get_instances())
|
||||||
|
@ -210,7 +220,7 @@ class PrefetchedDatabaseOperationCollection:
|
||||||
|
|
||||||
def apply(self):
|
def apply(self):
|
||||||
# todo: what if unique constraint error occurs?
|
# todo: what if unique constraint error occurs?
|
||||||
for operation in self.operations.operations:
|
for operation in self.operations:
|
||||||
if isinstance(operation, CreateObjectOperation):
|
if isinstance(operation, CreateObjectOperation):
|
||||||
self.instances[operation.obj] = operation.apply_create()
|
self.instances[operation.obj] = operation.apply_create()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -34,8 +34,7 @@ class DatabaseOverlayManager:
|
||||||
"""
|
"""
|
||||||
This class handles the currently active database overlay and will apply and/or intercept changes.
|
This class handles the currently active database overlay and will apply and/or intercept changes.
|
||||||
"""
|
"""
|
||||||
prev: PreviousObjectCollection = PreviousObjectCollection()
|
operations: DatabaseOperationCollection = field(default_factory=DatabaseOperationCollection)
|
||||||
operations: list[DatabaseOperation] = field(default_factory=list)
|
|
||||||
pre_change_values: dict[ObjectReference, FieldValuesDict] = field(default_factory=dict, init=False, repr=False)
|
pre_change_values: dict[ObjectReference, FieldValuesDict] = field(default_factory=dict, init=False, repr=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -54,7 +53,7 @@ class DatabaseOverlayManager:
|
||||||
operations = DatabaseOperationCollection()
|
operations = DatabaseOperationCollection()
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
manager = DatabaseOverlayManager(prev=copy.deepcopy(operations.prev))
|
manager = DatabaseOverlayManager(operations=DatabaseOperationCollection(prev=operations.prev))
|
||||||
operations.prefetch().apply()
|
operations.prefetch().apply()
|
||||||
overlay_state.manager = manager
|
overlay_state.manager = manager
|
||||||
yield manager
|
yield manager
|
||||||
|
|
|
@ -50,7 +50,7 @@ def accesses_mapdata(func):
|
||||||
changed_geometries.reset()
|
changed_geometries.reset()
|
||||||
with DatabaseOverlayManager.enable(operations=None, commit=writable_method) as manager:
|
with DatabaseOverlayManager.enable(operations=None, commit=writable_method) as manager:
|
||||||
result = func(request, *args, **kwargs)
|
result = func(request, *args, **kwargs)
|
||||||
if manager.new_operations:
|
if manager.operations:
|
||||||
if writable_method:
|
if writable_method:
|
||||||
MapUpdate.objects.create(user=request.user, type='direct_edit')
|
MapUpdate.objects.create(user=request.user, type='direct_edit')
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -218,7 +218,7 @@ def changeset_detail(request, pk):
|
||||||
else:
|
else:
|
||||||
title = next(iter(changed_object.titles.values()))
|
title = next(iter(changed_object.titles.values()))
|
||||||
|
|
||||||
prev_values = changeset.operations.prev.get(changed_object.obj).values
|
prev_values = changeset.changes.prev.get(changed_object.obj).values
|
||||||
|
|
||||||
edit_url = None
|
edit_url = None
|
||||||
if not changed_object.deleted:
|
if not changed_object.deleted:
|
||||||
|
|
|
@ -128,7 +128,7 @@ def space_detail(request, level, pk):
|
||||||
|
|
||||||
|
|
||||||
def get_changeset_exceeded(request):
|
def get_changeset_exceeded(request):
|
||||||
return request.user_permissions.max_changeset_changes <= len(request.changeset.operations.operations)
|
return request.user_permissions.max_changeset_changes <= len(request.changeset.changes)
|
||||||
|
|
||||||
|
|
||||||
@etag(editor_etag_func)
|
@etag(editor_etag_func)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue