Timeline Grid Component
Introduction
The Timeline Grid Component renders a scheduling grid with time on the horizontal axis and resources on the vertical axis. It is designed for allocation, dispatch, and capacity planning scenarios where you need to place and manipulate time spans (items) across multiple resources.
Unlike timeline
, which focuses on a linear sequence of events, timelineGrid
provides a matrix-like layout with rows (resources such as drivers, vehicles, docks, lanes, or teams) and time columns (hours/days/weeks). It supports virtualization for large datasets, range-based server loading, and rich interactions such as drag, drop, resize, and reassignment between resources.
Common use cases in CargoXplorer TMS:
- Vehicle/driver assignment board
- Dock and door scheduling by shift
- Warehouse lane/zone utilization planning
- Yard slot allocation
- Technician/maintenance work orders by bay
YAML Structure
component: timelineGrid
name: vehicleScheduler
props:
view: "day" # hour | day | week | month (see timescale below)
startDate: "{{ startDate }}" # optional; initial lower bound (ISO or expression)
endDate: "{{ endDate }}" # optional; initial upper bound (ISO or expression)
defaultDate: "{{ today() }}" # initial focal date when no explicit range
options:
height: "600px" # px, %, vh
rowHeight: 44 # px per row
timescale: "hour" # hour | day | week | month
timeStepMinutes: 30 # grid cell resolution when timescale=hour
snapToMinutes: 15 # drag/resize snap increment
showNowMarker: true # show current time line
showNonWorking: true # shade non-working hours/days
workingHours: ["06:00", "22:00"] # daily working window (local time)
weekendDays: [6, 7] # 1=Mon ... 7=Sun
allowOverlap: false # allow items to overlap in the same row
editable:
move: true # drag to move
resize: true # resize start/end
reassign: true # drag between rows to reassign resource
virtualization: true # virtualize rows for large datasets
stickyHeaders: true # keep time header and row headers sticky
rowTemplate: # optional; custom render for row header cell
component: layout
props:
orientation: horizontal
children:
- component: text
props: { type: "strong", value: "{{ row.label }}" }
- component: badge
if: "{{ row.status }}"
props: { value: "{{ row.status }}" }
itemTemplate: # how each time span renders in the grid
component: card
props:
title: "{{ item.title }}"
description: "{{ item.description }}"
backgroundColor: "{{ item.color || '#3788d8' }}"
textColor: "white"
# Data sources
rowSources: # load resources (rows) for the visible range
- query:
command: >-
query GetVehicles($organizationId: Int!) {
vehicles(organizationId: $organizationId) { id code status type }
}
variables:
organizationId: "{{ number organizationId }}"
path: vehicles
mapping:
rowId: "{{ item.id }}" # required
label: "{{ item.code }}" # required
status: "{{ item.status }}" # optional
type: "{{ item.type }}" # optional
itemSources: # load items (spans) for the visible window
- query:
command: >-
query VehicleAssignments($organizationId: Int!, $start: String!, $end: String!) {
vehicleAssignments(organizationId: $organizationId, start: $start, end: $end) {
id vehicleId start end shipmentId status priority
}
}
variables:
organizationId: "{{ number organizationId }}"
start: "{{ startDate }}"
end: "{{ endDate }}"
path: vehicleAssignments
mapping:
id: "{{ item.id }}" # required
rowId: "{{ item.vehicleId }}" # required; resource association
start: "{{ item.start }}" # required ISO
end: "{{ item.end }}" # required ISO
title: "Shipment {{ item.shipmentId }}" # required title
status: "{{ item.status }}"
priority: "{{ item.priority }}"
color: "{{ eval item.status === 'delayed' ? '#e53e3e' : (item.priority === 'high' ? '#ffa726' : '#4ecdc4') }}"
# Interaction events
events:
onItemClick:
- navigate:
to: "/shipments/{{ event.item.shipmentId }}"
onItemMove: # after drag/drop move (same row)
- mutation:
command: >-
mutation UpdateSchedule($id: ID!, $start: String!, $end: String!) {
updateVehicleAssignment(id: $id, start: $start, end: $end) { id start end }
}
variables:
id: "{{ event.item.id }}"
start: "{{ event.newStart }}"
end: "{{ event.newEnd }}"
onSuccess:
- notification: { message: "Schedule updated" }
onError:
- notification:
{ message: "Failed to update schedule", variant: "error" }
onItemReassign: # after drag to a different row
- mutation:
command: >-
mutation Reassign($id: ID!, $vehicleId: ID!, $start: String!, $end: String!) {
reassignVehicle(id: $id, vehicleId: $vehicleId, start: $start, end: $end) { id vehicleId start end }
}
variables:
id: "{{ event.item.id }}"
vehicleId: "{{ event.newRowId }}"
start: "{{ event.newStart }}"
end: "{{ event.newEnd }}"
onSuccess:
- notification: { message: "Reassigned" }
onError:
- notification: { message: "Failed to reassign", variant: "error" }
onRangeChange: # visible window changed by scroll/zoom/nav
- setVariables:
windowStart: "{{ event.start }}"
windowEnd: "{{ event.end }}"
onEmptySlotClick: # click on empty time cell
- dialog:
name: "createAssignment"
props:
rowId: "{{ event.row.rowId }}"
start: "{{ event.start }}"
end: "{{ event.end }}"
Attribute Description
Root
component
(string, required): Must betimelineGrid
.name
(string, optional): Component instance name for referencing in actions/variables.props
(object, required): Grid configuration.rowSources
(array, required): Data providers for resources (rows).itemSources
(array, required): Data providers for time spans (items).events
(object, optional): Interaction handlers.
Props
Attribute | Type | Required | Default | Description |
---|---|---|---|---|
view | enum | No | day | Zoom level preset. Works with timescale . |
startDate | templateExpression | No | — | Initial lower bound for visible window (ISO or expression). |
endDate | templateExpression | No | — | Initial upper bound for visible window. |
defaultDate | templateExpression | No | {{ today() }} | Initial focal date when range not provided. |
options | object | No | see below | Visual/behavioral options. |
rowTemplate | componentDefinition | No | default label | Template for row header cell. Receives row . |
itemTemplate | componentDefinition | No | card | Template for items. Receives item . |
Options
Attribute | Type | Default | Description |
---|---|---|---|
height | string|number | 600px | Grid height. |
rowHeight | number | 44 | Row height in pixels. |
timescale | enum | hour | Time unit on X-axis: hour , day , week , month . |
timeStepMinutes | number | 30 | Cell width resolution when timescale=hour . |
snapToMinutes | number | 15 | Drag/resize snap step. |
showNowMarker | boolean | true | Displays current time marker line. |
showNonWorking | boolean | true | Shades non-working periods. |
workingHours | [string,string] | ["06:00","22:00"] | Daily working period. |
weekendDays | number[] | [6,7] | Weekend day numbers (1=Mon..7=Sun). |
allowOverlap | boolean | false | Allow overlaps within the same row. |
editable.move | boolean | true | Enable drag move. |
editable.resize | boolean | true | Enable resize. |
editable.reassign | boolean | true | Enable row reassignment by drag. |
virtualization | boolean | true | Virtualize rows for performance. |
stickyHeaders | boolean | true | Sticky time header and row headers. |
Row Sources
Each entry defines how to fetch rows (resources) and map them to the grid.
Attribute | Type | Required | Description |
---|---|---|---|
query | object | Yes | GraphQL query configuration. |
query.command | string | Yes | GraphQL document string. |
query.variables | object | No | Variables for query. Template expressions supported. |
path | string | Yes | Dot path to array of rows in response. |
mapping | object | Yes | Mapping from source to row fields. |
Required row mapping fields:
rowId
(string|number): Unique row identifier.label
(string): Row display label.
Common optional row fields:
group
(string): Group name for collapsible grouping.status
(string),type
(string),color
(string): Extra row metadata available torowTemplate
.
Item Sources
Each entry describes how to load time spans within the current visible window.
Attribute | Type | Required | Description |
---|---|---|---|
query | object | Yes | GraphQL query configuration. |
query.command | string | Yes | GraphQL document string. |
query.variables | object | Yes | Should include start and end for window scoping. |
path | string | Yes | Dot path to array of items in response. |
mapping | object | Yes | Mapping from source to item fields. |
Required item mapping fields:
id
(string|number): Unique item identifier.rowId
(string|number): Row association.start
(string, ISO): Start datetime.end
(string, ISO): End datetime.title
(string): Display title.
Common optional item fields:
description
(string),status
(string),priority
(string|number)color
(string),textColor
(string),className
(string)- Any mapped fields are available via
{{ item.<prop> }}
initemTemplate
.