Repeating tasks (#25)

This commit is contained in:
konrad 2018-11-26 20:24:00 +00:00 committed by Gitea
parent 3f44e3b83e
commit 06fc9f7886
7 changed files with 54 additions and 25 deletions

View file

@ -165,7 +165,7 @@ Teams sind global, d.h. Ein Team kann mehrere Namespaces verwalten.
* [ ] Assignees * [ ] Assignees
* [ ] Subtasks * [ ] Subtasks
* [ ] Attachments * [ ] Attachments
* [ ] Repeating tasks * [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] 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.
* [ ] Tasks innerhalb eines definierbarem Bereich, sollte aber trotzdem der server machen, so à la "Gib mir alles für diesen Monat" * [ ] 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...) * [ ] Namespaces in Namespaces (in Namespaces in Namespaces in Namespaces...)

View file

@ -113,4 +113,13 @@ Authorization: Bearer {{auth_token}}
GET http://localhost:8080/api/v1/tasks/caldav GET http://localhost:8080/api/v1/tasks/caldav
#Authorization: Bearer {{auth_token}} #Authorization: Bearer {{auth_token}}
###
# Update a task
POST http://localhost:8080/api/v1/tasks/27
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"done":true}
### ###

View file

@ -16,7 +16,7 @@
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at // This file was generated by swaggo/swag at
// 2018-11-20 14:02:38.646137557 +0100 CET m=+0.072751301 // 2018-11-26 18:08:08.504247606 +0100 CET m=+0.124662709
package docs package docs
@ -107,7 +107,7 @@ var doc = `{
"ApiKeyAuth": [] "ApiKeyAuth": []
} }
], ],
"description": "Returns a list by its ID.", "description": "Returns a team by its ID.",
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -115,13 +115,13 @@ var doc = `{
"application/json" "application/json"
], ],
"tags": [ "tags": [
"list" "team"
], ],
"summary": "Gets one list", "summary": "Gets one team",
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "integer",
"description": "List ID", "description": "Team ID",
"name": "id", "name": "id",
"in": "path", "in": "path",
"required": true "required": true
@ -129,14 +129,14 @@ var doc = `{
], ],
"responses": { "responses": {
"200": { "200": {
"description": "The list", "description": "The team",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.List" "$ref": "#/definitions/models.Team"
} }
}, },
"403": { "403": {
"description": "The user does not have access to the list", "description": "The user does not have access to the team",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.HTTPError" "$ref": "#/definitions/models.HTTPError"
@ -2910,6 +2910,9 @@ var doc = `{
"type": "integer" "type": "integer"
} }
}, },
"repeatAfter": {
"type": "integer"
},
"text": { "text": {
"type": "string" "type": "string"
}, },

View file

@ -78,7 +78,7 @@
"ApiKeyAuth": [] "ApiKeyAuth": []
} }
], ],
"description": "Returns a list by its ID.", "description": "Returns a team by its ID.",
"consumes": [ "consumes": [
"application/json" "application/json"
], ],
@ -86,13 +86,13 @@
"application/json" "application/json"
], ],
"tags": [ "tags": [
"list" "team"
], ],
"summary": "Gets one list", "summary": "Gets one team",
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "integer",
"description": "List ID", "description": "Team ID",
"name": "id", "name": "id",
"in": "path", "in": "path",
"required": true "required": true
@ -100,14 +100,14 @@
], ],
"responses": { "responses": {
"200": { "200": {
"description": "The list", "description": "The team",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.List" "$ref": "#/definitions/models.Team"
} }
}, },
"403": { "403": {
"description": "The user does not have access to the list", "description": "The user does not have access to the team",
"schema": { "schema": {
"type": "object", "type": "object",
"$ref": "#/definitions/models.HTTPError" "$ref": "#/definitions/models.HTTPError"
@ -2881,6 +2881,9 @@
"type": "integer" "type": "integer"
} }
}, },
"repeatAfter": {
"type": "integer"
},
"text": { "text": {
"type": "string" "type": "string"
}, },

View file

@ -64,6 +64,8 @@ definitions:
items: items:
type: integer type: integer
type: array type: array
repeatAfter:
type: integer
text: text:
type: string type: string
updated: updated:
@ -389,9 +391,9 @@ paths:
get: get:
consumes: consumes:
- application/json - application/json
description: Returns a list by its ID. description: Returns a team by its ID.
parameters: parameters:
- description: List ID - description: Team ID
in: path in: path
name: id name: id
required: true required: true
@ -400,12 +402,12 @@ paths:
- application/json - application/json
responses: responses:
"200": "200":
description: The list description: The team
schema: schema:
$ref: '#/definitions/models.List' $ref: '#/definitions/models.Team'
type: object type: object
"403": "403":
description: The user does not have access to the list description: The user does not have access to the team
schema: schema:
$ref: '#/definitions/models.HTTPError' $ref: '#/definitions/models.HTTPError'
type: object type: object
@ -416,9 +418,9 @@ paths:
type: object type: object
security: security:
- ApiKeyAuth: [] - ApiKeyAuth: []
summary: Gets one list summary: Gets one team
tags: tags:
- list - team
post: post:
consumes: consumes:
- application/json - application/json

View file

@ -26,6 +26,7 @@ type ListTask struct {
RemindersUnix []int64 `xorm:"JSON TEXT" json:"reminderDates"` RemindersUnix []int64 `xorm:"JSON TEXT" json:"reminderDates"`
CreatedByID int64 `xorm:"int(11)" json:"-"` // ID of the user who put that task on the list CreatedByID int64 `xorm:"int(11)" json:"-"` // ID of the user who put that task on the list
ListID int64 `xorm:"int(11) INDEX" json:"listID" param:"list"` ListID int64 `xorm:"int(11) INDEX" json:"listID" param:"list"`
RepeatAfter int64 `xorm:"int(11) INDEX" json:"repeatAfter"`
Created int64 `xorm:"created" json:"created"` Created int64 `xorm:"created" json:"created"`
Updated int64 `xorm:"updated" json:"updated"` Updated int64 `xorm:"updated" json:"updated"`

View file

@ -55,7 +55,7 @@ func (i *ListTask) Create(doer *User) (err error) {
i.CreatedByID = u.ID i.CreatedByID = u.ID
i.CreatedBy = u i.CreatedBy = u
_, err = x.Cols("text", "description", "done", "due_date_unix", "reminder_unix", "created_by_id", "list_id", "created", "updated").Insert(i) _, err = x.Insert(i)
return err return err
} }
@ -80,6 +80,17 @@ func (i *ListTask) Update() (err error) {
return return
} }
// When a repeating task is marked, as done, we update all deadlines and reminders and set it as undone
if !ot.Done && i.Done && ot.RepeatAfter > 0 {
ot.DueDateUnix = ot.DueDateUnix + ot.RepeatAfter
for in, r := range ot.RemindersUnix {
ot.RemindersUnix[in] = r + ot.RepeatAfter
}
i.Done = false
}
// For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand // For whatever reason, xorm dont detect if done is updated, so we need to update this every time by hand
// Which is why we merge the actual task struct with the one we got from the // Which is why we merge the actual task struct with the one we got from the
// The user struct overrides values in the actual one. // The user struct overrides values in the actual one.
@ -92,7 +103,7 @@ func (i *ListTask) Update() (err error) {
ot.Done = false ot.Done = false
} }
_, err = x.ID(i.ID).Cols("text", "description", "done", "due_date_unix", "reminders_unix").Update(ot) _, err = x.ID(i.ID).Cols("text", "description", "done", "due_date_unix", "reminders_unix", "repeat_after").Update(ot)
*i = ot *i = ot
return return
} }