A task (row) of the Gantt chart.
Tasks mirror the DHTMLX Gantt data model:
:id- unique identifier (integer, string or atom). Required.:text- the task name.:start_date,:end_date-NaiveDateTimeboundaries (end is exclusive).:duration- integer amount of the chart's duration unit (:dayby default).:progress- completion between0.0and1.0.:parent- id of the parent task,nilfor root tasks.:type-:task,:project(summary task whose dates are computed from its children) or:milestone(zero-duration event).:open- whether the children are expanded initially.:readonly- disables editing for this task.:color,:text_color,:progress_color- optional CSS colors.:calendar_id- the working-time calendar of the task (seeGanttEx.Calendar).:constraint_type,:constraint_date- scheduling constraint used by auto-scheduling (seeGanttEx.Schedulerandconstraint_types/0).:planned_start,:planned_end- the baseline (the original plan).:deadline- the date the task must be finished by.:render-:splitdraws the children of the task on its own row.:rollup- also show the task on the rows of its ancestor projects.:resources- resource assignments (seeGanttEx.Resource.cast_assignments/1).:has_children- the task has children that are not loaded yet (dynamic loading: expanding it sends a:branch_requestedevent).:meta- any additional fields (for custom grid columns, templates, ...).
Only one or two of :start_date, :end_date and :duration are needed: the
missing one is computed by GanttEx.Store (see GanttEx.Store.new/3).
Building tasks
new/1 accepts maps (atom or string keys), keyword lists and structs, such
as Ecto schemas. Unknown fields are kept in :meta, and :parent_id is
accepted as an alias of :parent:
iex> {:ok, task} = GanttEx.Task.new(%{"id" => 1, "text" => "Design", "start_date" => "2025-01-06", "duration" => 3, "owner" => "Ana"})
iex> {task.id, task.text, task.start_date, task.duration, task.meta}
{1, "Design", ~N[2025-01-06 00:00:00], 3, %{"owner" => "Ana"}}
iex> {:ok, task} = GanttEx.Task.new(id: 2, parent_id: 1, type: "milestone", start_date: ~D[2025-01-10])
iex> {task.parent, task.type}
{1, :milestone}
iex> GanttEx.Task.new(%{text: "No id"})
{:error, {:missing, :id}}
iex> GanttEx.Task.new(%{id: 1, progress: 50})
{:error, {:invalid, :progress}}
Summary
Types
A scheduling constraint: as soon/late as possible, start/finish no earlier/later than a date, or must start/finish on a date.
A task or link identifier.
The kind of task.
Functions
Casts a constraint type (DHTMLX codes such as "snet" or atoms).
Casts a task type from an atom or string.
Applies attrs on top of an existing task, casting only the given fields.
Returns the supported constraint types.
Returns true for milestones.
Builds a task from a map, keyword list or struct. See the module docs.
Like new/1 but raises ArgumentError on invalid attributes.
Returns true for project (summary) tasks.
Converts the task into a plain map, handy to persist it.
Returns the supported task types.
Types
@type constraint() :: :asap | :alap | :snet | :snlt | :fnet | :fnlt | :mso | :mfo
A scheduling constraint: as soon/late as possible, start/finish no earlier/later than a date, or must start/finish on a date.
A task or link identifier.
@type t() :: %GanttEx.Task{ calendar_id: term(), color: String.t() | nil, constraint_date: NaiveDateTime.t() | nil, constraint_type: constraint() | nil, deadline: NaiveDateTime.t() | nil, duration: non_neg_integer() | nil, end_date: NaiveDateTime.t() | nil, has_children: boolean(), id: id(), meta: map(), open: boolean(), parent: id() | nil, planned_end: NaiveDateTime.t() | nil, planned_start: NaiveDateTime.t() | nil, progress: float(), progress_color: String.t() | nil, readonly: boolean(), render: :split | nil, resources: [GanttEx.Resource.assignment()], rollup: boolean(), start_date: NaiveDateTime.t() | nil, text: String.t(), text_color: String.t() | nil, type: type() }
@type type() :: :task | :project | :milestone
The kind of task.
Functions
@spec cast_constraint(term()) :: {:ok, constraint() | nil} | :error
Casts a constraint type (DHTMLX codes such as "snet" or atoms).
iex> GanttEx.Task.cast_constraint("mso")
{:ok, :mso}
iex> GanttEx.Task.cast_constraint("")
{:ok, nil}
Casts a task type from an atom or string.
iex> GanttEx.Task.cast_type("project")
{:ok, :project}
iex> GanttEx.Task.cast_type(nil)
{:ok, :task}
iex> GanttEx.Task.cast_type("epic")
:error
Applies attrs on top of an existing task, casting only the given fields.
The :id cannot be changed. Unknown fields are merged into :meta.
iex> task = GanttEx.Task.new!(id: 1, text: "Draft", start_date: ~D[2025-01-01])
iex> {:ok, task} = GanttEx.Task.change(task, %{"text" => "Final", "progress" => "0.25"})
iex> {task.text, task.progress}
{"Final", 0.25}
@spec constraint_types() :: [constraint()]
Returns the supported constraint types.
iex> GanttEx.Task.constraint_types()
[:asap, :alap, :snet, :snlt, :fnet, :fnlt, :mso, :mfo]
Returns true for milestones.
iex> GanttEx.Task.milestone?(GanttEx.Task.new!(id: 1, type: :milestone))
true
Builds a task from a map, keyword list or struct. See the module docs.
Like new/1 but raises ArgumentError on invalid attributes.
iex> GanttEx.Task.new!(id: 1, text: "Kickoff", start_date: ~D[2025-01-01]).text
"Kickoff"
Returns true for project (summary) tasks.
iex> GanttEx.Task.project?(GanttEx.Task.new!(id: 1))
false
Converts the task into a plain map, handy to persist it.
:meta fields are merged at the top level unless meta: false is given.
iex> task = GanttEx.Task.new!(id: 1, text: "A", start_date: ~D[2025-01-01], duration: 2, priority: :high)
iex> GanttEx.Task.to_map(task) |> Map.take([:id, :text, :duration, :priority])
%{id: 1, text: "A", duration: 2, priority: :high}
@spec types() :: [type()]
Returns the supported task types.
iex> GanttEx.Task.types()
[:task, :project, :milestone]