# Graph Builder

The **Graph Builder** module lets administrators create simple charts from existing tables. It features a dropdown to select the table, another dropdown to choose the chart type and a palette of the table's columns. Drag columns into the **Drop X Column**, **Drop Y Column**, **Drop Radius Column** and **Drop Label Column** areas to plot the data using D3. The radius and label drop zones are optional and allow varying point sizes and labels on scatter or line charts.

Graphs can be saved and loaded through the `/api/graphs` endpoints. Click **Save** to persist the current configuration or **Load** to enter the ID of a previously saved graph.

## Usage

1. Open **Graph Builder** from the dashboard.
2. Choose a table from the dropdown.
3. Drag columns onto the X and Y drop zones.
4. The chart renders automatically and supports pan and zoom.
5. Use **Save** to store the graph or **Load** to retrieve a saved one.
6. Click **Download PDF** to save the rendered chart as a PDF file.

## Configuration Options

Saved graphs use this JSON structure:

```json
{
  "table": "table_name",
  "x": "column_for_x_axis",
  "y": "column_for_y_axis",
  "r": "column_for_radius",
  "label": "column_for_labels",
  "type": "chart_type",
  "groupBy": "column_to_group",
  "aggregateFunc": "aggregate_function",
  "timeUnit": "time_unit"
}
```

- **table** – name of the table queried for rows.
- **x** – column used on the X axis.
- **y** – column used on the Y axis.
- **r** – column that controls point radius (optional).
- **label** – column providing tooltip labels (optional).
- **type** – chart type (`scatter`, `line`, `bar`, `stackedBar`, `groupedBar`, `pie`).
- **groupBy** – column to group records by before plotting (optional). For grouped bars supply two comma-separated columns (e.g. `date,classification`).
- **aggregateFunc** – function applied to the Y column when grouping (`sum`, `avg`, `count`, `min`, `max`).
- **timeUnit** – bucket date/time groups by `day`, `week` or `month`.

Definitions are stored in the `graphs` table with `tenant_id` and `branch_id` so each counsel can manage its own charts. The builder fetches rows using `SyncManagerSingleton` and performs an `immediateSync()` if the local store is empty.

The builder caches fetched rows in memory so switching the chart type reuses the same data without hitting the API again.

## Group By, Aggregate Function and Time Unit

Three additional dropdowns appear below the chart type selector:

1. **Group By** – choose a column to group records. When set, data is aggregated before rendering.
2. **Aggregate Function** – select how grouped values are calculated. Supported options are `sum`, `avg`, `count`, `min` and `max`.
3. **Time Unit** – when the group-by column contains dates, pick `day`, `week` or `month` to bucket timestamps.

An example configuration using these options:

```json
{
  "table": "sales",
  "x": "order_date",
  "y": "amount",
  "type": "bar",
  "groupBy": "order_date",
  "aggregateFunc": "sum",
"timeUnit": "month"
}
```

### Grouped Bar Example with Dynamic Time Units

Set `"type": "groupedBar"` and specify two columns in `groupBy` separated by a
comma to display grouped bars per time period and category. The first column must
be a date field. Use `timeUnit` to choose the default bucket (`year`, `month` or
`week`) and set `timeDropdown` to `true` so viewers can switch between units.

```json
{
  "table": "ohs_incidents",
  "x": "date",
  "y": "id",
  "type": "groupedBar",
  "groupBy": "date,classification",
  "aggregateFunc": "count",
  "timeUnit": "year",
  "timeDropdown": true
}
```
