fix(task): make sure the task's last updated timestamp is always updated when releated entities changed
continuous-integration/drone/push Build is failing Details

This commit is contained in:
kolaente 2023-02-14 20:09:05 +01:00
parent 659803fadf
commit fceb5dae0f
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
7 changed files with 198 additions and 8 deletions

View File

@ -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 //
//////////////////////

View File

@ -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})
}
///////

View File

@ -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

View File

@ -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,7 +214,16 @@ func (ta *TaskAttachment) Delete(s *xorm.Session, a web.Auth) error {
if err != nil && files.IsErrFileDoesNotExist(err) {
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) {

View File

@ -109,7 +109,16 @@ func (tc *TaskComment) Delete(s *xorm.Session, a web.Auth) error {
if deleted == 0 {
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

View File

@ -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,7 +191,16 @@ func (rel *TaskRelation) Create(s *xorm.Session, a web.Auth) error {
rel,
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
@ -241,5 +251,14 @@ func (rel *TaskRelation) Delete(s *xorm.Session, a web.Auth) error {
_, err = s.
Where(cond).
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,
})
}

View File

@ -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".