Packages

Interactive Gantt charts for Phoenix LiveView: tasks, dependencies, drag & drop scheduling, zoomable scales and i18n, with minimal JavaScript.

Current section

Files

Jump to
gantt_ex README.md
Raw

README.md

# GanttEx

Interactive Gantt charts for **Phoenix LiveView**, inspired by
[DHTMLX Gantt](https://github.com/DHTMLX/gantt).

State, validation, layout and dialogs live on the server. The only
JavaScript is one small colocated hook for what needs the mouse:
dragging, resizing and drawing dependencies.

```heex
<.live_component module={GanttEx.Live.Gantt} id="gantt" tasks={@tasks} links={@links} locale="es" />
```

## Features

These are the features of the DHTMLX Gantt community edition:

- **Task grid**: tree, configurable columns (slots), sorting, resizable
  columns and grid, inline editing
- **Task types**: tasks, projects (dates rolled up from their children) and milestones
- **Drag & drop**: move, resize and change progress, with snapping; reorder
  and re-parent rows
- **Dependencies**: finish-to-start, start-to-start, finish-to-finish and
  start-to-finish with lag, drawn by dragging between bar edges, with
  cycle detection
- **Zoomable time scale**: hours, days, weeks, months, quarters and years,
  or your own levels
- **Lightbox editor** with configurable sections and custom fields, quick
  info popup, tooltips and confirmation dialogs
- **Drag to create** tasks on the timeline and drag to pan, with edge
  auto-scrolling
- **Smart rendering**: large charts only render the rows around the viewport
- **Keyboard navigation**, fullscreen and print (PDF)
- **Export** to JSON (DHTMLX format), CSV/Excel, iCalendar, MS Project XML,
  SVG and PNG; **import** from DHTMLX JSON/XML and MS Project XML
- **8 languages**: English, Spanish, French, Italian, German, Portuguese,
  Brazilian Portuguese and Japanese (Gettext `.po` files)
- **Light and dark themes** based on CSS custom properties, WAI-ARIA roles,
  touch support and reduced motion
- **Events for persistence**: every change is sent to your LiveView as
  `{GanttEx, %GanttEx.Event{}}`

And the features of the PRO edition (see the
[Advanced features](guides/pro_features.md) guide):

- **Working-time calendars** with holidays and per-task calendars
- **Auto-scheduling** with the eight task constraints, strict mode and ALAP
- **Critical path** and total/free **slack**
- **Baselines** and **deadlines** with overdue detection
- **Resources**: assignments, load histogram and overload detection
- **Grouping** by any field or by resource
- **Split tasks** and **rollups**
- **Undo/redo**, **multi-selection** and multi-drag
- **Timeline markers**, **WBS codes**, **dynamic loading** and **auto types**

## Installation

Add `gantt_ex` to your dependencies (Phoenix 1.8+, LiveView 1.2+):

```elixir
def deps do
  [
    {:gantt_ex, "~> 0.1.0"}
  ]
end
```

Register the hook in `assets/js/app.js`:

```javascript
import {hooks as ganttHooks} from "phoenix-colocated/gantt_ex"

const liveSocket = new LiveSocket("/live", Socket, {
  hooks: {...colocatedHooks, ...ganttHooks},
  // ...
})
```

Import the styles in `assets/css/app.css` (Tailwind 4.2.3+):

```css
@import "phoenix-colocated/gantt_ex/colocated.css";
```

New Phoenix 1.8 applications already have the `NODE_PATH` and compiler
configuration needed to resolve `phoenix-colocated`. See
`Phoenix.LiveView.ColocatedJS` if yours does not.

## Usage

```elixir
defmodule MyAppWeb.ProjectLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, tasks: Planning.list_tasks(), links: Planning.list_links())}
  end

  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash}>
      <.live_component module={GanttEx.Live.Gantt} id="gantt" tasks={@tasks} links={@links} />
    </Layouts.app>
    """
  end

  # Persist every change, then re-render the chart with fresh data.
  def handle_info({GanttEx, %GanttEx.Event{} = event}, socket) do
    :ok = Planning.apply_event(event)
    {:noreply, assign(socket, tasks: Planning.list_tasks(), links: Planning.list_links())}
  end
end
```

Tasks can be maps, keyword lists or structs (Ecto schemas included) with
DHTMLX field names: `id`, `text`, `start_date`, `end_date`, `duration`,
`progress` (0..1), `parent` (or `parent_id`), `type` and `open`. Any other
field ends up in `task.meta` and can be shown in custom columns.

```heex
<.live_component module={GanttEx.Live.Gantt} id="gantt" tasks={@tasks} links={@links} zoom={:week}>
  <:column field={:text} tree />
  <:column field={:owner} label="Owner" editor={:text} :let={task}>{task.meta[:owner]}</:column>
  <:column field={:start_date} />
  <:column field={:duration} />
  <:column field={:add} />
</.live_component>
```

## Guides

- [Getting started](guides/getting_started.md)
- [Persistence](guides/persistence.md)
- [Customization](guides/customization.md)
- [Internationalization](guides/i18n.md)
- [Advanced features](guides/pro_features.md)

## Example application

`example/live_gantt` is a Phoenix application that
stores a project in Postgres:

```shell
cd example/live_gantt
mix setup
mix phx.server
```

## Development

```shell
mix test       # unit tests, LiveView tests and doctests
mix docs       # documentation
mix precommit  # compile with warnings as errors, format and test
```

## License

MIT, see the `LICENSE` file.