Priorites for tasks (#31)
This commit is contained in:
parent
f2f881f505
commit
cc6b35e314
11 changed files with 323 additions and 84 deletions
|
@ -160,13 +160,13 @@ Teams sind global, d.h. Ein Team kann mehrere Namespaces verwalten.
|
|||
|
||||
## Feature-Ideen
|
||||
|
||||
* [ ] Labels
|
||||
* [ ] Priorities
|
||||
* [ ] Assignees
|
||||
* [x] Subtasks
|
||||
* [ ] Attachments
|
||||
* [x] Priorities
|
||||
* [x] Repeating tasks
|
||||
* [x] Tagesübersicht ("Was ist heute/diese Woche due?") -> Machen letztenendes die Clients, wir brauchen nur nen endpoint, der alle tasks auskotzt, der Client macht dann die Sortierung.
|
||||
* [x] Subtasks
|
||||
* [ ] Assignees
|
||||
* [ ] Attachments
|
||||
* [ ] Labels
|
||||
* [ ] Tasks innerhalb eines definierbarem Bereich, sollte aber trotzdem der server machen, so à la "Gib mir alles für diesen Monat"
|
||||
* [ ] Namespaces in Namespaces (in Namespaces in Namespaces in Namespaces...)
|
||||
* Rechtemanagement dafür wird schwierig
|
||||
|
|
10
README.md
10
README.md
|
@ -22,14 +22,14 @@ Try it under [try.vikunja.io](https://try.vikunja.io)!
|
|||
|
||||
> I know, it's still a long way to go. I'm currently working on a lot of "basic" features, the exiting things will come later. Don't worry, they'll come.
|
||||
|
||||
* [ ] Labels for todo lists and tasks
|
||||
* [ ] Prioritize tasks
|
||||
* [ ] Assign users to tasks
|
||||
* [x] Prioritize tasks
|
||||
* [x] Subtasks
|
||||
* [x] Repeating tasks
|
||||
* [ ] Attachments on tasks
|
||||
* [ ] Get all tasks for you per interval (day/month/period)
|
||||
* [x] Get tasks via caldav
|
||||
* [ ] Labels for todo lists and tasks
|
||||
* [ ] Assign users to tasks
|
||||
* [ ] Attachments on tasks
|
||||
* [ ] Get all your tasks for an interval (day/month/period)
|
||||
* [ ] More sharing features
|
||||
* [x] Share with individual users
|
||||
* [ ] Share via a world-readable link with or without password, like Nextcloud
|
||||
|
|
|
@ -112,6 +112,12 @@ Authorization: Bearer {{auth_token}}
|
|||
|
||||
###
|
||||
|
||||
# Get all pending tasks with priorities
|
||||
GET http://localhost:8080/api/v1/tasks/desc
|
||||
Authorization: Bearer {{auth_token}}
|
||||
|
||||
###
|
||||
|
||||
# Get all pending tasks in caldav
|
||||
GET http://localhost:8080/api/v1/tasks/caldav
|
||||
#Authorization: Bearer {{auth_token}}
|
||||
|
|
78
docs/docs.go
78
docs/docs.go
|
@ -1,6 +1,6 @@
|
|||
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag at
|
||||
// 2018-12-01 03:02:40.853807498 +0100 CET m=+0.099265725
|
||||
// 2018-12-02 01:35:21.999635022 +0100 CET m=+0.131973644
|
||||
|
||||
package docs
|
||||
|
||||
|
@ -91,7 +91,7 @@ var doc = `{
|
|||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Returns a team by its ID.",
|
||||
"description": "Returns a list by its ID.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
|
@ -99,13 +99,13 @@ var doc = `{
|
|||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"team"
|
||||
"list"
|
||||
],
|
||||
"summary": "Gets one team",
|
||||
"summary": "Gets one list",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Team ID",
|
||||
"description": "List ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
|
@ -113,14 +113,14 @@ var doc = `{
|
|||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The team",
|
||||
"description": "The list",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/models.Team"
|
||||
"$ref": "#/definitions/models.List"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "The user does not have access to the team",
|
||||
"description": "The user does not have access to the list",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/code.vikunja.io/web.HTTPError"
|
||||
|
@ -2155,6 +2155,65 @@ var doc = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{sortby}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Returns all tasks on any list the user has access to.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"task"
|
||||
],
|
||||
"summary": "Get tasks sorted",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "The page number. Used for pagination. If not provided, the first page of results is returned.",
|
||||
"name": "p",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search tasks by task text.",
|
||||
"name": "s",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, dueadate, dueadatedesc, dueadateasc.",
|
||||
"name": "sortby",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The tasks",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.List"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/models.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/teams": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -2880,6 +2939,9 @@ var doc = `{
|
|||
"parentTaskID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer"
|
||||
},
|
||||
"reminderDates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Returns a team by its ID.",
|
||||
"description": "Returns a list by its ID.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
|
@ -86,13 +86,13 @@
|
|||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"team"
|
||||
"list"
|
||||
],
|
||||
"summary": "Gets one team",
|
||||
"summary": "Gets one list",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Team ID",
|
||||
"description": "List ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
|
@ -100,14 +100,14 @@
|
|||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The team",
|
||||
"description": "The list",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/models.Team"
|
||||
"$ref": "#/definitions/models.List"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "The user does not have access to the team",
|
||||
"description": "The user does not have access to the list",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/code.vikunja.io/web.HTTPError"
|
||||
|
@ -2142,6 +2142,65 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/tasks/{sortby}": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Returns all tasks on any list the user has access to.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"task"
|
||||
],
|
||||
"summary": "Get tasks sorted",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "The page number. Used for pagination. If not provided, the first page of results is returned.",
|
||||
"name": "p",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Search tasks by task text.",
|
||||
"name": "s",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, dueadate, dueadatedesc, dueadateasc.",
|
||||
"name": "sortby",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The tasks",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.List"
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal error",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/models.Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/teams": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
@ -2867,6 +2926,9 @@
|
|||
"parentTaskID": {
|
||||
"type": "integer"
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer"
|
||||
},
|
||||
"reminderDates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
|
@ -55,6 +55,8 @@ definitions:
|
|||
type: integer
|
||||
parentTaskID:
|
||||
type: integer
|
||||
priority:
|
||||
type: integer
|
||||
reminderDates:
|
||||
items:
|
||||
type: integer
|
||||
|
@ -390,9 +392,9 @@ paths:
|
|||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Returns a team by its ID.
|
||||
description: Returns a list by its ID.
|
||||
parameters:
|
||||
- description: Team ID
|
||||
- description: List ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
|
@ -401,12 +403,12 @@ paths:
|
|||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: The team
|
||||
description: The list
|
||||
schema:
|
||||
$ref: '#/definitions/models.Team'
|
||||
$ref: '#/definitions/models.List'
|
||||
type: object
|
||||
"403":
|
||||
description: The user does not have access to the team
|
||||
description: The user does not have access to the list
|
||||
schema:
|
||||
$ref: '#/definitions/code.vikunja.io/web.HTTPError'
|
||||
type: object
|
||||
|
@ -417,9 +419,9 @@ paths:
|
|||
type: object
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Gets one team
|
||||
summary: Gets one list
|
||||
tags:
|
||||
- team
|
||||
- list
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
|
@ -1726,6 +1728,46 @@ paths:
|
|||
summary: Update a task
|
||||
tags:
|
||||
- task
|
||||
/tasks/{sortby}:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Returns all tasks on any list the user has access to.
|
||||
parameters:
|
||||
- description: The page number. Used for pagination. If not provided, the first
|
||||
page of results is returned.
|
||||
in: query
|
||||
name: p
|
||||
type: integer
|
||||
- description: Search tasks by task text.
|
||||
in: query
|
||||
name: s
|
||||
type: string
|
||||
- description: The sorting parameter. Possible values to sort by are priority,
|
||||
prioritydesc, priorityasc, dueadate, dueadatedesc, dueadateasc.
|
||||
in: path
|
||||
name: sortby
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: The tasks
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/models.List'
|
||||
type: array
|
||||
"500":
|
||||
description: Internal error
|
||||
schema:
|
||||
$ref: '#/definitions/models.Message'
|
||||
type: object
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Get tasks sorted
|
||||
tags:
|
||||
- task
|
||||
/tasks/caldav:
|
||||
get:
|
||||
description: Returns a calDAV-parsable format with all tasks as calendar events.
|
||||
|
|
|
@ -18,7 +18,6 @@ package models
|
|||
|
||||
import (
|
||||
"code.vikunja.io/web"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// List represents a list of tasks
|
||||
|
@ -201,51 +200,3 @@ func AddListDetails(lists []*List) (err error) {
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// ReadAll gets all tasks for a user
|
||||
// @Summary Get tasks
|
||||
// @Description Returns all tasks on any list the user has access to.
|
||||
// @tags task
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param p query int false "The page number. Used for pagination. If not provided, the first page of results is returned."
|
||||
// @Param s query string false "Search tasks by task text."
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {array} models.List "The tasks"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /tasks [get]
|
||||
func (lt *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
|
||||
u, err := getUserWithError(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return GetTasksByUser(search, u, page)
|
||||
}
|
||||
|
||||
//GetTasksByUser returns all tasks for a user
|
||||
func GetTasksByUser(search string, u *User, page int) (tasks []*ListTask, err error) {
|
||||
// Get all lists
|
||||
lists, err := getRawListsForUser("", u, page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get all list IDs and get the tasks
|
||||
var listIDs []int64
|
||||
for _, l := range lists {
|
||||
listIDs = append(listIDs, l.ID)
|
||||
}
|
||||
|
||||
// Then return all tasks for that lists
|
||||
if err := x.In("list_id", listIDs).Where("text LIKE ?", "%"+search+"%").Find(&tasks); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Sort it by due date
|
||||
sort.Slice(tasks, func(i, j int) bool {
|
||||
return tasks[i].DueDateUnix > tasks[j].DueDateUnix
|
||||
})
|
||||
|
||||
return tasks, err
|
||||
}
|
||||
|
|
111
pkg/models/list_task_readall.go
Normal file
111
pkg/models/list_task_readall.go
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2018 the Vikunja Authors. All rights reserved.
|
||||
* Use of this source code is governed by a LPGLv3-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import "code.vikunja.io/web"
|
||||
|
||||
// SortBy declares constants to sort
|
||||
type SortBy int
|
||||
|
||||
// These are possible sort options
|
||||
const (
|
||||
SortTasksByUnsorted SortBy = -1
|
||||
SortTasksByDueDateAsc = iota
|
||||
SortTasksByDueDateDesc
|
||||
SortTasksByPriorityAsc
|
||||
SortTasksByPriorityDesc
|
||||
)
|
||||
|
||||
// ReadAllWithPriority gets all tasks for a user, sorted
|
||||
// @Summary Get tasks sorted
|
||||
// @Description Returns all tasks on any list the user has access to.
|
||||
// @tags task
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param p query int false "The page number. Used for pagination. If not provided, the first page of results is returned."
|
||||
// @Param s query string false "Search tasks by task text."
|
||||
// @Param sortby path string true "The sorting parameter. Possible values to sort by are priority, prioritydesc, priorityasc, dueadate, dueadatedesc, dueadateasc."
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {array} models.List "The tasks"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /tasks/{sortby} [get]
|
||||
func dummy() {
|
||||
// Dummy function for swaggo to pick up the docs comment
|
||||
}
|
||||
|
||||
// ReadAll gets all tasks for a user
|
||||
// @Summary Get tasks
|
||||
// @Description Returns all tasks on any list the user has access to.
|
||||
// @tags task
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param p query int false "The page number. Used for pagination. If not provided, the first page of results is returned."
|
||||
// @Param s query string false "Search tasks by task text."
|
||||
// @Security ApiKeyAuth
|
||||
// @Success 200 {array} models.List "The tasks"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /tasks [get]
|
||||
func (lt *ListTask) ReadAll(search string, a web.Auth, page int) (interface{}, error) {
|
||||
u, err := getUserWithError(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sortby SortBy
|
||||
switch lt.Sorting {
|
||||
case "priority":
|
||||
sortby = SortTasksByPriorityDesc
|
||||
case "prioritydesc":
|
||||
sortby = SortTasksByPriorityDesc
|
||||
case "priorityasc":
|
||||
sortby = SortTasksByPriorityAsc
|
||||
case "dueadate":
|
||||
sortby = SortTasksByDueDateDesc
|
||||
case "dueadatedesc":
|
||||
sortby = SortTasksByDueDateDesc
|
||||
case "duedateasc":
|
||||
sortby = SortTasksByDueDateAsc
|
||||
default:
|
||||
sortby = SortTasksByUnsorted
|
||||
}
|
||||
|
||||
return GetTasksByUser(search, u, page, sortby)
|
||||
}
|
||||
|
||||
//GetTasksByUser returns all tasks for a user
|
||||
func GetTasksByUser(search string, u *User, page int, sortby SortBy) (tasks []*ListTask, err error) {
|
||||
// Get all lists
|
||||
lists, err := getRawListsForUser("", u, page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get all list IDs and get the tasks
|
||||
var listIDs []int64
|
||||
for _, l := range lists {
|
||||
listIDs = append(listIDs, l.ID)
|
||||
}
|
||||
|
||||
var orderby string
|
||||
switch sortby {
|
||||
case SortTasksByPriorityDesc:
|
||||
orderby = "priority desc"
|
||||
case SortTasksByPriorityAsc:
|
||||
orderby = "priority asc"
|
||||
case SortTasksByDueDateDesc:
|
||||
orderby = "due_date_unix desc"
|
||||
case SortTasksByDueDateAsc:
|
||||
orderby = "due_date_unix asc"
|
||||
}
|
||||
|
||||
// Then return all tasks for that lists
|
||||
if err := x.In("list_id", listIDs).Where("text LIKE ?", "%"+search+"%").OrderBy(orderby).Find(&tasks); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tasks, err
|
||||
}
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package models
|
||||
|
||||
import "code.vikunja.io/web"
|
||||
import (
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
// ListTask represents an task in a todolist
|
||||
type ListTask struct {
|
||||
|
@ -30,6 +32,8 @@ type ListTask struct {
|
|||
ListID int64 `xorm:"int(11) INDEX" json:"listID" param:"list"`
|
||||
RepeatAfter int64 `xorm:"int(11) INDEX" json:"repeatAfter"`
|
||||
ParentTaskID int64 `xorm:"int(11) INDEX" json:"parentTaskID"`
|
||||
Priority int64 `xorm:"int(11)" json:"priority"`
|
||||
Sorting string `xorm:"-" json:"-" param:"sort"` // Parameter to sort by
|
||||
|
||||
Subtasks []*ListTask `xorm:"-" json:"subtasks"`
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ func Caldav(c echo.Context) error {
|
|||
}
|
||||
|
||||
// Get all tasks for that user
|
||||
tasks, err := models.GetTasksByUser("", &u, -1)
|
||||
tasks, err := models.GetTasksByUser("", &u, -1, models.SortTasksByUnsorted)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
return models.GetCurrentUser(c)
|
||||
},
|
||||
})
|
||||
c.Set("LoggingProvider", &log.Log)
|
||||
c.Set("LoggingProvider", log.Log)
|
||||
return next(c)
|
||||
}
|
||||
})
|
||||
|
@ -163,6 +163,7 @@ func RegisterRoutes(e *echo.Echo) {
|
|||
}
|
||||
a.PUT("/lists/:list", taskHandler.CreateWeb)
|
||||
a.GET("/tasks", taskHandler.ReadAllWeb)
|
||||
a.GET("/tasks/:sort", taskHandler.ReadAllWeb)
|
||||
a.DELETE("/tasks/:listtask", taskHandler.DeleteWeb)
|
||||
a.POST("/tasks/:listtask", taskHandler.UpdateWeb)
|
||||
|
||||
|
|
Loading…
Reference in a new issue