US #50: Neighbors nav for taskboard and kanban
parent
0585ce3162
commit
f982da7ebb
|
@ -23,7 +23,7 @@ class NeighborsMixin:
|
||||||
if queryset is None:
|
if queryset is None:
|
||||||
queryset = type(self).objects.get_queryset()
|
queryset = type(self).objects.get_queryset()
|
||||||
if not self._get_queryset_order_by(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))
|
queryset = queryset.filter(~Q(id=self.id))
|
||||||
|
|
||||||
return self._get_previous_neighbor(queryset), self._get_next_neighbor(queryset)
|
return self._get_previous_neighbor(queryset), self._get_next_neighbor(queryset)
|
||||||
|
@ -31,6 +31,9 @@ class NeighborsMixin:
|
||||||
def _get_queryset_order_by(self, queryset):
|
def _get_queryset_order_by(self, queryset):
|
||||||
return queryset.query.order_by or []
|
return queryset.query.order_by or []
|
||||||
|
|
||||||
|
def _get_order_by(self):
|
||||||
|
return self._meta.ordering
|
||||||
|
|
||||||
def _field(self, field):
|
def _field(self, field):
|
||||||
return getattr(self, field.lstrip("-"))
|
return getattr(self, field.lstrip("-"))
|
||||||
|
|
||||||
|
@ -42,25 +45,36 @@ class NeighborsMixin:
|
||||||
operator = inc
|
operator = inc
|
||||||
return field, operator
|
return field, operator
|
||||||
|
|
||||||
|
def _format(self, value):
|
||||||
|
if hasattr(value, "format"):
|
||||||
|
value = value.format(obj=self)
|
||||||
|
return value
|
||||||
|
|
||||||
def _or(self, conditions):
|
def _or(self, conditions):
|
||||||
result = Q(**conditions[0])
|
condition = conditions[0]
|
||||||
for condition in conditions:
|
result = Q(**{key: self._format(condition[key]) for key in condition})
|
||||||
result = result | Q(**condition)
|
for condition in conditions[1:]:
|
||||||
|
result = result | Q(**{key: self._format(condition[key]) for key in condition})
|
||||||
return result
|
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)}
|
conds = [{"{}__{}".format(*self._filter(field, "lt", "gt")): self._field(field)}
|
||||||
for field in self._get_queryset_order_by(queryset)]
|
for field in self._get_queryset_order_by(queryset)]
|
||||||
|
return self._or(conds)
|
||||||
|
|
||||||
|
def _get_previous_neighbor(self, queryset):
|
||||||
try:
|
try:
|
||||||
return queryset.filter(self._or(conds)).reverse()[0]
|
return queryset.filter(self._get_prev_neighbor_filters(queryset)).reverse()[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
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)}
|
conds = [{"{}__{}".format(*self._filter(field, "gt", "lt")): self._field(field)}
|
||||||
for field in self._get_queryset_order_by(queryset)]
|
for field in self._get_queryset_order_by(queryset)]
|
||||||
|
return self._or(conds)
|
||||||
|
|
||||||
|
def _get_next_neighbor(self, queryset):
|
||||||
try:
|
try:
|
||||||
return queryset.filter(self._or(conds))[0]
|
return queryset.filter(self._get_next_neighbor_filters(queryset))[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -61,7 +61,7 @@ class UserStoryViewSet(NotificationSenderMixin, ModelCrudViewSet):
|
||||||
permission_classes = (IsAuthenticated, permissions.UserStoryPermission)
|
permission_classes = (IsAuthenticated, permissions.UserStoryPermission)
|
||||||
|
|
||||||
filter_backends = (filters.IsProjectMemberFilterBackend, filters.TagsFilter)
|
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"
|
create_notification_template = "create_userstory_notification"
|
||||||
update_notification_template = "update_userstory_notification"
|
update_notification_template = "update_userstory_notification"
|
||||||
|
|
|
@ -100,7 +100,7 @@ class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "user story"
|
verbose_name = "user story"
|
||||||
verbose_name_plural = "user stories"
|
verbose_name_plural = "user stories"
|
||||||
ordering = ["project", "order"]
|
ordering = ["project", "order", "ref"]
|
||||||
unique_together = ("ref", "project")
|
unique_together = ("ref", "project")
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_userstory", "Can view user story"),
|
("view_userstory", "Can view user story"),
|
||||||
|
@ -112,6 +112,14 @@ class UserStory(NeighborsMixin, WatchedMixin, BlockedMixin, models.Model):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<UserStory %s>" % (self.id)
|
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):
|
def get_role_points(self):
|
||||||
return self.role_points
|
return self.role_points
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue