fix(task): make sure the task's last updated timestamp is always updated when releated entities changed
This commit is contained in:
parent
659803fadf
commit
fceb5dae0f
@ -80,6 +80,18 @@ func (t *TaskAssigneeCreatedEvent) Name() string {
|
|||||||
return "task.assignee.created"
|
return "task.assignee.created"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TaskAssigneeDeletedEvent represents a TaskAssigneeDeletedEvent event
|
||||||
|
type TaskAssigneeDeletedEvent struct {
|
||||||
|
Task *Task
|
||||||
|
Assignee *user.User
|
||||||
|
Doer *user.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for TaskAssigneeDeletedEvent
|
||||||
|
func (t *TaskAssigneeDeletedEvent) Name() string {
|
||||||
|
return "task.assignee.deleted"
|
||||||
|
}
|
||||||
|
|
||||||
// TaskCommentCreatedEvent represents an event where a task comment has been created
|
// TaskCommentCreatedEvent represents an event where a task comment has been created
|
||||||
type TaskCommentCreatedEvent struct {
|
type TaskCommentCreatedEvent struct {
|
||||||
Task *Task
|
Task *Task
|
||||||
@ -104,6 +116,66 @@ func (t *TaskCommentUpdatedEvent) Name() string {
|
|||||||
return "task.comment.edited"
|
return "task.comment.edited"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TaskCommentDeletedEvent represents a TaskCommentDeletedEvent event
|
||||||
|
type TaskCommentDeletedEvent struct {
|
||||||
|
Task *Task
|
||||||
|
Comment *TaskComment
|
||||||
|
Doer *user.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for TaskCommentDeletedEvent
|
||||||
|
func (t *TaskCommentDeletedEvent) Name() string {
|
||||||
|
return "task.comment.deleted"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TaskAttachmentCreatedEvent represents a TaskAttachmentCreatedEvent event
|
||||||
|
type TaskAttachmentCreatedEvent struct {
|
||||||
|
Task *Task
|
||||||
|
Attachment *TaskAttachment
|
||||||
|
Doer *user.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for TaskAttachmentCreatedEvent
|
||||||
|
func (t *TaskAttachmentCreatedEvent) Name() string {
|
||||||
|
return "task.attachment.created"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TaskAttachmentDeletedEvent represents a TaskAttachmentDeletedEvent event
|
||||||
|
type TaskAttachmentDeletedEvent struct {
|
||||||
|
Task *Task
|
||||||
|
Attachment *TaskAttachment
|
||||||
|
Doer *user.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for TaskAttachmentDeletedEvent
|
||||||
|
func (t *TaskAttachmentDeletedEvent) Name() string {
|
||||||
|
return "task.attachment.deleted"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TaskRelationCreatedEvent represents a TaskRelationCreatedEvent event
|
||||||
|
type TaskRelationCreatedEvent struct {
|
||||||
|
Task *Task
|
||||||
|
Relation *TaskRelation
|
||||||
|
Doer *user.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for TaskRelationCreatedEvent
|
||||||
|
func (t *TaskRelationCreatedEvent) Name() string {
|
||||||
|
return "task.relation.created"
|
||||||
|
}
|
||||||
|
|
||||||
|
// TaskRelationDeletedEvent represents a TaskRelationDeletedEvent event
|
||||||
|
type TaskRelationDeletedEvent struct {
|
||||||
|
Task *Task
|
||||||
|
Relation *TaskRelation
|
||||||
|
Doer *user.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for TaskRelationDeletedEvent
|
||||||
|
func (t *TaskRelationDeletedEvent) Name() string {
|
||||||
|
return "task.relation.deleted"
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Namespace Events //
|
// Namespace Events //
|
||||||
//////////////////////
|
//////////////////////
|
||||||
|
@ -51,6 +51,15 @@ func RegisterListeners() {
|
|||||||
events.RegisterListener((&TaskCreatedEvent{}).Name(), &HandleTaskCreateMentions{})
|
events.RegisterListener((&TaskCreatedEvent{}).Name(), &HandleTaskCreateMentions{})
|
||||||
events.RegisterListener((&TaskUpdatedEvent{}).Name(), &HandleTaskUpdatedMentions{})
|
events.RegisterListener((&TaskUpdatedEvent{}).Name(), &HandleTaskUpdatedMentions{})
|
||||||
events.RegisterListener((&UserDataExportRequestedEvent{}).Name(), &HandleUserDataExport{})
|
events.RegisterListener((&UserDataExportRequestedEvent{}).Name(), &HandleUserDataExport{})
|
||||||
|
events.RegisterListener((&TaskCommentCreatedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskCommentUpdatedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskCommentDeletedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskAssigneeCreatedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskAssigneeDeletedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskAttachmentCreatedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskAttachmentDeletedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskRelationCreatedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
|
events.RegisterListener((&TaskRelationDeletedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||||
}
|
}
|
||||||
|
|
||||||
//////
|
//////
|
||||||
@ -403,9 +412,62 @@ func (s *HandleTaskUpdatedMentions) Handle(msg *message.Message) (err error) {
|
|||||||
Doer: event.Doer,
|
Doer: event.Doer,
|
||||||
IsNew: false,
|
IsNew: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = notifyMentionedUsers(sess, event.Task, event.Task.Description, n)
|
_, err = notifyMentionedUsers(sess, event.Task, event.Task.Description, n)
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleTaskUpdateLastUpdated represents a listener
|
||||||
|
type HandleTaskUpdateLastUpdated struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name defines the name for the HandleTaskUpdateLastUpdated listener
|
||||||
|
func (s *HandleTaskUpdateLastUpdated) Name() string {
|
||||||
|
return "handle.task.update.last.updated"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is executed when the event HandleTaskUpdateLastUpdated listens on is fired
|
||||||
|
func (s *HandleTaskUpdateLastUpdated) Handle(msg *message.Message) (err error) {
|
||||||
|
// Using a map here allows us to plug this listener to all kinds of task events
|
||||||
|
event := map[string]interface{}{}
|
||||||
|
err = json.Unmarshal(msg.Payload, &event)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
task, is := event["Task"].(map[string]interface{})
|
||||||
|
if !is {
|
||||||
|
log.Errorf("Event payload does not contain task ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
taskID, is := task["id"]
|
||||||
|
if !is {
|
||||||
|
log.Errorf("Event payload does not contain a valid task ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var taskIDInt int64
|
||||||
|
switch taskID.(type) {
|
||||||
|
case int64:
|
||||||
|
taskIDInt = taskID.(int64)
|
||||||
|
case int:
|
||||||
|
taskIDInt = int64(taskID.(int))
|
||||||
|
case int32:
|
||||||
|
taskIDInt = int64(taskID.(int32))
|
||||||
|
case float64:
|
||||||
|
taskIDInt = int64(taskID.(float64))
|
||||||
|
case float32:
|
||||||
|
taskIDInt = int64(taskID.(float32))
|
||||||
|
default:
|
||||||
|
log.Errorf("Event payload does not contain a valid task ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := db.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
|
||||||
|
return updateTaskLastUpdated(sess, &Task{ID: taskIDInt})
|
||||||
}
|
}
|
||||||
|
|
||||||
///////
|
///////
|
||||||
|
@ -179,7 +179,16 @@ func (la *TaskAssginee) Delete(s *xorm.Session, a web.Auth) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = updateListByTaskID(s, la.TaskID)
|
err = updateListByTaskID(s, la.TaskID)
|
||||||
return
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
doer, _ := user.GetFromAuth(a)
|
||||||
|
return events.Dispatch(&TaskAssigneeDeletedEvent{
|
||||||
|
Task: &Task{ID: la.TaskID},
|
||||||
|
Assignee: &user.User{ID: la.UserID},
|
||||||
|
Doer: doer,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create adds a new assignee to a task
|
// Create adds a new assignee to a task
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"code.vikunja.io/api/pkg/events"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ type TaskAttachment struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name for task attachments
|
// TableName returns the table name for task attachments
|
||||||
func (TaskAttachment) TableName() string {
|
func (*TaskAttachment) TableName() string {
|
||||||
return "task_attachments"
|
return "task_attachments"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +85,11 @@ func (ta *TaskAttachment) NewAttachment(s *xorm.Session, f io.ReadCloser, realna
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return events.Dispatch(&TaskAttachmentCreatedEvent{
|
||||||
|
Task: &Task{ID: ta.TaskID},
|
||||||
|
Attachment: ta,
|
||||||
|
Doer: ta.CreatedBy,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadOne returns a task attachment
|
// ReadOne returns a task attachment
|
||||||
@ -209,7 +214,16 @@ func (ta *TaskAttachment) Delete(s *xorm.Session, a web.Auth) error {
|
|||||||
if err != nil && files.IsErrFileDoesNotExist(err) {
|
if err != nil && files.IsErrFileDoesNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
doer, _ := user.GetFromAuth(a)
|
||||||
|
return events.Dispatch(&TaskAttachmentDeletedEvent{
|
||||||
|
Task: &Task{ID: ta.TaskID},
|
||||||
|
Attachment: ta,
|
||||||
|
Doer: doer,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTaskAttachmentsByTaskIDs(s *xorm.Session, taskIDs []int64) (attachments []*TaskAttachment, err error) {
|
func getTaskAttachmentsByTaskIDs(s *xorm.Session, taskIDs []int64) (attachments []*TaskAttachment, err error) {
|
||||||
|
@ -109,7 +109,16 @@ func (tc *TaskComment) Delete(s *xorm.Session, a web.Auth) error {
|
|||||||
if deleted == 0 {
|
if deleted == 0 {
|
||||||
return ErrTaskCommentDoesNotExist{ID: tc.ID}
|
return ErrTaskCommentDoesNotExist{ID: tc.ID}
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return events.Dispatch(&TaskCommentDeletedEvent{
|
||||||
|
Task: &Task{ID: tc.TaskID},
|
||||||
|
Comment: tc,
|
||||||
|
Doer: tc.Author,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates a task text by its ID
|
// Update updates a task text by its ID
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"code.vikunja.io/api/pkg/events"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
@ -98,7 +99,7 @@ type TaskRelation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TableName holds the table name for the task relation table
|
// TableName holds the table name for the task relation table
|
||||||
func (TaskRelation) TableName() string {
|
func (*TaskRelation) TableName() string {
|
||||||
return "task_relations"
|
return "task_relations"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +191,16 @@ func (rel *TaskRelation) Create(s *xorm.Session, a web.Auth) error {
|
|||||||
rel,
|
rel,
|
||||||
otherRelation,
|
otherRelation,
|
||||||
})
|
})
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
doer, _ := user.GetFromAuth(a)
|
||||||
|
return events.Dispatch(&TaskRelationCreatedEvent{
|
||||||
|
Task: &Task{ID: rel.TaskID},
|
||||||
|
Relation: rel,
|
||||||
|
Doer: doer,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete removes a task relation
|
// Delete removes a task relation
|
||||||
@ -241,5 +251,14 @@ func (rel *TaskRelation) Delete(s *xorm.Session, a web.Auth) error {
|
|||||||
_, err = s.
|
_, err = s.
|
||||||
Where(cond).
|
Where(cond).
|
||||||
Delete(&TaskRelation{})
|
Delete(&TaskRelation{})
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
doer, _ := user.GetFromAuth(a)
|
||||||
|
return events.Dispatch(&TaskRelationDeletedEvent{
|
||||||
|
Task: &Task{ID: rel.TaskID},
|
||||||
|
Relation: rel,
|
||||||
|
Doer: doer,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1441,6 +1441,11 @@ func (t *Task) updateReminders(s *xorm.Session, reminders []time.Time) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateTaskLastUpdated(s *xorm.Session, task *Task) error {
|
||||||
|
_, err := s.ID(task.ID).Cols("updated").Update(task)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Delete implements the delete method for listTask
|
// Delete implements the delete method for listTask
|
||||||
// @Summary Delete a task
|
// @Summary Delete a task
|
||||||
// @Description Deletes a task from a list. This does not mean "mark it done".
|
// @Description Deletes a task from a list. This does not mean "mark it done".
|
||||||
|
Loading…
x
Reference in New Issue
Block a user