Add basic merge feature to MasterView

This commit is contained in:
Lance Edgar 2016-10-28 10:26:37 -05:00
parent a398a0a710
commit 06b0b13992
3 changed files with 251 additions and 4 deletions

View file

@ -55,6 +55,7 @@ class MasterView(View):
viewable = True
editable = True
deletable = True
mergeable = False
listing = False
creating = False
@ -394,6 +395,70 @@ class MasterView(View):
'instance_title': instance_title,
'form': form})
def get_merge_fields(self):
if hasattr(self, 'merge_fields'):
return self.merge_fields
def get_merge_coalesce_fields(self):
if hasattr(self, 'merge_coalesce_fields'):
return self.merge_coalesce_fields
return []
def merge(self):
"""
Preview and execute a merge of two records.
"""
object_to_remove = object_to_keep = None
if self.request.method == 'POST':
uuids = self.request.POST.get('uuids', '').split(',')
if len(uuids) == 2:
object_to_remove = self.Session.query(self.get_model_class()).get(uuids[0])
object_to_keep = self.Session.query(self.get_model_class()).get(uuids[1])
if object_to_remove and object_to_keep and self.request.POST.get('commit-merge') == 'yes':
msg = unicode(object_to_remove)
try:
self.validate_merge(object_to_remove, object_to_keep)
except Exception as error:
self.request.session.flash("Requested merge cannot proceed (maybe swap keep/remove and try again?): {}".format(error), 'error')
else:
self.merge_objects(object_to_remove, object_to_keep)
self.request.session.flash("{} has been merged into {}".format(msg, object_to_keep))
return self.redirect(self.get_action_url('view', object_to_keep))
if not object_to_remove or not object_to_keep or object_to_remove is object_to_keep:
return self.redirect(self.get_index_url())
remove = self.get_merge_data(object_to_remove)
keep = self.get_merge_data(object_to_keep)
return self.render_to_response('merge', {'object_to_remove': object_to_remove,
'object_to_keep': object_to_keep,
'view_url': lambda obj: self.get_action_url('view', obj),
'merge_fields': self.get_merge_fields(),
'remove_data': remove,
'keep_data': keep,
'resulting_data': self.get_merge_resulting_data(remove, keep)})
def validate_merge(self, removing, keeping):
"""
If applicable, your view should override this in order to confirm that
the requested merge is valid, in your context. If it is not - for *any
reason* - you should raise an exception; the type does not matter.
"""
def get_merge_data(self, obj):
raise NotImplementedError("please implement `{}.get_merge_data()`".format(self.__class__.__name__))
def get_merge_resulting_data(self, remove, keep):
result = dict(keep)
for field in self.get_merge_coalesce_fields():
if remove[field] and not keep[field]:
result[field] = remove[field]
return result
def merge_objects(self, removing, keeping):
raise NotImplementedError("please implement `{}.merge_objects()`".format(self.__class__.__name__))
##############################
# Core Stuff
##############################
@ -635,7 +700,8 @@ class MasterView(View):
'default_sortkey': getattr(self, 'default_sortkey', None),
'sortdir': getattr(self, 'sortdir', 'asc'),
'pageable': self.pageable,
'checkboxes': self.checkboxes,
'checkboxes': self.checkboxes or (
self.mergeable and self.request.has_perm('{}.merge'.format(self.get_permission_prefix()))),
'checked': self.checked,
'row_attrs': self.get_row_attrs,
'cell_attrs': self.get_cell_attrs,
@ -662,8 +728,12 @@ class MasterView(View):
defined; it depends on the type of data the grid deals with.
"""
if callable(self.row_attrs):
return self.row_attrs(row, i)
return self.row_attrs
attrs = self.row_attrs(row, i)
else:
attrs = dict(self.row_attrs)
if self.mergeable:
attrs['data-uuid'] = row.uuid
return attrs
def get_cell_attrs(self, row, column):
"""
@ -1142,6 +1212,14 @@ class MasterView(View):
config.add_tailbone_permission(permission_prefix, '{0}.create'.format(permission_prefix),
"Create new {0}".format(model_title))
# merge
if cls.mergeable:
config.add_route('{}.merge'.format(route_prefix), '{}/merge'.format(url_prefix))
config.add_view(cls, attr='merge', route_name='{}.merge'.format(route_prefix),
permission='{}.merge'.format(permission_prefix))
config.add_tailbone_permission(permission_prefix, '{}.merge'.format(permission_prefix),
"Merge 2 {}".format(model_title_plural))
# view
if cls.viewable:
config.add_tailbone_permission(permission_prefix, '{}.view'.format(permission_prefix),