Adding questions support
parent
7df355d92e
commit
bce92c42f0
|
@ -44,7 +44,6 @@ class ApiRoot(APIView):
|
||||||
'priorities': reverse('priority-list', request=request, format=format),
|
'priorities': reverse('priority-list', request=request, format=format),
|
||||||
'documents': reverse('document-list', request=request, format=format),
|
'documents': reverse('document-list', request=request, format=format),
|
||||||
'questions': reverse('question-list', request=request, format=format),
|
'questions': reverse('question-list', request=request, format=format),
|
||||||
'question_responses': reverse('question-response-list', request=request, format=format),
|
|
||||||
'wiki/pages': reverse('wiki-page-list', request=request, format=format),
|
'wiki/pages': reverse('wiki-page-list', request=request, format=format),
|
||||||
'users': reverse('user-list', request=request, format=format),
|
'users': reverse('user-list', request=request, format=format),
|
||||||
'roles': reverse('user-roles', request=request, format=format),
|
'roles': reverse('user-roles', request=request, format=format),
|
||||||
|
|
|
@ -1,561 +1,601 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
"model": "base.role",
|
"model": "base.role",
|
||||||
"fields": {
|
"fields": {
|
||||||
"permissions": [
|
"permissions": [
|
||||||
[
|
[
|
||||||
"add_logentry",
|
"add_logentry",
|
||||||
"admin",
|
"admin",
|
||||||
"logentry"
|
"logentry"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_logentry",
|
"change_logentry",
|
||||||
"admin",
|
"admin",
|
||||||
"logentry"
|
"logentry"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_logentry",
|
"delete_logentry",
|
||||||
"admin",
|
"admin",
|
||||||
"logentry"
|
"logentry"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_group",
|
"add_group",
|
||||||
"auth",
|
"auth",
|
||||||
"group"
|
"group"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_group",
|
"change_group",
|
||||||
"auth",
|
"auth",
|
||||||
"group"
|
"group"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_group",
|
"delete_group",
|
||||||
"auth",
|
"auth",
|
||||||
"group"
|
"group"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_permission",
|
"add_permission",
|
||||||
"auth",
|
"auth",
|
||||||
"permission"
|
"permission"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_permission",
|
"change_permission",
|
||||||
"auth",
|
"auth",
|
||||||
"permission"
|
"permission"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_permission",
|
"delete_permission",
|
||||||
"auth",
|
"auth",
|
||||||
"permission"
|
"permission"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_role",
|
"add_role",
|
||||||
"base",
|
"base",
|
||||||
"role"
|
"role"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_role",
|
"change_role",
|
||||||
"base",
|
"base",
|
||||||
"role"
|
"role"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_role",
|
"delete_role",
|
||||||
"base",
|
"base",
|
||||||
"role"
|
"role"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_user",
|
"add_user",
|
||||||
"base",
|
"base",
|
||||||
"user"
|
"user"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_user",
|
"change_user",
|
||||||
"base",
|
"base",
|
||||||
"user"
|
"user"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_user",
|
"delete_user",
|
||||||
"base",
|
"base",
|
||||||
"user"
|
"user"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_contenttype",
|
"add_contenttype",
|
||||||
"contenttypes",
|
"contenttypes",
|
||||||
"contenttype"
|
"contenttype"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_contenttype",
|
"change_contenttype",
|
||||||
"contenttypes",
|
"contenttypes",
|
||||||
"contenttype"
|
"contenttype"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_contenttype",
|
"delete_contenttype",
|
||||||
"contenttypes",
|
"contenttypes",
|
||||||
"contenttype"
|
"contenttype"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_document",
|
"add_document",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_owned_documents",
|
"can_change_owned_documents",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_download_from_my_projects",
|
"can_download_from_my_projects",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_download_from_other_projects",
|
"can_download_from_other_projects",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_documents",
|
"can_view_documents",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_document",
|
"change_document",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_document",
|
"delete_document",
|
||||||
"documents",
|
"documents",
|
||||||
"document"
|
"document"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_question",
|
"add_question",
|
||||||
"questions",
|
"questions",
|
||||||
"question"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_owned_question",
|
"can_assign_question_to_myself",
|
||||||
"questions",
|
"questions",
|
||||||
"question"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_reply_question",
|
"can_assign_question_to_other",
|
||||||
"questions",
|
"questions",
|
||||||
"question"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_question",
|
"can_change_assigned_question",
|
||||||
"questions",
|
"questions",
|
||||||
"question"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_question",
|
"can_change_owned_question",
|
||||||
"questions",
|
"questions",
|
||||||
"question"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_questionresponse",
|
"can_change_question_state",
|
||||||
"questions",
|
"questions",
|
||||||
"questionresponse"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_questionresponse",
|
"can_reply_question",
|
||||||
"questions",
|
"questions",
|
||||||
"questionresponse"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_questionresponse",
|
"can_view_question",
|
||||||
"questions",
|
"questions",
|
||||||
"questionresponse"
|
"question"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_issue",
|
"change_question",
|
||||||
"scrum",
|
"questions",
|
||||||
|
"question"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_question",
|
||||||
|
"questions",
|
||||||
|
"question"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_questionstatus",
|
||||||
|
"questions",
|
||||||
|
"questionstatus"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_questionstatus",
|
||||||
|
"questions",
|
||||||
|
"questionstatus"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_questionstatus",
|
||||||
|
"questions",
|
||||||
|
"questionstatus"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_attachment",
|
||||||
|
"scrum",
|
||||||
|
"attachment"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"change_attachment",
|
||||||
|
"scrum",
|
||||||
|
"attachment"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"delete_attachment",
|
||||||
|
"scrum",
|
||||||
|
"attachment"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"add_issue",
|
||||||
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_assign_issue_to_myself",
|
"can_assign_issue_to_myself",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_assign_issue_to_other",
|
"can_assign_issue_to_other",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_assigned_issue",
|
"can_change_assigned_issue",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_issue_state",
|
"can_change_issue_state",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_owned_issue",
|
"can_change_owned_issue",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_comment_issue",
|
"can_comment_issue",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_issue",
|
"can_view_issue",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_issue",
|
"change_issue",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_issue",
|
"delete_issue",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issue"
|
"issue"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_issuestatus",
|
"add_issuestatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issuestatus"
|
"issuestatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_issuestatus",
|
"change_issuestatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issuestatus"
|
"issuestatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_issuestatus",
|
"delete_issuestatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issuestatus"
|
"issuestatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_issuetype",
|
"add_issuetype",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issuetype"
|
"issuetype"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_issuetype",
|
"change_issuetype",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issuetype"
|
"issuetype"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_issuetype",
|
"delete_issuetype",
|
||||||
"scrum",
|
"scrum",
|
||||||
"issuetype"
|
"issuetype"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_membership",
|
"add_membership",
|
||||||
"scrum",
|
"scrum",
|
||||||
"membership"
|
"membership"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_membership",
|
"change_membership",
|
||||||
"scrum",
|
"scrum",
|
||||||
"membership"
|
"membership"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_membership",
|
"delete_membership",
|
||||||
"scrum",
|
"scrum",
|
||||||
"membership"
|
"membership"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_milestone",
|
"add_milestone",
|
||||||
"scrum",
|
"scrum",
|
||||||
"milestone"
|
"milestone"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_milestone",
|
"can_view_milestone",
|
||||||
"scrum",
|
"scrum",
|
||||||
"milestone"
|
"milestone"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_milestone",
|
"change_milestone",
|
||||||
"scrum",
|
"scrum",
|
||||||
"milestone"
|
"milestone"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_milestone",
|
"delete_milestone",
|
||||||
"scrum",
|
"scrum",
|
||||||
"milestone"
|
"milestone"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_points",
|
"add_points",
|
||||||
"scrum",
|
"scrum",
|
||||||
"points"
|
"points"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_points",
|
"change_points",
|
||||||
"scrum",
|
"scrum",
|
||||||
"points"
|
"points"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_points",
|
"delete_points",
|
||||||
"scrum",
|
"scrum",
|
||||||
"points"
|
"points"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_priority",
|
"add_priority",
|
||||||
"scrum",
|
"scrum",
|
||||||
"priority"
|
"priority"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_priority",
|
"change_priority",
|
||||||
"scrum",
|
"scrum",
|
||||||
"priority"
|
"priority"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_priority",
|
"delete_priority",
|
||||||
"scrum",
|
"scrum",
|
||||||
"priority"
|
"priority"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_project",
|
"add_project",
|
||||||
"scrum",
|
"scrum",
|
||||||
"project"
|
"project"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_list_projects",
|
"can_list_projects",
|
||||||
"scrum",
|
"scrum",
|
||||||
"project"
|
"project"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_manage_users",
|
"can_manage_users",
|
||||||
"scrum",
|
"scrum",
|
||||||
"project"
|
"project"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_project",
|
"can_view_project",
|
||||||
"scrum",
|
"scrum",
|
||||||
"project"
|
"project"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_project",
|
"change_project",
|
||||||
"scrum",
|
"scrum",
|
||||||
"project"
|
"project"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_project",
|
"delete_project",
|
||||||
"scrum",
|
"scrum",
|
||||||
"project"
|
"project"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_severity",
|
"add_severity",
|
||||||
"scrum",
|
"scrum",
|
||||||
"severity"
|
"severity"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_severity",
|
"change_severity",
|
||||||
"scrum",
|
"scrum",
|
||||||
"severity"
|
"severity"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_severity",
|
"delete_severity",
|
||||||
"scrum",
|
"scrum",
|
||||||
"severity"
|
"severity"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_task",
|
"add_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_add_task_to_us",
|
"can_add_task_to_us",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_assign_task_to_myself",
|
"can_assign_task_to_myself",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_assign_task_to_other",
|
"can_assign_task_to_other",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_assigned_task",
|
"can_change_assigned_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_owned_task",
|
"can_change_owned_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_task_state",
|
"can_change_task_state",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_comment_task",
|
"can_comment_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_task",
|
"can_view_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_task",
|
"change_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_task",
|
"delete_task",
|
||||||
"scrum",
|
"scrum",
|
||||||
"task"
|
"task"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_taskstatus",
|
"add_taskstatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"taskstatus"
|
"taskstatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_taskstatus",
|
"change_taskstatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"taskstatus"
|
"taskstatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_taskstatus",
|
"delete_taskstatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"taskstatus"
|
"taskstatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_userstory",
|
"add_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_add_userstory_to_milestones",
|
"can_add_userstory_to_milestones",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_owned_userstory",
|
"can_change_owned_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_comment_userstory",
|
"can_comment_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_delete_userstory",
|
"can_delete_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_userstory",
|
"can_view_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_userstory",
|
"change_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_userstory",
|
"delete_userstory",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstory"
|
"userstory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_userstorystatus",
|
"add_userstorystatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstorystatus"
|
"userstorystatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_userstorystatus",
|
"change_userstorystatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstorystatus"
|
"userstorystatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_userstorystatus",
|
"delete_userstorystatus",
|
||||||
"scrum",
|
"scrum",
|
||||||
"userstorystatus"
|
"userstorystatus"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_session",
|
"add_session",
|
||||||
"sessions",
|
"sessions",
|
||||||
"session"
|
"session"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_session",
|
"change_session",
|
||||||
"sessions",
|
"sessions",
|
||||||
"session"
|
"session"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_session",
|
"delete_session",
|
||||||
"sessions",
|
"sessions",
|
||||||
"session"
|
"session"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_migrationhistory",
|
"add_migrationhistory",
|
||||||
"south",
|
"south",
|
||||||
"migrationhistory"
|
"migrationhistory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_migrationhistory",
|
"change_migrationhistory",
|
||||||
"south",
|
"south",
|
||||||
"migrationhistory"
|
"migrationhistory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_migrationhistory",
|
"delete_migrationhistory",
|
||||||
"south",
|
"south",
|
||||||
"migrationhistory"
|
"migrationhistory"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_wikipage",
|
"add_wikipage",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipage"
|
"wikipage"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_change_owned_wikipage",
|
"can_change_owned_wikipage",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipage"
|
"wikipage"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"can_view_wikipage",
|
"can_view_wikipage",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipage"
|
"wikipage"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_wikipage",
|
"change_wikipage",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipage"
|
"wikipage"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_wikipage",
|
"delete_wikipage",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipage"
|
"wikipage"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"add_wikipageattachment",
|
"add_wikipageattachment",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipageattachment"
|
"wikipageattachment"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"change_wikipageattachment",
|
"change_wikipageattachment",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipageattachment"
|
"wikipageattachment"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"delete_wikipageattachment",
|
"delete_wikipageattachment",
|
||||||
"wiki",
|
"wiki",
|
||||||
"wikipageattachment"
|
"wikipageattachment"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"name": "Developer",
|
"name": "Developer",
|
||||||
"slug": ""
|
"slug": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from greenmine.questions.models import Question, QuestionResponse
|
from greenmine.questions.models import Question, QuestionStatus
|
||||||
|
|
||||||
|
import reversion
|
||||||
|
|
||||||
|
|
||||||
class QuestionAdmin(admin.ModelAdmin):
|
class QuestionAdmin(reversion.VersionAdmin):
|
||||||
list_display = ["subject", "project", "owner"]
|
list_display = ["subject", "project", "owner"]
|
||||||
|
|
||||||
admin.site.register(Question, QuestionAdmin)
|
admin.site.register(Question, QuestionAdmin)
|
||||||
|
|
||||||
|
|
||||||
class QuestionResponseAdmin(admin.ModelAdmin):
|
class QuestionStatusAdmin(admin.ModelAdmin):
|
||||||
list_display = ["id", "question", "owner"]
|
list_display = ["name", "order", "is_closed", "project"]
|
||||||
|
|
||||||
admin.site.register(QuestionResponse, QuestionResponseAdmin)
|
admin.site.register(QuestionStatus, QuestionStatusAdmin)
|
||||||
|
|
|
@ -1,32 +1,34 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
from greenmine.questions.serializers import QuestionSerializer, QuestionResponseSerializer
|
from greenmine.questions.serializers import QuestionSerializer
|
||||||
from greenmine.questions.models import Question, QuestionResponse
|
from greenmine.questions.models import Question
|
||||||
from greenmine.questions.permissions import QuestionDetailPermission, QuestionResponseDetailPermission
|
from greenmine.questions.permissions import QuestionDetailPermission
|
||||||
|
|
||||||
|
import reversion
|
||||||
|
|
||||||
class QuestionList(generics.ListCreateAPIView):
|
class QuestionList(generics.ListCreateAPIView):
|
||||||
model = Question
|
model = Question
|
||||||
serializer_class = QuestionSerializer
|
serializer_class = QuestionSerializer
|
||||||
|
filter_fields = ('project',)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.model.objects.filter(project__members=self.request.user)
|
return self.model.objects.filter(project__members=self.request.user)
|
||||||
|
|
||||||
|
def pre_save(self, obj):
|
||||||
|
obj.owner = self.request.user
|
||||||
|
|
||||||
|
|
||||||
class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
|
class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||||
model = Question
|
model = Question
|
||||||
serializer_class = QuestionSerializer
|
serializer_class = QuestionSerializer
|
||||||
permission_classes = (QuestionDetailPermission,)
|
permission_classes = (IsAuthenticated, QuestionDetailPermission,)
|
||||||
|
|
||||||
|
def post_save(self, obj, created=False):
|
||||||
class QuestionResponseList(generics.ListCreateAPIView):
|
with reversion.create_revision():
|
||||||
model = QuestionResponse
|
if "comment" in self.request.DATA:
|
||||||
serializer_class = QuestionResponseSerializer
|
# Update the comment in the last version
|
||||||
|
reversion.set_comment(self.request.DATA['comment'])
|
||||||
def get_queryset(self):
|
|
||||||
return self.model.objects.filter(question__project__members=self.request.user)
|
|
||||||
|
|
||||||
class QuestionResponseDetail(generics.RetrieveUpdateDestroyAPIView):
|
|
||||||
model = QuestionResponse
|
|
||||||
serializer_class = QuestionResponseSerializer
|
|
||||||
permission_classes = (QuestionResponseDetailPermission,)
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
QUESTION_STATUS = (
|
||||||
|
(1, _(u"New"), False),
|
||||||
|
(2, _(u"Pending"), False),
|
||||||
|
(3, _(u"Answered"), True),
|
||||||
|
)
|
|
@ -1,15 +1,51 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
from greenmine.base.utils.slug import slugify_uniquely
|
from greenmine.base.utils.slug import slugify_uniquely, ref_uniquely
|
||||||
from greenmine.base.fields import DictField
|
from greenmine.base.fields import DictField
|
||||||
|
from greenmine.scrum.models import Project
|
||||||
|
|
||||||
|
from picklefield.fields import PickledObjectField
|
||||||
|
from greenmine.questions.choices import QUESTION_STATUS
|
||||||
|
|
||||||
|
|
||||||
|
class QuestionStatus(models.Model):
|
||||||
|
name = models.CharField(max_length=255, null=False, blank=False,
|
||||||
|
verbose_name=_('name'))
|
||||||
|
order = models.IntegerField(default=10, null=False, blank=False,
|
||||||
|
verbose_name=_('order'))
|
||||||
|
is_closed = models.BooleanField(default=False, null=False, blank=True,
|
||||||
|
verbose_name=_('is closed'))
|
||||||
|
project = models.ForeignKey(Project, null=False, blank=False,
|
||||||
|
related_name='question_status',
|
||||||
|
verbose_name=_('project'))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = u'question status'
|
||||||
|
verbose_name_plural = u'question status'
|
||||||
|
ordering = ['project', 'name']
|
||||||
|
unique_together = ('project', 'name')
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u'project {0} - {1}'.format(self.project_id, self.name)
|
||||||
|
|
||||||
|
|
||||||
class Question(models.Model):
|
class Question(models.Model):
|
||||||
subject = models.CharField(max_length=150, null=False, blank=False,
|
|
||||||
|
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
|
||||||
|
verbose_name=_('ref'))
|
||||||
|
owner = models.ForeignKey('base.User', null=True, blank=True, default=None,
|
||||||
|
related_name='owned_questions',
|
||||||
|
verbose_name=_('owner'))
|
||||||
|
status = models.ForeignKey('QuestionStatus', null=False, blank=False,
|
||||||
|
related_name='questions',
|
||||||
|
verbose_name=_('status'))
|
||||||
|
subject = models.CharField(max_length=250, null=False, blank=False,
|
||||||
verbose_name=_('subject'))
|
verbose_name=_('subject'))
|
||||||
slug = models.SlugField(unique=True, max_length=250, null=False, blank=True,
|
|
||||||
verbose_name=_('slug'))
|
|
||||||
content = models.TextField(null=False, blank=True,
|
content = models.TextField(null=False, blank=True,
|
||||||
verbose_name=_('content'))
|
verbose_name=_('content'))
|
||||||
closed = models.BooleanField(default=False, null=False, blank=True,
|
closed = models.BooleanField(default=False, null=False, blank=True,
|
||||||
|
@ -18,66 +54,68 @@ class Question(models.Model):
|
||||||
upload_to='messages',
|
upload_to='messages',
|
||||||
verbose_name=_('attached_file'))
|
verbose_name=_('attached_file'))
|
||||||
project = models.ForeignKey('scrum.Project', null=False, blank=False,
|
project = models.ForeignKey('scrum.Project', null=False, blank=False,
|
||||||
related_name='questions')
|
related_name='questions',
|
||||||
|
verbose_name=_('project'))
|
||||||
milestone = models.ForeignKey('scrum.Milestone', null=True, blank=True, default=None,
|
milestone = models.ForeignKey('scrum.Milestone', null=True, blank=True, default=None,
|
||||||
related_name='questions',
|
related_name='questions',
|
||||||
verbose_name=_('milestone'))
|
verbose_name=_('milestone'))
|
||||||
assigned_to = models.ForeignKey('base.User', null=False, blank=False,
|
finished_date = models.DateTimeField(null=True, blank=True,
|
||||||
|
verbose_name=_('finished date'))
|
||||||
|
assigned_to = models.ForeignKey('base.User', null=True, blank=True, default=None,
|
||||||
related_name='questions_assigned_to_me',
|
related_name='questions_assigned_to_me',
|
||||||
verbose_name=_('assigned_to'))
|
verbose_name=_('assigned_to'))
|
||||||
created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
|
created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
|
||||||
verbose_name=_('created date'))
|
verbose_name=_('created date'))
|
||||||
modified_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
|
modified_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
|
||||||
verbose_name=_('modified date'))
|
verbose_name=_('modified date'))
|
||||||
owner = models.ForeignKey('base.User', null=False, blank=False,
|
|
||||||
related_name='owned_questions')
|
|
||||||
watchers = models.ManyToManyField('base.User', null=True, blank=True,
|
watchers = models.ManyToManyField('base.User', null=True, blank=True,
|
||||||
related_name='watched_questions',
|
related_name='watched_questions',
|
||||||
verbose_name=_('watchers'))
|
verbose_name=_('watchers'))
|
||||||
tags = DictField(null=False, blank=True,
|
tags = PickledObjectField(null=False, blank=True,
|
||||||
verbose_name=_('tags'))
|
verbose_name=_('tags'))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = u'question'
|
verbose_name = u'question'
|
||||||
verbose_name_plural = u'questions'
|
verbose_name_plural = u'questions'
|
||||||
ordering = ['project', 'subject', 'id']
|
ordering = ['project', 'subject', 'id']
|
||||||
|
#TODO: permissions
|
||||||
permissions = (
|
permissions = (
|
||||||
('can_reply_question', 'Can reply questions'),
|
('can_reply_question', 'Can reply questions'),
|
||||||
('can_change_owned_question', 'Can modify owned questions'),
|
('can_change_owned_question', 'Can modify owned questions'),
|
||||||
|
('can_change_assigned_question', 'Can modify assigned questions'),
|
||||||
|
('can_assign_question_to_other', 'Can assign questions to others'),
|
||||||
|
('can_assign_question_to_myself', 'Can assign questions to myself'),
|
||||||
|
('can_change_question_state', 'Can change the question state'),
|
||||||
|
('can_view_question', 'Can view the question'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.subject
|
return self.subject
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.slug:
|
if self.id:
|
||||||
self.slug = slugify_uniquely(self.subject, self.__class__)
|
self.modified_date = timezone.now()
|
||||||
|
|
||||||
|
if not self.ref:
|
||||||
|
self.ref = ref_uniquely(self.project, 'last_issue_ref', self.__class__)
|
||||||
|
|
||||||
super(Question, self).save(*args, **kwargs)
|
super(Question, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class QuestionResponse(models.Model):
|
|
||||||
content = models.TextField(null=False, blank=False,
|
|
||||||
verbose_name=_('content'))
|
|
||||||
created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
|
|
||||||
verbose_name=_('created date'))
|
|
||||||
modified_date = models.DateTimeField(auto_now=True, null=False, blank=False,
|
|
||||||
verbose_name=_('modified date'))
|
|
||||||
attached_file = models.FileField(max_length=500, null=True, blank=True,
|
|
||||||
upload_to='messages',
|
|
||||||
verbose_name=_('attached file'))
|
|
||||||
question = models.ForeignKey('Question', null=False, blank=False,
|
|
||||||
related_name='responses',
|
|
||||||
verbose_name=_('question'))
|
|
||||||
owner = models.ForeignKey('base.User', null=False, blank=False,
|
|
||||||
related_name='question_responses')
|
|
||||||
tags = DictField(null=False, blank=True,
|
|
||||||
verbose_name=_('tags'))
|
|
||||||
|
|
||||||
class Meta:
|
# Model related signals handlers
|
||||||
verbose_name = u'question response'
|
|
||||||
verbose_name_plural = u'question responses'
|
|
||||||
ordering = ['question', 'created_date']
|
|
||||||
|
|
||||||
def __unicode__(self):
|
@receiver(models.signals.post_save, sender=Project, dispatch_uid='project_post_save_add_question_states')
|
||||||
return u'{0} - response {1}'.format(unicode(self.question), self.id)
|
def project_post_save_add_question_states(sender, instance, created, **kwargs):
|
||||||
|
"""
|
||||||
|
Create all project model depences on project is
|
||||||
|
created.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not created:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Populate new project dependen default data
|
||||||
|
for order, name, is_closed in QUESTION_STATUS:
|
||||||
|
QuestionStatus.objects.create(name=name, order=order,
|
||||||
|
is_closed=is_closed, project=instance)
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
from greenmine.base.permissions import BaseDetailPermission
|
from greenmine.base.permissions import BaseDetailPermission
|
||||||
|
|
||||||
|
|
||||||
class QuestionDetailPermission(BaseDetailPermission):
|
class QuestionDetailPermission(BaseDetailPermission):
|
||||||
get_permission = "can_view_question"
|
get_permission = "can_view_question"
|
||||||
put_permission = "can_change_question"
|
put_permission = "change_question"
|
||||||
delete_permission = "can_delete_question"
|
patch_permission = "change_question"
|
||||||
|
delete_permission = "delete_question"
|
||||||
safe_methods = ['HEAD', 'OPTIONS']
|
safe_methods = ['HEAD', 'OPTIONS']
|
||||||
path_to_document = []
|
path_to_project = []
|
||||||
|
|
||||||
class QuestionResponseDetailPermission(BaseDetailPermission):
|
|
||||||
get_permission = "can_view_questionresponse"
|
|
||||||
put_permission = "can_change_questionresponse"
|
|
||||||
delete_permission = "can_delete_questionresponse"
|
|
||||||
safe_methods = ['HEAD', 'OPTIONS']
|
|
||||||
path_to_document = []
|
|
||||||
|
|
|
@ -1,15 +1,58 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from greenmine.questions.models import Question, QuestionResponse
|
from greenmine.questions.models import Question
|
||||||
|
from greenmine.scrum.serializers import PickleField
|
||||||
|
|
||||||
|
import reversion
|
||||||
|
|
||||||
|
|
||||||
class QuestionSerializer(serializers.ModelSerializer):
|
class QuestionSerializer(serializers.ModelSerializer):
|
||||||
|
tags = PickleField()
|
||||||
|
comment = serializers.SerializerMethodField('get_comment')
|
||||||
|
history = serializers.SerializerMethodField('get_history')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Question
|
model = Question
|
||||||
fields = ()
|
fields = ()
|
||||||
|
|
||||||
|
def get_comment(self, obj):
|
||||||
|
return ''
|
||||||
|
|
||||||
class QuestionResponseSerializer(serializers.ModelSerializer):
|
def get_questions_diff(self, old_question_version, new_question_version):
|
||||||
class Meta:
|
old_obj = old_question_version.field_dict
|
||||||
model = QuestionResponse
|
new_obj = new_question_version.field_dict
|
||||||
fields = ()
|
|
||||||
|
diff_dict = {
|
||||||
|
'modified_date': new_obj['modified_date'],
|
||||||
|
'by': old_question_version.revision.user,
|
||||||
|
'comment': old_question_version.revision.comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
for key in old_obj.keys():
|
||||||
|
if key == 'modified_date':
|
||||||
|
continue
|
||||||
|
|
||||||
|
if old_obj[key] == new_obj[key]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
diff_dict[key] = {
|
||||||
|
'old': old_obj[key],
|
||||||
|
'new': new_obj[key],
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff_dict
|
||||||
|
|
||||||
|
def get_history(self, obj):
|
||||||
|
diff_list = []
|
||||||
|
current = None
|
||||||
|
|
||||||
|
for version in reversed(list(reversion.get_for_object(obj))):
|
||||||
|
if current:
|
||||||
|
questions_diff = self.get_questions_diff(version, current)
|
||||||
|
diff_list.append(questions_diff)
|
||||||
|
|
||||||
|
current = version
|
||||||
|
|
||||||
|
return diff_list
|
||||||
|
|
|
@ -6,7 +6,5 @@ from greenmine.questions import api
|
||||||
urlpatterns = format_suffix_patterns(patterns('',
|
urlpatterns = format_suffix_patterns(patterns('',
|
||||||
url(r'^questions/$', api.QuestionList.as_view(), name='question-list'),
|
url(r'^questions/$', api.QuestionList.as_view(), name='question-list'),
|
||||||
url(r'^questions/(?P<pk>[0-9]+)/$', api.QuestionDetail.as_view(), name='question-detail'),
|
url(r'^questions/(?P<pk>[0-9]+)/$', api.QuestionDetail.as_view(), name='question-detail'),
|
||||||
url(r'^question_responses/$', api.QuestionResponseList.as_view(), name='question-response-list'),
|
|
||||||
url(r'^question_responses/(?P<pk>[0-9]+)/$', api.QuestionResponseDetail.as_view(), name='question-response-detail'),
|
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ from django.contrib.webdesign import lorem_ipsum
|
||||||
|
|
||||||
from greenmine.base.models import User, Role
|
from greenmine.base.models import User, Role
|
||||||
from greenmine.scrum.models import *
|
from greenmine.scrum.models import *
|
||||||
|
from greenmine.questions.models import *
|
||||||
|
|
||||||
subjects = [
|
subjects = [
|
||||||
"Fixing templates for Django 1.2.",
|
"Fixing templates for Django 1.2.",
|
||||||
|
@ -146,3 +147,19 @@ class Command(BaseCommand):
|
||||||
bug.tags.append(tag)
|
bug.tags.append(tag)
|
||||||
|
|
||||||
bug.save()
|
bug.save()
|
||||||
|
|
||||||
|
# create questions.
|
||||||
|
for y in xrange(20):
|
||||||
|
question = Question.objects.create(
|
||||||
|
project=project,
|
||||||
|
subject=lorem_ipsum.words(random.randint(1, 5), common=False),
|
||||||
|
content=lorem_ipsum.words(random.randint(1, 15), common=False),
|
||||||
|
owner=project.owner,
|
||||||
|
status=QuestionStatus.objects.get(project=project, order=1),
|
||||||
|
tags=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
for tag in lorem_ipsum.words(random.randint(1, 5), common=True).split(" "):
|
||||||
|
question.tags.append(tag)
|
||||||
|
|
||||||
|
question.save()
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from greenmine.scrum.models import *
|
from greenmine.scrum.models import *
|
||||||
|
|
Loading…
Reference in New Issue