Roster View

A roster view presents resource-by-shift scheduling data as a grid. Each row in the source table is rendered as a resource (e.g. an employee, machine, or room) and the columns are the shifts (e.g. days, time slots, or allocation buckets) being rostered. Cell contents are rendered with shared Card templates registered on the view.

A roster is composed of three parts:

  • Resource column — the leftmost column identifying each row’s resource.

  • Shift columns — one column per slot being rostered, appearing after the resource column in the order they are added.

  • Summary column — an optional rightmost column showing per-row aggregates (e.g. total hours).

Cards rendered in a shift column can optionally be made drag-and-droppable by attaching a RosterTaskDefinition to the column. Drags are always within a single column — dragging a card from one row onto another row of the same column swaps the configured fields between those two rows.

Basic setup

Create the view, set the resource and (optional) summary columns, and add one shift column per slot being rostered:

roster_view = builder.add_roster_view(
    source_table=roster_table, display_name="Weekly Roster"
)

roster_view.set_resource_column(
    RosterColumn(table_field_reference=roster_table.get_field("employee"))
)

for shift in ("mon", "tue", "wed"):
    roster_view.add_shift_column(
        table_field_reference=roster_table.get_field(f"shift_{shift}"),
        minimum_width="120px",
    )

Card templates and per-column bindings

A single Card template is typically reused across every shift column. Placeholders in the template (e.g. ${[start]}) are filled in per-column by mapping each placeholder to that column’s source field:

shift_card = Card()
shift_card.add_element(Text("${[start]} - ${[end]}"))
roster_view.add_card_template("shift", shift_card)

for shift in ("mon", "tue", "wed"):
    column = roster_view.add_shift_column(
        default_card_template_key="shift", minimum_width="120px"
    )
    column.add_template_field_mapping(
        TemplateBindingKey("[start]"), roster_table.get_field(f"start_{shift}")
    )
    column.add_template_field_mapping(
        TemplateBindingKey("[end]"), roster_table.get_field(f"end_{shift}")
    )

Drag-and-drop

The helper below builds drag-and-drop configuration for one shift column of a roster. Each shift has its own set of per-column fields (availability, location, start/end times, capability lists), so the helper is parameterised by shift and called once per shift column.

def build_shift_drag_and_drop(
    roster_table: Table, shift: str
) -> RosterTaskDefinition:
    """Drag-and-drop config for one shift column of a roster."""
    task_def = RosterTaskDefinition(
        enable_drag_and_drop_field=roster_table.get_field(f"available_{shift}"),
        highlight_whole_column_on_drag=True,
    )

    # Fields whose values are exchanged between the source and target
    # rows on drop. The column's table_field_reference is typically a
    # calculation that recomputes from these — include it here only if
    # it is a data field that should also move.
    for field_name in (
        f"location_{shift}",
        f"start_time_{shift}",
        f"end_time_{shift}",
    ):
        task_def.add_swap_field(roster_table.get_field(field_name))

    # Gate valid drop targets: a drop is only allowed when the target
    # row's <capability> array contains the dragged card's <required>
    # value, for each pair below.
    requirements = [
        (f"location_{shift}",   f"location_options_{shift}"),
        (f"shift_type_{shift}", f"shift_type_options_{shift}"),
    ]
    for required, capability in requirements:
        task_def.add_requirement(
            required_field=roster_table.get_field(required),
            capability_field=roster_table.get_field(capability),
        )

    return task_def

# Attach to a shift column on the roster view:
monday = roster_view.add_shift_column(
    table_field_reference=roster_table.get_field("monday_shift"),
    minimum_width="80px",
)
monday.set_task_definition(build_shift_drag_and_drop(roster_table, "monday"))

API Reference

class RosterView(source_table, display_name=None, hidden=False)[source]

Bases: BaseView, FilterableView

Resource-by-shift tabular view.

Each row in source_table is rendered as a resource row; the columns are the resource column (leftmost identifier), the shift columns (one per slot being rostered), and an optional summary column.

source_table

Table ID of the source table whose rows back the roster.

card_templates

Shared Card templates, keyed by the strings referenced from RosterColumn.default_card_template_key and RosterColumn.header_card_template_key.

resource_column

Leftmost column identifying each row’s resource. Required for the view to be valid.

shift_columns

Ordered list of shift columns appearing after the resource column.

summary_column

Optional rightmost column showing per-row aggregates.

freeze_headers

If True, the header row stays fixed while the body scrolls vertically.

set_resource_column(col)[source]

Set the resource (leftmost) column. Returns self for chaining.

Return type:

RosterView

set_summary_column(col)[source]

Set the optional summary (rightmost) column. Returns self for chaining.

Return type:

RosterView

set_freeze_headers(freeze_headers)[source]

Set whether the header row stays fixed during vertical scrolling.

Return type:

RosterView

set_use_filter(use_filter)[source]

Attach a FilterComponent to this view and display its UI.

Sets both the bound filter (use_filter) and the displayed filter (show_filter) to use_filter.filter_name.

Return type:

RosterView

add_card_template(key, card)[source]

Register a shared card template on the view.

Card templates are looked up by key from RosterColumn.default_card_template_key and RosterColumn.header_card_template_key.

Parameters:
  • key (str) – Unique identifier referenced from RosterColumn template keys.

  • card (Card) – Card defining the template’s layout and content.

add_shift_column(table_field_reference=None, default_card_template_key=None, header_card_template_key=None, minimum_width=None)[source]

Append a shift column to the roster.

At least one of table_field_reference and default_card_template_key must be supplied. Any card-template keys provided must already be registered via add_card_template.

Parameters:
  • table_field_reference (Field | None) – Source-table Field providing this column’s value.

  • default_card_template_key (str | None) – Key of the card template used to render normal cells.

  • header_card_template_key (str | None) – Optional key of the card template used to render the header.

  • minimum_width (str | None) – Optional CSS minimum width (e.g. "80px").

Return type:

RosterColumn

Returns:

The newly created RosterColumn, already appended to shift_columns.

Raises:

ValueError – If a referenced card-template key is not registered, or if neither table_field_reference nor default_card_template_key is provided.

class RosterColumn(table_field_reference=None, default_card_template_key=None, header_card_template_key=None, minimum_width=None)[source]

Bases: Buildable

Configuration for a single column within a RosterView.

A column either binds directly to a source-table field (via table_field_reference) or renders its cells with a card template (via default_card_template_key); at least one of the two must be supplied.

table_field_reference

Field ID of the source-table field providing this column’s value. Required unless default_card_template_key is set.

default_card_template_key

Key of a card template registered on the parent RosterView used to render normal (non-header) cells for this column.

header_card_template_key

Optional card-template key used to render the column header.

minimum_width

Optional CSS width hint (e.g. "120px") setting the column’s minimum width.

template_field_mappings

Card-template placeholder keys (TemplateBindingKey) mapped to the model Field/Calculation/Parameter strings substituted in at render time.

model_event_mappings

Card-template placeholder keys mapped to ModelEvent instances fired when the corresponding UI element is activated.

task_definition

Optional RosterTaskDefinition configuring drag-and-drop behaviour for the cards rendered in this column. Has no effect on rendering or data binding.

add_template_field_mapping(key, value)[source]

Bind a card-template placeholder to a model value.

Parameters:
  • key (TemplateBindingKey) – Placeholder key declared in the card template.

  • value (Field | Calculation | Parameter) – Field, Calculation, or Parameter whose string form is substituted into the template at render time.

Return type:

RosterColumn

Returns:

This RosterColumn, for fluent chaining.

add_model_event_mapping(key, event)[source]

Bind a card-template placeholder to a ModelEvent.

Parameters:
  • key (TemplateBindingKey) – Placeholder key representing an interactive element in the card template.

  • event (ModelEvent) – ModelEvent fired when that element is activated.

Return type:

RosterColumn

Returns:

This RosterColumn, for fluent chaining.

set_task_definition(task_definition)[source]

Attach drag-and-drop configuration for cards in this column.

Parameters:

task_definition (RosterTaskDefinition) – RosterTaskDefinition describing draggability, which fields swap between rows on drop, and requirement/capability matching for valid drop targets.

Return type:

RosterColumn

Returns:

This RosterColumn, for fluent chaining.

class RosterTaskDefinition(enable_drag_and_drop_field, highlight_whole_column_on_drag)[source]

Bases: Buildable

Drag-and-drop configuration for the cards rendered in a roster column.

Attached to a RosterColumn via RosterColumn.set_task_definition(…), this describes only how cards in that column behave when the user drags them — it does not affect rendering, data binding, or which fields are displayed.

Drags are always within a single column: a card is dragged from one row onto another row of the same column, and the drop swaps the values of the configured swap_fields between those two rows. The column’s table_field_reference is typically a calculation that recomputes naturally from the swapped values; if it is a data field that should also move, add it to swap_fields explicitly.

enable_drag_and_drop_field

Field ID of a per-row boolean field on the source table that gates whether a given card is draggable.

highlight_whole_column_on_drag

UI hint controlling drop-target highlighting. If True, every card in the column is shaded green/red up-front (so the user can see which rows are valid drops before dragging over them). If False, only the card currently hovered is highlighted.

swap_fields

Complete list of field IDs whose values are swapped between the source and target rows when a drop occurs.

required_value_fields

Field IDs on the dragged card carrying scalar requirement values. Paired positionally with capability_fields to gate which target rows are valid drop targets: a drop is only permitted when, for every index i, the target row’s capability_fields[i] (an array) contains the dragged card’s required_value_fields[i] (a scalar of the matching type).

capability_fields

Field IDs on the target row holding array-valued capabilities, aligned positionally with required_value_fields.

__init__(enable_drag_and_drop_field, highlight_whole_column_on_drag)[source]
Parameters:
  • enable_drag_and_drop_field (Field) – Per-row boolean field gating whether each card is draggable.

  • highlight_whole_column_on_drag (bool) – If True, highlight the whole destination column while dragging.

add_swap_field(field)[source]

Register a field whose value is swapped between the source and target rows on drop.

Parameters:

field (Field) – Field whose value moves with the card: on drop, the source row’s value and the target row’s value are exchanged.

Return type:

RosterTaskDefinition

add_requirement(required_field, capability_field)[source]

Add a (requirement, capability) pair gating valid drop targets.

A drop is only permitted when the target row’s capability_field (an array) contains the dragged card’s required_field value (a scalar). The capability field’s data type must therefore be the array form of the required field’s data type.

Parameters:
  • required_field (Field) – Scalar field on the dragged card supplying the required value.

  • capability_field (Field) – Array-valued field on the target row whose contents must include required_field’s value for the drop to be valid.

Raises:

ValueError – If capability_field’s data type is not the array form of required_field’s data type.

Return type:

RosterTaskDefinition