# Container Designer & Dashboard Cards

The Container Designer is the visual dashboard authoring tool in OtisEd.Nimble. Administrators use it to build configurable data dashboards — called **containers** — by placing and arranging **cards** on a responsive grid. Each card displays a distinct type of content (chart, table, KPI metric, filter panel, HTML block, embedded report, and more). Finished containers can be surfaced to end users through Report Groups or embedded anywhere in the portal.

## Table of Contents

* [Who Uses It](#who-uses-it)
* [Concepts](#concepts)
* [Finding the Container Designer](#finding-the-container-designer)
* [Creating and Managing Containers](#creating-and-managing-containers)
* [Designing a Container](#designing-a-container)
* [Available Card Types](#available-card-types)
* [Configuring Card Data Sources](#configuring-card-data-sources)
* [Responsive Layout](#responsive-layout)
* [Preview Mode vs. Design Mode](#preview-mode-vs-design-mode)
* [Viewing a Container at Runtime](#viewing-a-container-at-runtime)
* [Event Bus: Filter and Publisher/Subscriber Cards](#event-bus-filter-and-publishersubscriber-cards)
* [Data Suppression](#data-suppression)
* [Expand and Print Actions](#expand-and-print-actions)
* [Cloning Containers](#cloning-containers)
* [Permissions](#permissions)
* [Troubleshooting](#troubleshooting)

***

## Who Uses It

| Role                         | What they do                                                                                                  |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Administrator / Designer** | Creates, edits, and deletes containers; configures cards and data sources; manages layout across breakpoints. |
| **Report Manager**           | Assigns containers to Report Groups so users can view them on report pages.                                   |
| **End User**                 | Views the finished dashboard; may interact with filter cards; cannot edit the layout.                         |

***

## Concepts

**Container** — A named dashboard canvas that holds one or more cards. A container has a name (used in admin lists), an optional display title (shown to viewers), an optional description, and a row height setting that controls the vertical sizing of all grid cells.

**Card** — A single content block placed on the container grid. Every card has a type (e.g., `bar-chart`, `kpi`, `data-grid`), a unique identifier within the container, layout coordinates for each responsive breakpoint, and a configuration object that controls its appearance and behavior.

**Card Data** — Pre-loaded data stored separately from the card configuration. When a container is viewed, the system looks up matching data by organization/term context and merges it into each card before rendering. This separation lets data be refreshed independently of the layout design.

**Breakpoint** — A named screen-width tier (`Large`, `Medium`, `Small`, `Print`) used to control how cards resize and reposition at different viewport widths.

**Event Bus** — A message-passing channel scoped to a single container. Cards can publish events (filter changes, property changes) and subscribe to events from other cards, enabling coordinated cross-card interactions such as a filter panel controlling chart data.

***

## Finding the Container Designer

Navigate to **Admin > Container Designer** (the exact menu path may vary by tenant configuration). The landing page shows a searchable table of all containers for your tenant.

By default the table shows only **active** containers. Check **Show inactive containers** to include containers that have been deactivated.

Use the **Filter Containers** text box to search by name or description.

***

## Creating and Managing Containers

### Create a new container

Click **+ New Container**. A blank canvas opens immediately with a temporary container called "New Container". Fill in the name and other settings in the properties panel on the right before saving.

### Edit an existing container

Click the **Edit** icon (pencil) on any row in the container table. The full container and all its card configurations load before the designer canvas appears.

### Clone an existing container

Click the **Clone** icon on a container row. A dialog appears with the suggested name "Copy of \[original name]" — you can change the name, title, description, and row height before confirming. The clone copies all cards and their configurations exactly; card data records are not copied.

### Delete a container

Deletion is available from within the designer. This action requires the **Containers.Delete** permission and permanently removes the container and all its cards.

***

## Designing a Container

When a container is open in the designer you work in one of two modes: **Design Mode** (editing) and **Preview Mode** (read-only simulation). See [Preview Mode vs. Design Mode](#preview-mode-vs-design-mode).

### Container settings

In Design Mode, the right-hand sidebar shows the container's properties:

| Field           | Description                                                                                                                |
| --------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Name**        | Internal identifier used in admin lists. Required.                                                                         |
| **Title**       | Display title shown to viewers. Optional.                                                                                  |
| **Description** | Free-text description. Optional.                                                                                           |
| **Row Height**  | Vertical height (in pixels) of a single grid row. Changing this affects all card heights proportionally. Default is 30 px. |
| **Active**      | When unchecked, the container is hidden from viewer interfaces.                                                            |

### Adding a card

In Design Mode, use the **Add Card** palette to browse all available card types by category. Click a type to add it to the canvas. The card is placed at the next available position on the grid with its default dimensions.

### Moving and resizing cards

Drag a card by its title bar to reposition it. Drag the resize handle at the card's bottom-right corner to change its size. All movements snap to the grid.

### Configuring a card

Click a card to select it. The right sidebar switches to show that card's **Properties** panel, which groups configurable settings by category (General, Display, Appearance, Data, Layout, etc.). Settings vary by card type — see [Available Card Types](#available-card-types) for details specific to each type.

Every card has a **Card ID** field (the `ContainerCardId`). This is the unique string identifier for the card within the container (for example, `enrollment-bar-chart-1`). Card IDs must be unique within a container. The system uses this ID to match card configuration with stored data and to route event bus messages.

Most card types include a **Card Data** section in the properties panel where you can navigate directly to the container card data records for that card. A small number of card types that source their data independently — such as the **Form Card**, which fetches form responses directly at view time — do not show the Card Data section, because Container Card Data records do not apply to them.

### Removing a card

Select the card and click the **Remove** button in the properties panel, or use the remove action in the card's context menu.

### Duplicating a card

Select the card and use the **Duplicate** action. The copy gets a new Card ID and is placed adjacent to the original.

### Saving

Click **Save** to persist the container and all its cards to the backend. If the container is new, it is created; if it already exists, all cards are reconciled (new cards inserted, changed cards updated, removed cards deleted) in a single operation.

Click **Cancel** to discard unsaved changes and return to the container list.

***

## Available Card Types

Cards are grouped into two broad categories in the Add Card palette.

> For the complete property reference for every card type — every configurable setting, its default value, and the expected data-payload shape — see the companion [**Container Card Reference**](https://github.com/otised-inc/OtisEd.Nimble/blob/master/docs/guides/container-card-reference.md).

### Data Visualization

| Card Type             | Name                | Description                                                                                                                                                                                                                                                                                                                      |
| --------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bar-chart`           | Bar Chart           | Vertical or horizontal bar chart with configurable series, color palette, legend, value labels, and suppression support.                                                                                                                                                                                                         |
| `line-chart`          | Line Chart          | Line/area chart for trends over time. Supports multiple series and the same axis/legend options as bar charts.                                                                                                                                                                                                                   |
| `combo-chart`         | Combo Chart         | Combines bar and line series on a single chart with dual-axis support.                                                                                                                                                                                                                                                           |
| `ring-chart`          | Ring Chart          | Doughnut-style ring chart for part-to-whole comparisons.                                                                                                                                                                                                                                                                         |
| `pie-chart`           | Pie Chart           | Classic pie chart with configurable color palette and legend.                                                                                                                                                                                                                                                                    |
| `sankey-chart`        | Sankey Chart        | Flow diagram showing weighted connections between named nodes (source → target). Configurable palette with per-node color overrides, link color modes (source / target / gradient / solid), node alignment and sizing, optional custom legend, and currency/percentage number formatting in tooltips.                            |
| `dials-chart`         | Dials Chart         | Circular gauge (speedometer) with color-coded ranges and a configurable value indicator needle.                                                                                                                                                                                                                                  |
| `data-grid`           | Data Grid           | Feature-rich tabular display powered by DevExtreme DataGrid. Supports sorting, filtering, paging, column configuration, Excel export, and an optional stored-procedure data source for large/dynamic datasets.                                                                                                                   |
| `kpi`                 | KPI Card            | Displays a single key metric with an optional trend indicator, previous-value comparison, and configurable number format, font sizes, and background colors.                                                                                                                                                                     |
| `map`                 | Map                 | Static geographic map using the Google Static Maps API. Configurable center point, zoom, map type, and marker pins.                                                                                                                                                                                                              |
| `powerbi`             | Power BI            | Embeds a Power BI report or paginated report (RDL) by Report ID and Workspace ID. Standard reports optionally expose the built-in filter panel, page navigation, bookmarks, and status bar. Paginated reports render with their own built-in controls; display settings are automatically skipped. Report type is auto-detected. |
| `diversity-chart`     | Diversity Chart     | Doughnut chart specialized for student diversity breakdowns.                                                                                                                                                                                                                                                                     |
| `diversity-table`     | Diversity Table     | Tabular companion to the Diversity Chart.                                                                                                                                                                                                                                                                                        |
| `performance`         | Performance         | Specialized performance metric display.                                                                                                                                                                                                                                                                                          |
| `performance-rating`  | Performance Rating  | Displays a rating scale alongside a performance score.                                                                                                                                                                                                                                                                           |
| `overall-performance` | Overall Performance | Aggregated performance summary card.                                                                                                                                                                                                                                                                                             |
| `legend-performance`  | Legend Performance  | Displays a performance legend.                                                                                                                                                                                                                                                                                                   |
| `population-count`    | Population Count    | Displays a student population count metric.                                                                                                                                                                                                                                                                                      |
| `filter`              | Filter Card         | Provides one or more dropdown filter controls that broadcast selection changes to other cards via the event bus. Supports cascading filters (parent-child dropdowns), a suppression toggle, and configurable titles. See [Event Bus](#event-bus-filter-and-publishersubscriber-cards).                                           |

### Content

| Card Type | Name       | Description                                                                                                                     |
| --------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `html`    | HTML Block | Renders arbitrary HTML content. Sanitization is on by default; scripts can be allowed explicitly. Supports optional PDF export. |

### Event Bus (debug / advanced)

| Card Type          | Name             | Description                                                                                                     |
| ------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------- |
| `event-publisher`  | Event Publisher  | Publishes any event type to the container's event bus. Intended for testing and debugging event-driven layouts. |
| `event-subscriber` | Event Subscriber | Displays a live log of all events received on the container's event bus. Intended for testing and debugging.    |

***

## Configuring Card Data Sources

Most data visualization cards display data that was loaded into the system externally (via the Container Card Data API or a background synchronization job). The card configuration controls **how** that data is presented; the actual data records are stored separately.

> For the admin experience of creating, editing, and deleting Container Card Data records — plus the context-matching rules and the public vs. suppressed data tiers — see the companion [**Container Card Data**](https://github.com/otised-inc/OtisEd.Nimble/blob/master/docs/guides/container-card-data.md) guide.

### Static card data

The most common pattern: data is stored as a JSON blob in `ContainerCardData` records, keyed by container card, organization unit, and academic term. When the container is viewed, the system:

1. Identifies the organization context from the URL (`?organization=YEAR:ORGCODE`).
2. Fetches the matching `ContainerCardData` record for each card (preferring an exact context match over the default/fallback record).
3. Merges the data JSON into the card's configuration before delivering it to the browser.

No card-level configuration is needed to enable this — it is automatic whenever matching data exists.

The merge also lets a Container Card Data record **override designer-configured properties** for its (term, organization) context. Any top-level key in the Data JSON whose name matches a property on the card — `title`, `description`, `chartColor`, etc. — replaces the designer value when the card renders for that context. This is how you make one card definition show different titles, colors, or other property values across districts, schools, or years without duplicating the card. See [Overriding Card Properties via Data JSON](https://github.com/otised-inc/OtisEd.Nimble/blob/master/docs/guides/container-card-data.md#overriding-card-properties-via-data-json) for the rules and examples.

### Stored procedure data source (Data Grid only)

For large, paginated, or dynamically filtered datasets, the Data Grid card can be configured to call a SQL Server stored procedure directly at query time.

In the Data Grid card's properties:

1. Enable **Use Stored Procedure**.
2. Enter the **Stored Procedure Name** (schema-qualified, e.g., `Report.MyGridProcedure`).

The stored procedure must accept these eight input parameters plus two output parameters in the exact order shown:

| Parameter             | Type                | Purpose                                        |
| --------------------- | ------------------- | ---------------------------------------------- |
| `@Skip`               | int                 | Pagination offset                              |
| `@Take`               | int                 | Page size                                      |
| `@SortJson`           | nvarchar            | Sort descriptor from the grid                  |
| `@FilterJson`         | nvarchar            | Grid-level filter from column headers          |
| `@CardFiltersJson`    | nvarchar            | Filters from Filter Cards (event bus)          |
| `@GlobalFiltersJson`  | nvarchar            | Page-level global filters                      |
| `@OrganizationUnitId` | uniqueidentifier    | Resolved org unit ID from org code             |
| `@AppTermId`          | int                 | Academic term year from org code               |
| `@TotalCount`         | int OUTPUT          | Total record count for paging                  |
| `@GeneratedSql`       | nvarchar MAX OUTPUT | Diagnostic SQL string (not returned to client) |

The stored procedure returns a single result set; column names become the grid's column headers.

### Scrollbar visibility (Data Grid only)

The Data Grid card exposes a **Show Scrollbar** property that controls when horizontal and vertical scrollbars appear inside the grid. This is helpful when the grid is wider than its container (many columns) or taller than its container (more rows than fit on a page) — users need a visual cue that additional data exists off-screen, especially on macOS where native scrollbars auto-hide.

| Mode                  | Behavior                                                                                                  |
| --------------------- | --------------------------------------------------------------------------------------------------------- |
| `onScroll`            | Scrollbar appears only while the user is actively scrolling, then fades out.                              |
| `onHover` *(default)* | Scrollbar appears when the user hovers over the grid or scrolls.                                          |
| `always`              | Scrollbar is permanently visible whenever there is content to scroll. Recommended for tall or wide grids. |
| `never`               | Scrollbar is hidden. Users can still scroll with mouse wheel, trackpad, or keyboard.                      |

The scrollbar only renders when content actually overflows — if all columns and rows fit within the card, no scrollbar is drawn regardless of this setting. Under the hood, the Data Grid uses DevExtreme's simulated scrolling so the setting behaves consistently across browsers and operating systems.

### Fit Grid to Content (Data Grid only)

By default the Data Grid stretches to fill 100% of its card width and the columns share that space proportionally. The **Fit Grid to Content** property changes this — the grid renders only as wide as its columns need, leaving any remaining card space blank to the right.

Use this when:

* A few-column grid sits in a wide card. Stretching makes columns look excessively spaced; fit-to-content keeps the grid compact and easier to scan.
* You want a small reference table inside a card alongside other content.

Behind the scenes this passes `columnWidth="auto"` to DevExtreme's DataGrid, which decreases the component's width when content is narrower than its container. Column widths defined in **Series Configuration** are still honored. If the total column width exceeds the card width, horizontal scrolling kicks in as usual.

### Filter source

Cards also have an optional **Filter Source** field. This is a reference to a Filter Card (by its Card ID) that drives which data slice is active. It is used by the viewer to pass filter state to stored-procedure-backed grids.

***

## Responsive Layout

Every card has independent layout settings for three visible breakpoints and one print breakpoint:

| Breakpoint | Label  | Grid width | Columns |
| ---------- | ------ | ---------- | ------- |
| `lg`       | Large  | 1100 px    | 12      |
| `md`       | Medium | 896 px     | 10      |
| `sm`       | Small  | 668 px     | 6       |
| `print`    | Print  | 794 px     | 10      |

### Switching breakpoints

Use the **breakpoint selector** in the designer toolbar to switch between Large, Medium, Small, and Print views. The canvas redraws to show how cards will appear at that size. Card positions and sizes are independent per breakpoint.

### Copying layouts between breakpoints

To avoid configuring every breakpoint from scratch, use the **Copy Layout** action (in the designer toolbar or properties panel). Select a source breakpoint and a target breakpoint; the designer scales card widths and positions proportionally to fit the target column count.

### Print layout

The print breakpoint (`794 px`, 10-column grid) determines how the container renders when the `?isPrint=true` URL parameter is set. If a card has no explicit print layout configured, it falls back to the medium layout, then the large layout.

### Default row height

The container's **Row Height** setting (default 30 px) multiplies by the card's `h` grid units to calculate its actual pixel height. For example, a card with `h = 6` and a row height of 30 is 180 px tall. Increase row height if cards with fixed-height content (maps, gauges) feel cramped; decrease it to pack more information into the visible area.

***

## Preview Mode vs. Design Mode

### Design Mode

The default mode when a container is opened in the Container Designer. Cards are selectable, draggable, and resizable. The right sidebar shows configuration panels. The event bus is active, but cards may show placeholder content if no live data has been loaded.

### Preview Mode

Toggle Preview Mode using the **Preview** button in the designer toolbar. The canvas becomes read-only (no dragging or resizing). Cards render their full interactive behavior — filters broadcast events, charts respond to filter changes, the suppression toggle (if configured) becomes clickable. Preview Mode is useful for verifying the layout and interactions before publishing.

### Runtime / Viewer

When an end user opens a container from a Report page or an embedded link, the Container Viewer loads the container in a fully rendered, non-editable state. Data is fetched from the backend, merged into card configurations, and the event bus is initialized. The user can interact with filter controls and suppression toggles but cannot move or resize cards.

***

## Viewing a Container at Runtime

The Container Viewer accepts a `containerId` (GUID) and an optional `organization` URL parameter:

```
/container-viewer?containerId=<guid>&organization=<orgcode>
```

Two additional routes serve specialized views of the same container:

| Route                                              | Purpose                                                     |
| -------------------------------------------------- | ----------------------------------------------------------- |
| `/container-expanded?containerId=<guid>`           | Full-screen expanded view (no surrounding navigation)       |
| `/container-print?containerId=<guid>&isPrint=true` | Print-optimized view that triggers the browser print dialog |

Both routes preserve all other URL parameters (organization, filters, etc.) passed from the originating page.

The `organization` parameter accepts two formats:

| Format         | Meaning                                                                         |
| -------------- | ------------------------------------------------------------------------------- |
| `YYYY`         | Academic term year only; no specific organization unit filtered                 |
| `YYYY:ORGCODE` | Year and organization code, resolved to an organization unit for data filtering |

If no `organization` parameter is provided, the container displays its default (unfiltered) data.

### Anonymous vs. authenticated access

The viewer determines the appropriate data tier based on authentication state:

* **Anonymous users** always receive the suppressed (public-safe) data tier and cannot see the suppression toggle.
* **Authenticated users** receive unsuppressed data by default (if data has been loaded) and may see a suppression toggle if the card is configured to show one.

***

## Event Bus: Filter and Publisher/Subscriber Cards

The event bus connects cards within the same container. Each container has its own isolated event bus instance.

### How filters work

A **Filter Card** renders one or more dropdown controls. When a user changes a selection, the Filter Card publishes a `filter.change` event containing the updated filter key/value pairs. Any card that subscribes to filter events (most data visualization cards do) responds by re-rendering with the new filter applied to its data.

Cascading filters are supported: a "City" dropdown can have `parentFilterKey` set to "State", so it shows only cities belonging to the selected state.

### Suppression toggle

The Filter Card optionally includes a **suppression toggle** (`showSuppressionToggle: true`). When the toggle is present and the user flips it, the viewer publishes a `property.change` event with `propertyKey: "suppressionValue"`. The Container Viewer listens for this event and reloads the container data using either the suppressed endpoint (anonymous data) or the unsuppressed endpoint (authenticated data), depending on the toggle state.

The suppression toggle is only visible if the current user has suppression permission. Users without suppression permission always see suppressed data regardless of toggle configuration.

### Event Publisher and Event Subscriber cards

These cards are diagnostic tools intended for design-time testing:

* **Event Publisher** provides buttons that fire any registered event type onto the bus so you can verify that subscriber cards respond correctly.
* **Event Subscriber** displays a live log of all events received on the bus, showing event type, source card, timestamp, and payload.

Both cards are in the **Event Bus** category of the Add Card palette and are intended for development and debugging, not for production dashboards.

### Event types

The event bus supports the following event types:

| Category   | Event Types                                                      |
| ---------- | ---------------------------------------------------------------- |
| Data       | `data.refresh`, `data.loaded`, `data.error`                      |
| Filters    | `filter.change`, `filter.clear`, `filter.apply`                  |
| Cards      | `card.selected`, `card.deselected`, `card.added`, `card.removed` |
| Layout     | `layout.change`, `breakpoint.change`                             |
| Properties | `property.change`, `property.validation.error`                   |
| Page       | `page.save`, `page.load`, `page.preview`                         |
| Charts     | `chart.zoom`, `chart.pan`                                        |
| Tables     | `table.sort`, `table.page.change`                                |
| Maps       | `map.zoom`, `map.center.change`                                  |
| Custom     | `custom`                                                         |

***

## Data Suppression

Data suppression is a mechanism for protecting small-count data that could identify individuals. The system maintains two data tiers per card:

> For the admin-facing view of the two tiers — editing the `Data` (public) and `Secured Data` (unsuppressed) JSON payloads on a record — see [The Two Data Tiers](https://github.com/otised-inc/OtisEd.Nimble/blob/master/docs/guides/container-card-data.md#the-two-data-tiers-data-vs-secured-data) in the Container Card Data guide.

| Field         | Who sees it                                     | Description                                               |
| ------------- | ----------------------------------------------- | --------------------------------------------------------- |
| `Data`        | Everyone (including anonymous users)            | The suppressed/public-safe version of the data            |
| `SecuredData` | Authenticated users with suppression permission | The unsuppressed version with actual small counts visible |

At runtime, the viewer checks the user's suppression permission and selects the appropriate data tier. If a card has a `SecuredData` record loaded and the user has permission, `SecuredData` is used; otherwise `Data` is used.

The `included` flag on a `ContainerCardData` record controls whether a card is rendered at all for a given context. If `included` is `false`, the card is omitted from the layout for that organization/term context.

The `suppressionValue` property in a card's configuration is set server-side based on which data tier was served. Cards that display a suppression indicator read this value. Cards that have a suppression toggle allow the user to switch tiers (for users with permission), triggering a reload.

***

## Expand and Print Actions

At runtime, each container can display **Expand** and **Print** action buttons in the card title area. These buttons give end users quick access to a full-screen view and a print-optimized view of the container.

### Expand button

The **Expand** button opens the container in a new browser tab at the `/container-expanded` route. The expanded view renders the container at full viewport width without surrounding navigation chrome, allowing users to see dashboards at maximum size. All existing URL parameters (organization context, filters, etc.) are preserved in the new tab.

### Print button

The **Print** button opens the container in a new browser tab at the `/container-print` route with the `isPrint=true` URL parameter. Once all cards have finished loading, the browser's print dialog opens automatically. The print view uses a dedicated layout optimized for paper output.

### Print layout rendering

When a container renders in print mode (`?isPrint=true`):

1. **Fixed width** — The container renders at 794 px (US Letter width at 96 DPI) regardless of the browser window size.
2. **Print breakpoint** — The print breakpoint layout (10-column grid) is used. If a card has no explicit print layout, it falls back to the medium layout, then the large layout.
3. **Flow-based layout** — Instead of the absolute-positioned grid used in normal viewing, print mode renders cards in a row-based flow layout. Cards at the same vertical position are grouped into rows, and each row uses `break-inside: avoid` to prevent page breaks from splitting a row.
4. **Landscape orientation** — The print stylesheet sets `@page { size: letter landscape; }`.
5. **Colors preserved** — The stylesheet enables `print-color-adjust: exact` so chart colors, backgrounds, and branding render correctly on paper.
6. **Interactive elements hidden** — Buttons, close icons, expand/print actions, and other interactive controls are hidden via CSS during printing.
7. **Automatic print trigger** — After all cards report they are ready (via `CARD_READY` event bus events), a short delay allows final rendering before `window.print()` is called automatically.

### Printing properties

All card types include a **Printing** property group in their configuration panel. The following properties control print behavior:

| Property                    | Key                  | Type    | Default                    | Description                                                                                                                                                                                                                                                                                                                                                       |
| --------------------------- | -------------------- | ------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Hide Card in Print**      | `printHideCard`      | Boolean | Off (see exceptions below) | When enabled, the entire card is excluded from the print layout.                                                                                                                                                                                                                                                                                                  |
| **Hide Filters in Print**   | `printHideFilters`   | Boolean | On                         | When enabled, inline filter controls within the card are hidden during printing, leaving only the visualization. Only present on card types that have filter controls.                                                                                                                                                                                            |
| **Disable Paging in Print** | `printDisablePaging` | Boolean | Off                        | Data Grid only. When enabled, paging is turned off during printing so all rows render on the page. Off by default for both local-data and stored-procedure grids — opt in only when the dataset is small enough that printing every row makes sense. For stored-procedure grids this still issues a single backend request to fetch all rows, so be conservative. |

### Which card types get which printing properties

| Card Type           | Hide Card in Print    | Hide Filters in Print |
| ------------------- | --------------------- | --------------------- |
| Bar Chart           | Yes (default: Off)    | Yes (default: On)     |
| Line Chart          | Yes (default: Off)    | Yes (default: On)     |
| Combo Chart         | Yes (default: Off)    | Yes (default: On)     |
| Ring Chart          | Yes (default: Off)    | Yes (default: On)     |
| Pie Chart           | Yes (default: Off)    | Yes (default: On)     |
| Dials Chart         | Yes (default: Off)    | Yes (default: On)     |
| Data Grid           | Yes (default: Off)    | Yes (default: On)     |
| KPI                 | Yes (default: Off)    | Yes (default: On)     |
| Map                 | Yes (default: Off)    | —                     |
| Power BI            | Yes (default: Off)    | —                     |
| HTML Block          | Yes (default: Off)    | —                     |
| Diversity Chart     | Yes (default: Off)    | —                     |
| Diversity Table     | Yes (default: Off)    | —                     |
| Performance Rating  | Yes (default: Off)    | —                     |
| Overall Performance | Yes (default: Off)    | —                     |
| Legend Performance  | Yes (default: Off)    | —                     |
| Population Count    | Yes (default: Off)    | —                     |
| **Filter Card**     | **Yes (default: On)** | —                     |
| Event Publisher     | Yes (default: Off)    | —                     |
| Event Subscriber    | Yes (default: Off)    | —                     |

The Filter Card is the only card type that defaults to hidden in print, since interactive filter dropdowns serve no purpose in a static printed output.

### Designing the print layout

To customize how the container looks when printed:

1. Open the container in Design Mode.
2. Switch to the **Print** breakpoint using the breakpoint selector in the toolbar.
3. Arrange and resize cards for the print layout. The print grid is 10 columns wide at 794 px with tighter margins (5 px) than screen breakpoints.
4. Use the **Copy Layout** action to copy from another breakpoint as a starting point, then fine-tune.
5. Set the **Hide in Print** property on any cards that should not appear in the printed output.
6. Save the container.

If no print layout is configured, the container falls back to the medium layout, then the large layout.

***

To create a variation of an existing container:

1. From the container list, click the **Clone** icon on the source container's row.
2. The system loads the full container details (all card configurations are included in the clone).
3. A dialog prompts for a new name (defaulting to "Copy of \[source name]"), an optional title, description, and row height.
4. Click **Clone** to create the new container.

The cloned container is created as a new, independent container. Changes to the clone do not affect the original. Card Data records are **not** cloned — the new cards will reference their own data once it is loaded.

***

## Permissions

| Permission                      | What it allows                                          |
| ------------------------------- | ------------------------------------------------------- |
| `Containers.Default`            | View the container list and open containers for reading |
| `Containers.Create`             | Create new containers                                   |
| `Containers.Edit`               | Modify existing containers and their cards              |
| `Containers.Delete`             | Delete containers                                       |
| `ReportGroupContainers.Default` | View container assignments within Report Groups         |
| `ReportGroupContainers.Create`  | Assign containers to Report Groups                      |
| `ReportGroupContainers.Edit`    | Change container assignments in Report Groups           |
| `ReportGroupContainers.Delete`  | Remove container assignments from Report Groups         |

Suppression permission (the ability to view unsuppressed data) is a separate privilege checked at runtime for each viewer request.

***

## Troubleshooting

**Container does not appear in the list.** Check the **Show inactive containers** checkbox. If the container is active and still missing, verify that you are logged in to the correct tenant.

**A card shows no data.** The card may not have any `ContainerCardData` loaded for the current organization/term context. Confirm that data has been synchronized for the container card and that the `organization` URL parameter matches an existing context. Check the card's **Refresh Status** field in the Container Card Data admin view for any error messages from the last data load.

**Layout looks wrong at a particular screen size.** Open the container in Design Mode and switch to the affected breakpoint using the breakpoint selector. Adjust card positions and sizes for that breakpoint and save. If no layout has been configured for the breakpoint, the container falls back to the next larger breakpoint.

**The suppression toggle is not visible.** The toggle is only rendered if the card's `showSuppressionToggle` property is enabled **and** the current user has suppression permission. Confirm the card property is enabled in Design Mode. If the user should have permission but does not see the toggle, contact your system administrator to verify their role.

**A stored-procedure-backed Data Grid is empty or shows an error.** Verify the stored procedure name is spelled correctly (schema-qualified, e.g., `Report.MyProc`). The stored procedure must accept all ten parameters in the exact order described in [Stored Procedure Data Source](#stored-procedure-data-source-data-grid-only). The database user must have EXECUTE permission on the stored procedure.

**Cloning fails with "Failed to load container for cloning".** This typically means the source container could not be retrieved from the backend. Refresh the container list and try again. If the problem persists, check that you have `Containers.Default` and `Containers.Create` permissions.

**The URL loses the container ID after navigating away.** The designer maintains container selection in the URL query parameter `containerId`. Using browser navigation (back/forward) is supported and will restore the previously selected container. If the parameter is missing after a full page reload, the container list is shown and you will need to re-select the container.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nimble.docs.otised.com/guides/container-designer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
