diff --git a/api/handler/task.go b/api/handler/task.go index 6c53c7a44..b134cb648 100644 --- a/api/handler/task.go +++ b/api/handler/task.go @@ -263,6 +263,7 @@ type updateTaskIn struct { WatcherUsernames []string `json:"watcher_usernames"` WatcherGroups []string `json:"watcher_groups"` Tags map[string]string `json:"tags"` + DueDateAt *time.Time `json:"due_date_at"` } // UpdateTask modifies a task, allowing it's requester or an administrator @@ -324,6 +325,7 @@ func UpdateTask(c *gin.Context, in *updateTaskIn) (*task.Task, error) { t.SetInput(clearInput) t.SetWatcherUsernames(in.WatcherUsernames) t.SetWatcherGroups(in.WatcherGroups) + t.SetDueDateAt(in.DueDateAt) // validate read-only tags v, readOnlyTagUpdated := in.Tags[constants.SubtaskTagParentTaskID] diff --git a/models/task/task.go b/models/task/task.go index f7adff785..f3db613bd 100644 --- a/models/task/task.go +++ b/models/task/task.go @@ -85,6 +85,7 @@ type DBModel struct { StepsTotal int `json:"steps_total" db:"steps_total"` LastActivity time.Time `json:"last_activity" db:"last_activity"` Tags map[string]string `json:"tags,omitempty" db:"tags"` + DueDateAt *time.Time `json:"due_date_at,omitempty" db:"due_date_at"` CryptKey []byte `json:"-" db:"crypt_key"` // key for encrypting steps (itself encrypted with master key) EncryptedInput []byte `json:"-" db:"encrypted_input"` @@ -574,6 +575,12 @@ func (t *Task) SetWatcherGroups(watcherGroups []string) { t.WatcherGroups = watcherGroups } +// SetDueDateAt sets the due date for the task +// Pass nil to clear the due date +func (t *Task) SetDueDateAt(dueDateAt *time.Time) { + t.DueDateAt = dueDateAt +} + // SetInput sets the provided input for the task func (t *Task) SetInput(input map[string]interface{}) { t.Input = input @@ -692,7 +699,7 @@ func (t *Task) ExportTaskInfos(values *values.Values) { var ( tSelector = sqlgenerator.PGsql.Select( - `"task".id, "task".public_id, "task".title, "task".id_template, "task".id_batch, "task".requester_username, "task".requester_groups, "task".watcher_usernames, "task".watcher_groups, "task".created, "task".state, "task".tags, "task".steps_done, "task".steps_total, "task".crypt_key, "task".encrypted_input, "task".encrypted_result, "task".last_activity, "task".resolver_usernames, "task".resolver_groups, "task_template".name as template_name, "task_template".resolver_inputs as resolver_inputs, "resolution".public_id as resolution_public_id, "resolution".last_start as last_start, "resolution".last_stop as last_stop, "resolution".resolver_username as resolver_username, "batch".public_id as batch_public_id`, + `"task".id, "task".public_id, "task".title, "task".id_template, "task".id_batch, "task".requester_username, "task".requester_groups, "task".watcher_usernames, "task".watcher_groups, "task".created, "task".state, "task".tags, "task".steps_done, "task".steps_total, "task".crypt_key, "task".encrypted_input, "task".encrypted_result, "task".last_activity, "task".resolver_usernames, "task".resolver_groups, "task".due_date_at, "task_template".name as template_name, "task_template".resolver_inputs as resolver_inputs, "resolution".public_id as resolution_public_id, "resolution".last_start as last_start, "resolution".last_stop as last_stop, "resolution".resolver_username as resolver_username, "batch".public_id as batch_public_id`, ).From( `"task"`, ).Join( diff --git a/sql/migrations/011_task_due_date.sql b/sql/migrations/011_task_due_date.sql new file mode 100644 index 000000000..62c0cc1d8 --- /dev/null +++ b/sql/migrations/011_task_due_date.sql @@ -0,0 +1,4 @@ +-- Migration: Add due_date_at column to task table +-- Allows tasks to have an optional deadline + +ALTER TABLE "task" ADD COLUMN IF NOT EXISTS due_date_at TIMESTAMP with time zone; diff --git a/sql/schema.sql b/sql/schema.sql index 7d02c42e6..5edf91a07 100644 --- a/sql/schema.sql +++ b/sql/schema.sql @@ -57,7 +57,8 @@ CREATE TABLE "task" ( crypt_key BYTEA NOT NULL, encrypted_input BYTEA NOT NULL, encrypted_result BYTEA NOT NULL, - tags JSONB NOT NULL DEFAULT 'null' + tags JSONB NOT NULL DEFAULT 'null', + due_date_at TIMESTAMP with time zone ); CREATE INDEX ON "task"(id_template);