fix(filters): add task to buckets of saved filters when creating the task
This commit is contained in:
parent
327905bb90
commit
5cc420b289
@ -23,7 +23,6 @@ import (
|
||||
"time"
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
@ -66,6 +65,7 @@ func RegisterListeners() {
|
||||
events.RegisterListener((&TaskAttachmentDeletedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||
events.RegisterListener((&TaskRelationCreatedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||
events.RegisterListener((&TaskRelationDeletedEvent{}).Name(), &HandleTaskUpdateLastUpdated{})
|
||||
events.RegisterListener((&TaskCreatedEvent{}).Name(), &UpdateTaskInSavedFilterViews{})
|
||||
if config.TypesenseEnabled.GetBool() {
|
||||
events.RegisterListener((&TaskDeletedEvent{}).Name(), &RemoveTaskFromTypesense{})
|
||||
events.RegisterListener((&TaskCreatedEvent{}).Name(), &AddTaskToTypesense{})
|
||||
@ -671,6 +671,91 @@ func (s *DecreaseAttachmentCounter) Handle(_ *message.Message) (err error) {
|
||||
return keyvalue.DecrBy(metrics.AttachmentsCountKey, 1)
|
||||
}
|
||||
|
||||
// UpdateTaskInSavedFilterViews represents a listener
|
||||
type UpdateTaskInSavedFilterViews struct {
|
||||
}
|
||||
|
||||
// Name defines the name for the UpdateTaskInSavedFilterViews listener
|
||||
func (l *UpdateTaskInSavedFilterViews) Name() string {
|
||||
return "task.set.saved.filter.views"
|
||||
}
|
||||
|
||||
// Handle is executed when the event UpdateTaskInSavedFilterViews listens on is fired
|
||||
func (l *UpdateTaskInSavedFilterViews) Handle(msg *message.Message) (err error) {
|
||||
event := &TaskCreatedEvent{}
|
||||
err = json.Unmarshal(msg.Payload, event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This operation is potentially very resource-heavy, because we don't know if a task is included
|
||||
// in a filter until we evaluate that filter. We need to evaluate each filter individually - since
|
||||
// there can be many filters, this can take a while to execute.
|
||||
// For this reason, we do this in an asynchronous event listener.
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
// Get all saved filters with a manual kanban view
|
||||
kanbanFilterViews := []*ProjectView{}
|
||||
err = s.Where("project_id < 0 and view_kind = ? and bucket_configuration_mode = ?", ProjectViewKindKanban, BucketConfigurationModeManual).
|
||||
Find(&kanbanFilterViews)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filterIDs := []int64{}
|
||||
for _, view := range kanbanFilterViews {
|
||||
filterIDs = append(filterIDs, getSavedFilterIDFromProjectID(view.ProjectID))
|
||||
}
|
||||
|
||||
filters := map[int64]*SavedFilter{}
|
||||
err = s.In("id", filterIDs).Find(&filters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u, err := user.GetUserByID(s, event.Doer.GetID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doerTimezone := u.Timezone
|
||||
|
||||
taskBuckets := []*TaskBucket{}
|
||||
taskPositions := []*TaskPosition{}
|
||||
|
||||
for _, view := range kanbanFilterViews {
|
||||
filter, exists := filters[getSavedFilterIDFromProjectID(view.ProjectID)]
|
||||
if !exists {
|
||||
log.Debugf("Did not find filter for view %d", view.ID)
|
||||
continue
|
||||
}
|
||||
|
||||
taskBucket, taskPosition, err := addTaskToFilter(s, filter, view, doerTimezone, event.Task)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if taskBucket != nil && taskPosition != nil {
|
||||
taskBuckets = append(taskBuckets, taskBucket)
|
||||
taskPositions = append(taskPositions, taskPosition)
|
||||
}
|
||||
}
|
||||
|
||||
if len(taskBuckets) > 0 || len(taskPositions) > 0 {
|
||||
_, err = s.Insert(taskBuckets)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = s.Insert(taskPositions)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
///////
|
||||
// Project Event Listeners
|
||||
|
||||
|
@ -18,8 +18,11 @@ package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"xorm.io/builder"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
|
||||
"code.vikunja.io/web"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
@ -214,3 +217,54 @@ func (sf *SavedFilter) Delete(s *xorm.Session, _ web.Auth) error {
|
||||
Delete(sf)
|
||||
return err
|
||||
}
|
||||
|
||||
func addTaskToFilter(s *xorm.Session, filter *SavedFilter, view *ProjectView, fallbackTimezone string, task *Task) (taskBucket *TaskBucket, taskPosition *TaskPosition, err error) {
|
||||
|
||||
filterString := filter.Filters.Filter
|
||||
|
||||
if filter.Filters.FilterTimezone == "" {
|
||||
filter.Filters.FilterTimezone = fallbackTimezone
|
||||
}
|
||||
|
||||
parsedFilters, err := getTaskFiltersFromFilterString(filterString, filter.Filters.FilterTimezone)
|
||||
if err != nil {
|
||||
log.Errorf("Could not parse filter string '%s' from view %d and saved filter %d: %v", filterString, view.ID, filter.ID, err)
|
||||
return
|
||||
}
|
||||
|
||||
filterCond, err := convertFiltersToDBFilterCond(parsedFilters, filter.Filters.FilterIncludeNulls)
|
||||
if err != nil {
|
||||
log.Errorf("Could not convert filter string '%s' from view %d and saved filter %d to db conditions: %v", filterString, view.ID, filter.ID, err)
|
||||
return
|
||||
}
|
||||
|
||||
taskIsInCurrentFilterAndView, err := s.Where(builder.And(
|
||||
filterCond,
|
||||
builder.Eq{"id": task.ID},
|
||||
)).Exist(&Task{})
|
||||
if !taskIsInCurrentFilterAndView {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
bucketID, err := getDefaultBucketID(s, view)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
taskBucket = &TaskBucket{
|
||||
BucketID: bucketID,
|
||||
TaskID: task.ID,
|
||||
ProjectViewID: view.ID,
|
||||
}
|
||||
|
||||
taskPosition = &TaskPosition{
|
||||
TaskID: task.ID,
|
||||
ProjectViewID: view.ID,
|
||||
Position: calculateDefaultPosition(task.Index, task.Position),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user