Support query by task state in projects.get_tasks_parents, return task project names

This commit is contained in:
allegroai 2021-01-05 19:02:48 +02:00
parent d7ddfde26e
commit 16430a6636
6 changed files with 126 additions and 43 deletions

View File

@ -1,7 +1,8 @@
from jsonmodels import models, fields from jsonmodels import models, fields
from apiserver.apimodels import ListField from apiserver.apimodels import ListField, ActualEnumField
from apiserver.apimodels.organization import TagsRequest from apiserver.apimodels.organization import TagsRequest
from apiserver.database.model import EntityVisibility
class ProjectReq(models.Base): class ProjectReq(models.Base):
@ -19,3 +20,5 @@ class ProjectTagsRequest(TagsRequest):
class ProjectTaskParentsRequest(ProjectReq): class ProjectTaskParentsRequest(ProjectReq):
projects = ListField(str) projects = ListField(str)
tasks_state = ActualEnumField(EntityVisibility)

View File

@ -1,11 +1,12 @@
from collections import defaultdict from collections import defaultdict
from enum import Enum from enum import Enum
from operator import itemgetter from operator import itemgetter
from typing import Sequence, Dict from typing import Sequence, Dict, Optional
from mongoengine import Q from mongoengine import Q
from apiserver.config_repo import config from apiserver.config_repo import config
from apiserver.database.model import EntityVisibility
from apiserver.database.model.model import Model from apiserver.database.model.model import Model
from apiserver.database.model.task.task import Task from apiserver.database.model.task.task import Task
from apiserver.redis_manager import redman from apiserver.redis_manager import redman
@ -67,7 +68,10 @@ class OrgBLL:
@classmethod @classmethod
def get_parent_tasks( def get_parent_tasks(
cls, company_id: str, projects: Sequence[str] cls,
company_id: str,
projects: Sequence[str],
state: Optional[EntityVisibility] = None,
) -> Sequence[dict]: ) -> Sequence[dict]:
""" """
Get list of unique parent tasks sorted by task name for the passed company projects Get list of unique parent tasks sorted by task name for the passed company projects
@ -76,12 +80,19 @@ class OrgBLL:
query = Q(company=company_id) query = Q(company=company_id)
if projects: if projects:
query &= Q(project__in=projects) query &= Q(project__in=projects)
if state == EntityVisibility.archived:
query &= Q(system_tags__in=[EntityVisibility.archived.value])
elif state == EntityVisibility.active:
query &= Q(system_tags__nin=[EntityVisibility.archived.value])
parent_ids = set(Task.objects(query).distinct("parent")) parent_ids = set(Task.objects(query).distinct("parent"))
if not parent_ids: if not parent_ids:
return [] return []
parents = [ parents = Task.get_many_with_join(
{"id": task.id, "name": task.name} company_id,
for task in Task.objects(id__in=parent_ids).only("id", "name") query=Q(id__in=parent_ids),
] allow_public=True,
override_projection=("id", "name", "project.name"),
)
return sorted(parents, key=itemgetter("name")) return sorted(parents, key=itemgetter("name"))

View File

@ -650,6 +650,12 @@ get_task_parents {
type: array type: array
items { type: string } items { type: string }
} }
tasks_state {
description: "Return parents for tasks in the specified state. If Null is provided, parents for all task states will be returned."
type: string
enum: [ active, archived ]
default: active
}
} }
} }
response { response {
@ -669,6 +675,17 @@ get_task_parents {
description: "The name of the parent task" description: "The name of the parent task"
type: string type: string
} }
project {
type: object
id {
description: "The ID of the parent task project"
type: string
}
name {
description: "The name of the parent task project"
type: string
}
}
} }
} }
} }

View File

@ -429,7 +429,6 @@ def get_tags(call: APICall, company, request: ProjectTagsRequest):
"projects.make_public", min_version="2.9", request_data_model=MakePublicRequest "projects.make_public", min_version="2.9", request_data_model=MakePublicRequest
) )
def make_public(call: APICall, company_id, request: MakePublicRequest): def make_public(call: APICall, company_id, request: MakePublicRequest):
with translate_errors_context():
call.result.data = Project.set_public( call.result.data = Project.set_public(
company_id, ids=request.ids, invalid_cls=InvalidProjectId, enabled=True company_id, ids=request.ids, invalid_cls=InvalidProjectId, enabled=True
) )
@ -439,7 +438,6 @@ def make_public(call: APICall, company_id, request: MakePublicRequest):
"projects.make_private", min_version="2.9", request_data_model=MakePublicRequest "projects.make_private", min_version="2.9", request_data_model=MakePublicRequest
) )
def make_public(call: APICall, company_id, request: MakePublicRequest): def make_public(call: APICall, company_id, request: MakePublicRequest):
with translate_errors_context():
call.result.data = Project.set_public( call.result.data = Project.set_public(
company_id, ids=request.ids, invalid_cls=InvalidProjectId, enabled=False company_id, ids=request.ids, invalid_cls=InvalidProjectId, enabled=False
) )
@ -454,5 +452,7 @@ def get_task_parents(
call: APICall, company_id: str, request: ProjectTaskParentsRequest call: APICall, company_id: str, request: ProjectTaskParentsRequest
): ):
call.result.data = { call.result.data = {
"parents": org_bll.get_parent_tasks(company_id, projects=request.projects) "parents": org_bll.get_parent_tasks(
company_id, projects=request.projects, state=request.tasks_state
)
} }

View File

@ -7,33 +7,6 @@ class TestProjectTags(TestService):
def setUp(self, version="2.12"): def setUp(self, version="2.12"):
super().setUp(version=version) super().setUp(version=version)
def test_task_parent(self):
# stand alone task
parent_sa_name = "Test parent parent standalone"
parent_sa = self.new_task(name=parent_sa_name)
self.new_task(name="Test parent task standalone", parent=parent_sa)
# tasks in projects
parent_name = "Test parent parent"
parent = self.new_task(name=parent_name)
p1 = self.create_temp("projects", name="Test parents1", description="test")
self.new_task(project=p1, name="Test parent task1", parent=parent)
p2 = self.create_temp("projects", name="Test parents2", description="test")
self.new_task(project=p1, name="Test parent task2", parent=parent)
parents = self.api.projects.get_task_parents(projects=[p1, p2]).parents
self.assertEqual([{"id": parent, "name": parent_name}], parents)
res = self.api.projects.get_task_parents()
parents = [p for p in res.parents if p.id in (parent, parent_sa)]
self.assertEqual(
[
{"id": parent, "name": parent_name},
{"id": parent_sa, "name": parent_sa_name},
],
parents,
)
def test_project_tags(self): def test_project_tags(self):
tags_1 = ["Test tag 1", "Test tag 2"] tags_1 = ["Test tag 1", "Test tag 2"]
tags_2 = ["Test tag 3", "Test tag 4"] tags_2 = ["Test tag 3", "Test tag 4"]

View File

@ -0,0 +1,79 @@
from apiserver.tests.automated import TestService
class TestTaskParent(TestService):
def setUp(self, version="2.12"):
super().setUp(version=version)
def test_query_by_project(self):
# stand alone task
parent_sa_name = "Test parent parent standalone"
parent_sa = self.new_task(name=parent_sa_name)
self.new_task(name="Test parent task standalone", parent=parent_sa)
# tasks in projects
project_name = "Test parents project"
project = self.create_temp("projects", name=project_name, description="test")
parent_name = "Test parent parent"
parent = self.new_task(project=project, name=parent_name)
self.new_task(project=project, name="Test parent task1", parent=parent)
self.new_task(project=project, name="Test parent task2", parent=parent)
parents = self.api.projects.get_task_parents(projects=[project]).parents
self.assertEqual(
[
{
"id": parent,
"name": parent_name,
"project": {"id": project, "name": project_name},
}
],
parents,
)
res = self.api.projects.get_task_parents()
parents = [p for p in res.parents if p.id in (parent, parent_sa)]
self.assertEqual(
[
{
"id": parent,
"name": parent_name,
"project": {"id": project, "name": project_name},
},
{"id": parent_sa, "name": parent_sa_name},
],
parents,
)
def test_query_by_state(self):
project_name = "Test parents project"
project = self.create_temp("projects", name=project_name, description="test")
parent1_name = "Test parent parent1"
parent1 = self.new_task(project=project, name=parent1_name)
t1 = self.new_task(project=project, name="Test parent task1", parent=parent1)
parent2_name = "Test parent parent2"
parent2 = self.new_task(project=project, name=parent2_name)
t2 = self.new_task(project=project, name="Test parent task2", parent=parent2)
self.api.tasks.archive(tasks=[t2])
# No state filter
parents = self.api.projects.get_task_parents(projects=[project]).parents
self.assertEqual([parent1, parent2], [p.id for p in parents])
# Active tasks
parents = self.api.projects.get_task_parents(projects=[project], tasks_state="active").parents
self.assertEqual([parent1], [p.id for p in parents])
# Archived tasks
parents = self.api.projects.get_task_parents(projects=[project], tasks_state="archived").parents
self.assertEqual([parent2], [p.id for p in parents])
def new_task(self, **kwargs):
self.update_missing(
kwargs, type="testing", name="test project tags", input=dict(view=dict())
)
return self.create_temp("tasks", **kwargs)