US #50: Neighbors nav for taskboard and kanban

remotes/origin/enhancement/email-actions
ikame 2014-02-27 13:38:51 +01:00
parent 0585ce3162
commit f982da7ebb
3 changed files with 32 additions and 10 deletions

View File

@ -23,7 +23,7 @@ class NeighborsMixin:
if queryset is None:
queryset = type(self).objects.get_queryset()
if not self._get_queryset_order_by(queryset):
queryset = queryset.order_by(*self._meta.ordering)
queryset = queryset.order_by(*self._get_order_by())
queryset = queryset.filter(~Q(id=self.id))
return self._get_previous_neighbor(queryset), self._get_next_neighbor(queryset)
@ -31,6 +31,9 @@ class NeighborsMixin:
def _get_queryset_order_by(self, queryset):
return queryset.query.order_by or []
def _get_order_by(self):
return self._meta.ordering
def _field(self, field):
return getattr(self, field.lstrip("-"))
@ -42,25 +45,36 @@ class NeighborsMixin:
operator = inc
return field, operator
def _format(self, value):
if hasattr(value, "format"):
value = value.format(obj=self)
return value
def _or(self, conditions):
result = Q(**conditions[0])
for condition in conditions:
result = result | Q(**condition)
condition = conditions[0]
result = Q(**{key: self._format(condition[key]) for key in condition})
for condition in conditions[1:]:
result = result | Q(**{key: self._format(condition[key]) for key in condition})
return result
def _get_previous_neighbor(self, queryset):
def _get_prev_neighbor_filters(self, queryset):
conds = [{"{}__{}".format(*self._filter(field, "lt", "gt")): self._field(field)}
for field in self._get_queryset_order_by(queryset)]
return self._or(conds)
def _get_previous_neighbor(self, queryset):
try:
return queryset.filter(self._or(conds)).reverse()[0]
return queryset.filter(self._get_prev_neighbor_filters(queryset)).reverse()[0]
except IndexError:
return None
def _get_next_neighbor(self, queryset):
def _get_next_neighbor_filters(self, queryset):
conds = [{"{}__{}".format(*self._filter(field, "gt", "lt")): self._field(field)}
for field in self._get_queryset_order_by(queryset)]
return self._or(conds)
def _get_next_neighbor(self, queryset):
try:
return queryset.filter(self._or(conds))[0]
return queryset.filter(self._get_next_neighbor_filters(queryset))[0]
except IndexError:
return None

View File

@ -61,7 +61,7 @@ class UserStoryViewSet(NotificationSenderMixin, ModelCrudViewSet):
permission_classes = (IsAuthenticated, permissions.UserStoryPermission)
filter_backends = (filters.IsProjectMemberFilterBackend, filters.TagsFilter)
filter_fields = ['project', 'milestone', 'milestone__isnull']
filter_fields = ['project', 'milestone', 'milestone__isnull', 'status']
create_notification_template = "create_userstory_notification"
update_notification_template = "update_userstory_notification"

View File

@ -100,7 +100,7 @@ class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model):
class Meta:
verbose_name = "user story"
verbose_name_plural = "user stories"
ordering = ["project", "order"]
ordering = ["project", "order", "ref"]
unique_together = ("ref", "project")
permissions = (
("view_userstory", "Can view user story"),
@ -112,6 +112,14 @@ class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model):
def __repr__(self):
return "<UserStory %s>" % (self.id)
def _get_prev_neighbor_filters(self, queryset):
return self._or([{"order__lt": "{obj.order}"},
{"order__lte": "{obj.order}", "ref__lt": "{obj.ref}"}])
def _get_next_neighbor_filters(self, queryset):
return self._or([{"order__gt": "{obj.order}"},
{"order__gte": "{obj.order}", "ref__gt": "{obj.ref}"}])
def get_role_points(self):
return self.role_points