US #50: Neighbors nav for taskboard and kanban
parent
0585ce3162
commit
f982da7ebb
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue