Merge pull request #4141 from normanjaeckel/HistoryInformation
Added history information for some motion views.
This commit is contained in:
commit
a83de77180
@ -17,11 +17,12 @@ Core:
|
||||
- Enabled docs for using OpenSlides with Gunicorn and Uvicorn in big
|
||||
mode [#3799, #3817].
|
||||
- Changed format for elements send via autoupdate [#3926].
|
||||
- Fixed autoupdate system for related objects [#4140].
|
||||
- Add a change-id system to get only new elements [#3938].
|
||||
- Switch from Yarn back to npm [#3964].
|
||||
- Added password reset link (password reset via email) [#3914].
|
||||
- Added global history mode [#3977].
|
||||
- Projector Refactor [4119, #4130].
|
||||
- Added global history mode [#3977, #4141].
|
||||
- Projector refactoring [4119, #4130].
|
||||
|
||||
Agenda:
|
||||
- Added viewpoint to assign multiple items to a new parent item [#4037].
|
||||
|
25
openslides/core/migrations/0013_auto_20190119_1641.py
Normal file
25
openslides/core/migrations/0013_auto_20190119_1641.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Generated by Django 2.1.5 on 2019-01-19 15:41
|
||||
|
||||
import jsonfield.encoder
|
||||
import jsonfield.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0012_auto_20190119_1425'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='history',
|
||||
name='restricted',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='history',
|
||||
name='information',
|
||||
field=jsonfield.fields.JSONField(dump_kwargs={'cls': jsonfield.encoder.JSONEncoder, 'separators': (',', ':')}, load_kwargs={}),
|
||||
),
|
||||
]
|
@ -286,7 +286,8 @@ class HistoryManager(models.Manager):
|
||||
element["collection_string"], element["id"]
|
||||
),
|
||||
now=history_time,
|
||||
information=element.get("information", ""),
|
||||
information=element.get("information", []),
|
||||
restricted=element.get("restricted", False),
|
||||
user_id=element.get("user_id"),
|
||||
full_data=data,
|
||||
)
|
||||
@ -334,7 +335,9 @@ class History(RESTModelMixin, models.Model):
|
||||
|
||||
now = models.DateTimeField()
|
||||
|
||||
information = models.CharField(max_length=255)
|
||||
information = JSONField()
|
||||
|
||||
restricted = models.BooleanField(default=False)
|
||||
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, null=True, on_delete=SET_NULL_AND_AUTOUPDATE
|
||||
|
@ -169,5 +169,5 @@ class HistorySerializer(ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = History
|
||||
fields = ("id", "element_id", "now", "information", "user")
|
||||
fields = ("id", "element_id", "now", "information", "restricted", "user")
|
||||
read_only_fields = ("now",)
|
||||
|
@ -124,7 +124,7 @@ class MotionViewSet(ModelViewSet):
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_deleted_data(
|
||||
[(motion.get_collection_string(), motion.pk)],
|
||||
information="Motion deleted",
|
||||
information=["Motion deleted"],
|
||||
user_id=request.user.pk,
|
||||
)
|
||||
|
||||
@ -221,10 +221,16 @@ class MotionViewSet(ModelViewSet):
|
||||
|
||||
# Send new submitters and supporters via autoupdate because users
|
||||
# without permission to see users may not have them but can get it now.
|
||||
# TODO: Skip history.
|
||||
new_users = list(motion.submitters.all())
|
||||
new_users.extend(motion.supporters.all())
|
||||
inform_changed_data(new_users)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["Motion created"], user_id=request.user.pk,
|
||||
)
|
||||
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
# Strip out response data so nobody gets unrestricted data.
|
||||
data = ReturnDict(id=serializer.data.get("id"), serializer=serializer)
|
||||
@ -298,12 +304,13 @@ class MotionViewSet(ModelViewSet):
|
||||
|
||||
# Send new supporters via autoupdate because users
|
||||
# without permission to see users may not have them but can get it now.
|
||||
# TODO: Skip history.
|
||||
new_users = list(updated_motion.supporters.all())
|
||||
inform_changed_data(new_users)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
updated_motion, information="Motion updated", user_id=request.user.pk
|
||||
updated_motion, information=["Motion updated"], user_id=request.user.pk
|
||||
)
|
||||
|
||||
# We do not add serializer.data to response so nobody gets unrestricted data here.
|
||||
@ -396,7 +403,7 @@ class MotionViewSet(ModelViewSet):
|
||||
|
||||
# write log
|
||||
motion.write_log([f"Comment {section.name} updated"], request.user)
|
||||
message = f"Comment {section.name} updated"
|
||||
message = ["Comment {arg1} updated", section.name]
|
||||
else: # DELETE
|
||||
try:
|
||||
comment = MotionComment.objects.get(motion=motion, section=section)
|
||||
@ -407,7 +414,12 @@ class MotionViewSet(ModelViewSet):
|
||||
comment.delete()
|
||||
|
||||
motion.write_log([f"Comment {section.name} deleted"], request.user)
|
||||
message = f"Comment {section.name} deleted"
|
||||
message = ["Comment {arg1} deleted", section.name]
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=message, user_id=request.user.pk, restricted=True,
|
||||
)
|
||||
|
||||
return Response({"detail": message})
|
||||
|
||||
@ -475,7 +487,7 @@ class MotionViewSet(ModelViewSet):
|
||||
motion_result.append(motion)
|
||||
|
||||
# Now inform all clients.
|
||||
inform_changed_data(motion_result)
|
||||
inform_changed_data(motion_result, information=["Submitters changed"], user_id=request.user.pk)
|
||||
|
||||
# Also send all new submitters via autoupdate because users without
|
||||
# permission to see users may not have them but can get it now.
|
||||
@ -512,6 +524,7 @@ class MotionViewSet(ModelViewSet):
|
||||
motion.write_log(["Motion supported"], request.user)
|
||||
# Send new supporter via autoupdate because users without permission
|
||||
# to see users may not have it but can get it now.
|
||||
# TODO: Skip history.
|
||||
inform_changed_data([request.user])
|
||||
message = "You have supported this motion successfully."
|
||||
else:
|
||||
@ -523,6 +536,11 @@ class MotionViewSet(ModelViewSet):
|
||||
motion.write_log(["Motion unsupported"], request.user)
|
||||
message = "You have unsupported this motion successfully."
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["Supporters changed"], user_id=request.user.pk
|
||||
)
|
||||
|
||||
# Initiate response.
|
||||
return Response({"detail": message})
|
||||
|
||||
@ -569,11 +587,10 @@ class MotionViewSet(ModelViewSet):
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
inform_changed_data(
|
||||
motion,
|
||||
information=f"State set to {motion.state.name}.",
|
||||
user_id=request.user.pk,
|
||||
)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(motion, information=["State set to {arg1}", motion.state.name], user_id=request.user.pk)
|
||||
|
||||
return Response({"detail": message})
|
||||
|
||||
@list_route(methods=["post"])
|
||||
@ -640,15 +657,17 @@ class MotionViewSet(ModelViewSet):
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["State set to {arg1}", motion.state.name], user_id=request.user.pk,
|
||||
)
|
||||
|
||||
# Finish motion.
|
||||
motion_result.append(motion)
|
||||
|
||||
# Now inform all clients.
|
||||
inform_changed_data(motion_result)
|
||||
|
||||
# Send response.
|
||||
return Response(
|
||||
{"detail": f"{len(motion_result)} motions successfully updated."}
|
||||
{"detail": f"State of {len(motion_result)} motions successfully set."}
|
||||
)
|
||||
|
||||
@detail_route(methods=["put"])
|
||||
@ -703,7 +722,12 @@ class MotionViewSet(ModelViewSet):
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
inform_changed_data(motion)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["Recommendation set to {arg1}", label], user_id=request.user.pk,
|
||||
)
|
||||
|
||||
return Response({"detail": message})
|
||||
|
||||
@list_route(methods=["post"])
|
||||
@ -784,12 +808,14 @@ class MotionViewSet(ModelViewSet):
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Fire autoupdate and save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["Recommendation set to {arg1}", label], user_id=request.user.pk,
|
||||
)
|
||||
|
||||
# Finish motion.
|
||||
motion_result.append(motion)
|
||||
|
||||
# Now inform all clients.
|
||||
inform_changed_data(motion_result)
|
||||
|
||||
# Send response.
|
||||
return Response(
|
||||
{"detail": f"{len(motion_result)} motions successfully updated."}
|
||||
@ -826,7 +852,8 @@ class MotionViewSet(ModelViewSet):
|
||||
)
|
||||
|
||||
# Now send all changes to the clients.
|
||||
inform_changed_data(motion)
|
||||
inform_changed_data(motion, information=["State set to {arg1}", motion.state.name], user_id=request.user.pk)
|
||||
|
||||
return Response({"detail": "Recommendation followed successfully."})
|
||||
|
||||
@detail_route(methods=["post"])
|
||||
@ -846,7 +873,11 @@ class MotionViewSet(ModelViewSet):
|
||||
raise ValidationError({"detail": err})
|
||||
motion.write_log(["Vote created"], request.user, skip_autoupdate=True)
|
||||
|
||||
inform_changed_data(motion)
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["Vote created"], user_id=request.user.pk,
|
||||
)
|
||||
|
||||
return Response(
|
||||
{"detail": "Vote created successfully.", "createdPollId": poll.pk}
|
||||
)
|
||||
@ -939,6 +970,12 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
response = super().update(*args, **kwargs)
|
||||
poll = self.get_object()
|
||||
poll.motion.write_log(["Vote updated"], self.request.user)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
poll.motion, information=["Poll updated"], user_id=self.request.user.pk
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
def destroy(self, *args, **kwargs):
|
||||
@ -948,6 +985,12 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
poll = self.get_object()
|
||||
result = super().destroy(*args, **kwargs)
|
||||
poll.motion.write_log(["Vote deleted"], self.request.user)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
poll.motion, information=["Poll deleted"], user_id=self.request.user.pk
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@ -1205,7 +1248,7 @@ class CategoryViewSet(ModelViewSet):
|
||||
error_message = "Error: At least one identifier of this category does already exist in another category."
|
||||
response = Response({"detail": error_message}, status=400)
|
||||
else:
|
||||
inform_changed_data(instances)
|
||||
inform_changed_data(instances, information=["Number set"], user_id=request.user.pk)
|
||||
message = f"All motions in category {category} numbered " "successfully."
|
||||
response = Response({"detail": message})
|
||||
return response
|
||||
@ -1251,7 +1294,6 @@ class MotionBlockViewSet(ModelViewSet):
|
||||
its recommendation. It is a POST request without any data.
|
||||
"""
|
||||
motion_block = self.get_object()
|
||||
instances = []
|
||||
with transaction.atomic():
|
||||
for motion in motion_block.motion_set.all():
|
||||
# Follow recommendation.
|
||||
@ -1263,8 +1305,10 @@ class MotionBlockViewSet(ModelViewSet):
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
instances.append(motion)
|
||||
inform_changed_data(instances)
|
||||
# Fire autoupdate and save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion, information=["State set to {arg1}", motion.state.name], user_id=request.user.pk
|
||||
)
|
||||
return Response({"detail": "Followed recommendations successfully."})
|
||||
|
||||
|
||||
|
@ -31,7 +31,8 @@ class Element(ElementBase, total=False):
|
||||
process.
|
||||
"""
|
||||
|
||||
information: str
|
||||
information: List[str]
|
||||
restricted: bool
|
||||
user_id: Optional[int]
|
||||
disable_history: bool
|
||||
reload: bool
|
||||
@ -51,8 +52,9 @@ AutoupdateFormat = TypedDict(
|
||||
|
||||
def inform_changed_data(
|
||||
instances: Union[Iterable[Model], Model],
|
||||
information: str = "",
|
||||
information: List[str] = None,
|
||||
user_id: Optional[int] = None,
|
||||
restricted: bool = False,
|
||||
) -> None:
|
||||
"""
|
||||
Informs the autoupdate system and the caching system about the creation or
|
||||
@ -62,6 +64,8 @@ def inform_changed_data(
|
||||
|
||||
History creation is enabled.
|
||||
"""
|
||||
if information is None:
|
||||
information = []
|
||||
root_instances = set()
|
||||
if not isinstance(instances, Iterable):
|
||||
instances = (instances,)
|
||||
@ -81,6 +85,7 @@ def inform_changed_data(
|
||||
collection_string=root_instance.get_collection_string(),
|
||||
full_data=root_instance.get_full_data(),
|
||||
information=information,
|
||||
restricted=restricted,
|
||||
user_id=user_id,
|
||||
)
|
||||
|
||||
@ -95,8 +100,9 @@ def inform_changed_data(
|
||||
|
||||
def inform_deleted_data(
|
||||
deleted_elements: Iterable[Tuple[str, int]],
|
||||
information: str = "",
|
||||
information: List[str] = None,
|
||||
user_id: Optional[int] = None,
|
||||
restricted: bool = False,
|
||||
) -> None:
|
||||
"""
|
||||
Informs the autoupdate system and the caching system about the deletion of
|
||||
@ -104,6 +110,8 @@ def inform_deleted_data(
|
||||
|
||||
History creation is enabled.
|
||||
"""
|
||||
if information is None:
|
||||
information = []
|
||||
elements: Dict[str, Element] = {}
|
||||
for deleted_element in deleted_elements:
|
||||
key = deleted_element[0] + str(deleted_element[1])
|
||||
@ -112,6 +120,7 @@ def inform_deleted_data(
|
||||
collection_string=deleted_element[0],
|
||||
full_data=None,
|
||||
information=information,
|
||||
restricted=restricted,
|
||||
user_id=user_id,
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user