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"
|
||||
}
|
||||
|
||||
// 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
|
||||
type TaskCommentCreatedEvent struct {
|
||||
Task *Task
|
||||
@ -104,6 +116,66 @@ func (t *TaskCommentUpdatedEvent) Name() string {
|
||||
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 //
|
||||
//////////////////////
|
||||
|
@ -51,6 +51,15 @@ func RegisterListeners() {
|
||||
events.RegisterListener((&TaskCreatedEvent{}).Name(), &HandleTaskCreateMentions{})
|
||||
events.RegisterListener((&TaskUpdatedEvent{}).Name(), &HandleTaskUpdatedMentions{})
|
||||
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,
|
||||
IsNew: false,
|
||||
}
|
||||
|
||||
_, err = notifyMentionedUsers(sess, event.Task, event.Task.Description, n)
|
||||
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)
|
||||
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
|
||||
|
@ -17,6 +17,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
@ -44,7 +45,7 @@ type TaskAttachment struct {
|
||||
}
|
||||
|
||||
// TableName returns the table name for task attachments
|
||||
func (TaskAttachment) TableName() string {
|
||||
func (*TaskAttachment) TableName() string {
|
||||
return "task_attachments"
|
||||
}
|
||||
|
||||
@ -84,7 +85,11 @@ func (ta *TaskAttachment) NewAttachment(s *xorm.Session, f io.ReadCloser, realna
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return events.Dispatch(&TaskAttachmentCreatedEvent{
|
||||
Task: &Task{ID: ta.TaskID},
|
||||
Attachment: ta,
|
||||
Doer: ta.CreatedBy,
|
||||
})
|
||||
}
|
||||
|
||||
// ReadOne returns a task attachment
|
||||
@ -209,9 +214,18 @@ func (ta *TaskAttachment) Delete(s *xorm.Session, a web.Auth) error {
|
||||
if err != nil && files.IsErrFileDoesNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
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) {
|
||||
attachments = []*TaskAttachment{}
|
||||
err = s.
|
||||
|
@ -109,9 +109,18 @@ func (tc *TaskComment) Delete(s *xorm.Session, a web.Auth) error {
|
||||
if deleted == 0 {
|
||||
return ErrTaskCommentDoesNotExist{ID: tc.ID}
|
||||
}
|
||||
|
||||
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
|
||||
// @Summary Update an existing task comment
|
||||
// @Description Update an existing task comment. The user doing this need to have at least write access to the task this comment belongs to.
|
||||
|
@ -17,6 +17,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"time"
|
||||
|
||||
"xorm.io/builder"
|
||||
@ -98,7 +99,7 @@ type TaskRelation struct {
|
||||
}
|
||||
|
||||
// TableName holds the table name for the task relation table
|
||||
func (TaskRelation) TableName() string {
|
||||
func (*TaskRelation) TableName() string {
|
||||
return "task_relations"
|
||||
}
|
||||
|
||||
@ -190,9 +191,18 @@ func (rel *TaskRelation) Create(s *xorm.Session, a web.Auth) error {
|
||||
rel,
|
||||
otherRelation,
|
||||
})
|
||||
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
|
||||
// @Summary Remove a task relation
|
||||
// @tags task
|
||||
@ -241,5 +251,14 @@ func (rel *TaskRelation) Delete(s *xorm.Session, a web.Auth) error {
|
||||
_, err = s.
|
||||
Where(cond).
|
||||
Delete(&TaskRelation{})
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
// @Summary Delete a task
|
||||
// @Description Deletes a task from a list. This does not mean "mark it done".
|
||||
|
Loading…
x
Reference in New Issue
Block a user