diff --git a/lib/hawat/view/__init__.py b/lib/hawat/view/__init__.py index e626d3b02d5ef7ea5112de4621b4dc0f90c74214..ed16e442975d9b5328b14a1caec32e37f0677dac 100644 --- a/lib/hawat/view/__init__.py +++ b/lib/hawat/view/__init__.py @@ -1511,6 +1511,23 @@ class ItemActionView(RenderableView): # pylint: disable=locally-disabled,abstra self.dbsession.add(chlog) self.dbsession.commit() + def get_affected_items(self, item, form): + """ + Return dict of hawat.db.MODEL items affected by the change of the item + as keys and their JSON representation before change as value. + (e.g. dict of groups which lost a member after a user item was deleted) + + :param hawat.db.MODEL item: Item that is being changed. + :param flask_wtf.FlaskForm form: Form representing the change. + """ + changed = set() + for attribute in ["memberships", "memberships_wanted", "managements", "members", "members_wanted", "managers"]: + if hasattr(item, attribute): + changed.update(getattr(item, attribute)) + if hasattr(form, attribute): + changed.update(getattr(form, attribute).data) + return { obj: obj.to_json() for obj in changed } + class ItemCreateView(ItemActionView): # pylint: disable=locally-disabled,abstract-method """ @@ -1625,6 +1642,8 @@ class ItemCreateView(ItemActionView): # pylint: disable=locally-disabled,abstra return cancel_response if form.validate_on_submit(): + affected_items = self.get_affected_items(item, form) + form_data = form.data self.response_context.update(form_data = form_data) @@ -1640,6 +1659,10 @@ class ItemCreateView(ItemActionView): # pylint: disable=locally-disabled,abstra # Log the item creation into changelog. self.changelog_log(item, '', item.to_json()) + # Log changes of all affected items into changelog. + for affected_item, json_before in affected_items.items(): + self.changelog_log(affected_item, json_before, affected_item.to_json()) + self.flash( flask.Markup( self.get_message_success(item = item) @@ -1826,6 +1849,8 @@ class ItemCreateForView(ItemActionView): # pylint: disable=locally-disabled,abs return cancel_response if form.validate_on_submit(): + affected_items = self.get_affected_items(item, form) + form_data = form.data self.response_context.update(form_data = form_data) @@ -1842,6 +1867,10 @@ class ItemCreateForView(ItemActionView): # pylint: disable=locally-disabled,abs # Log the item creation into changelog. self.changelog_log(item, '', item.to_json()) + # Log changes of all affected items into changelog. + for affected_item, json_before in affected_items.items(): + self.changelog_log(affected_item, json_before, affected_item.to_json()) + self.flash( flask.Markup(self.get_message_success(item = item, parent = parent)), hawat.const.FLASH_SUCCESS @@ -2116,6 +2145,22 @@ class ItemUpdateView(ItemActionView): # pylint: disable=locally-disabled,abstra ) return breadcrumbs_menu + def get_affected_items(self, item, form): + """ + Return dict of hawat.db.MODEL items affected by the update of the item + as keys and their JSON representation before update as value. + (e.g. dict of groups which lost a member after a user item was updated) + Overrides get_affected_items(self, item, form) in ItemActionView. + + :param hawat.db.MODEL item: Item that is being changed. + :param flask_wtf.FlaskForm form: Form representing the change. + """ + changed = set() + for attribute in ["memberships", "memberships_wanted", "managements", "members", "members_wanted", "managers"]: + if hasattr(item, attribute) and hasattr(form, attribute): + changed.update(set(getattr(item, attribute)).symmetric_difference(set(getattr(form, attribute).data))) + return { obj: obj.to_json() for obj in changed } + def dispatch_request(self, item_id): # pylint: disable=locally-disabled,arguments-differ """ Mandatory interface required by the :py:func:`flask.views.View.dispatch_request`. @@ -2143,6 +2188,8 @@ class ItemUpdateView(ItemActionView): # pylint: disable=locally-disabled,abstra item_json_before = item.to_json() if form.validate_on_submit(): + affected_items = self.get_affected_items(item, form) + form_data = form.data self.response_context.update(form_data = form_data) @@ -2164,6 +2211,10 @@ class ItemUpdateView(ItemActionView): # pylint: disable=locally-disabled,abstra # Log the item update into changelog. self.changelog_log(item, item_json_before, item.to_json()) + # Log changes of all affected items into changelog. + for affected_item, json_before in affected_items.items(): + self.changelog_log(affected_item, json_before, affected_item.to_json()) + self.flash( flask.Markup(self.get_message_success(item = item)), hawat.const.FLASH_SUCCESS @@ -2242,6 +2293,8 @@ class ItemDeleteView(ItemActionView): # pylint: disable=locally-disabled,abstra item_json_before = item.to_json() if form.validate_on_submit(): + affected_items = self.get_affected_items(item, form) + form_data = form.data self.response_context.update(form_data = form_data) @@ -2256,6 +2309,10 @@ class ItemDeleteView(ItemActionView): # pylint: disable=locally-disabled,abstra # Log the item deletion into changelog. self.changelog_log(item, item_json_before, '') + # Log changes of all affected items into changelog. + for affected_item, json_before in affected_items.items(): + self.changelog_log(affected_item, json_before, affected_item.to_json()) + self.flash( flask.Markup(self.get_message_success(item = item)), hawat.const.FLASH_SUCCESS @@ -2544,6 +2601,7 @@ class ItemObjectRelationView(ItemChangeView): # pylint: disable=locally-disable if cancel_response: return cancel_response item_json_before = item.to_json() + other_json_before = other.to_json() if form.validate_on_submit(): form_data = form.data @@ -2562,8 +2620,10 @@ class ItemObjectRelationView(ItemChangeView): # pylint: disable=locally-disable self.dbsession.commit() self.do_after_action(item) - # Log the item change into changelog. + + # Log changes of 'item' and 'other' into changelog. self.changelog_log(item, item_json_before, item.to_json()) + self.changelog_log(other, other_json_before, other.to_json()) self.flash( flask.Markup(