diff --git a/docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx b/docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
index f308980e3b940..82efef0a63912 100644
--- a/docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
+++ b/docs-mintlify/docs/explore-analyze/dashboards/widgets/controls.mdx
@@ -36,7 +36,7 @@ You can set a default value that's applied when the dashboard loads. Defaults ar
There are two ways to set a default:
- **Static default** — pick a value (or values) directly in the filter. Every viewer sees the same default.
-- **User attribute default** — resolve the default from the viewer's [user attribute][ref-user-attributes] at load time, so each viewer sees their own personalized default. [Parent controls](#default-option) support this too.
+- **User attribute default** — resolve the default from the viewer's [user attribute][ref-user-attributes] at load time, so each viewer sees their own personalized default. [Parent controls](#parent-user-attribute-default) support this too.
Static defaults are configured by interacting with the filter in the dashboard builder — the value you select is saved on the widget and applied to every viewer when the dashboard loads.
@@ -113,7 +113,7 @@ Add the child controls to the dashboard *before* the parent control. The **Child
On the **Options** tab, type a label and click **Add** for each entry you want in the dropdown. Options appear as chips — remove one with its close button. A parent control can hold up to 50 options.
-Renaming an option later doesn't disturb the values you've mapped to it, so you can reword a label without redoing the mapping.
+Renaming an option later doesn't disturb the values you've mapped to it, so you can reword a label without redoing the mapping — but if the control has a [user attribute default](#parent-user-attribute-default), that match is by label, so rename the attribute's values with it.
### Children
@@ -147,13 +147,13 @@ Click the indicator to jump straight to the **Children** tab of the parent that
### Default option
-The option a parent control opens on is the one you last picked **in the control itself on the dashboard**, not a field in its settings — the same way a filter's static default and a time granularity switcher's default are set. Pick an option in the dashboard builder and it's saved on the widget and applied to every viewer when the dashboard loads.
+A parent control's default is set the same way a filter's static default is — by interacting with the control in the dashboard builder. The option you select is saved on the widget and applied to every viewer when the dashboard loads; there's no static default field in the parent's settings.
Picking in the builder also applies that option's values to the children, so their saved defaults line up with the parent's and a published dashboard opens in a consistent state.
If you never pick an option, the parent opens with nothing selected and the children use their own defaults. Deleting the option that was serving as the default clears it, and the parent goes back to opening on nothing.
-#### User attribute default
+#### User attribute default {#parent-user-attribute-default}
The default above is one arrangement for everyone. To give each viewer their own, turn on **User attribute default** in the parent control's settings and pick a [user attribute][ref-user-attributes]. When the dashboard loads, Cube reads that attribute for the current viewer and opens the control on the option it names — and drives the children with it, exactly as if the viewer had picked that option themselves.
@@ -163,17 +163,21 @@ To configure it:
- In the dashboard builder, click **Configure Parent** on the control, or open its settings menu.
+ In the dashboard builder, click **Configure Parent** on the control.
- Scroll to the **User attribute default** switch and turn it on.
+ Below the **Options** and **Children** tabs — next to **Visibility** — turn on the **User attribute default** switch.
Select the [user attribute][ref-user-attributes] to resolve. Only attributes defined in your account appear in the picker.
-The attribute value is matched against the **option labels**, ignoring case and surrounding spaces — an attribute reading `quarter` selects the option labelled `Quarter`. Give the options the labels your attribute already uses, or adjust the attribute values to match; renaming an option later doesn't disturb the child mappings, so labels are safe to align after the fact.
+The attribute value is matched against the **option labels**, ignoring case and surrounding spaces — an attribute reading `quarter` selects the option labelled `Quarter`. Give the options the labels your attribute already uses, or adjust the attribute values to match.
+
+
+Renaming an option leaves its child mappings intact, but the attribute match is by label — so a rename that moves a label away from the values your attribute holds silently stops it resolving, with no error. The control falls back to the option you picked as the default. Rename labels and attribute values together.
+
| Attribute type | How it's applied |
|---|---|
@@ -186,14 +190,11 @@ If the value matches no option — or is empty, `null`, or unresolvable — the
The attribute is resolved for the viewer, not baked into the dashboard. Editing the attribute's value changes what that viewer opens on the next time the dashboard loads; it never rewrites the published dashboard, so the default you picked in the builder stays intact for everyone else.
-Viewers can still switch to another option unless the control's [visibility](#visibility) is set to **Disabled**, and their own pick outranks the attribute for the rest of the session. Values passed [in the URL](#sharing-the-current-selection) outrank both, so a shared link opens on the values it names rather than on the recipient's attribute.
+Viewers can still switch to another option unless the control's [visibility](#visibility) is set to **Disabled**, and their own pick outranks the attribute for the rest of the session. Values passed [in the URL](#sharing-the-current-selection) outrank both — but only what the sharer actually picked travels: a parent control has no parameter of its own, and an untouched, attribute-resolved one puts nothing in the link, so the recipient still opens on their own attribute. When the sharer did pick an option, the link carries that option's *children's* values and the recipient opens on those.
## Sharing the current selection
-On a published dashboard, the values a viewer picks in the controls are reflected
-in the URL, so the view they are looking at is bookmarkable and shareable. Copy
-the address bar, send it on, and the recipient opens the dashboard with the same
-filters and granularities applied.
+On a published dashboard, the values a viewer picks in the controls are reflected in the URL, so the view they are looking at is bookmarkable and shareable. Copy the address bar, send it on, and the recipient opens the dashboard with the same filters and granularities applied.
Each control type has its own parameter:
@@ -202,36 +203,18 @@ Each control type has its own parameter:
| [Filter](#filter) | `f_.=` | `f_orders.status={"value":"shipped"}` |
| [Time granularity switcher](#time-granularity-switcher) | `tg_.=` | `tg_orders.created_at=week` |
-The semantic view and dimension are the **internal names** configured on the
-control — not the display titles you see in the picker. A view shown as `Orders`
-is usually `orders` in the parameter. Granularities are lowercase: `day`, `week`,
-`month`, `quarter`, `year`.
+The semantic view and dimension are the **internal names** configured on the control — not the display titles you see in the picker. A view shown as `Orders` is usually `orders` in the parameter. Granularities are lowercase and must be one of the switcher's [allowed granularities](#allowed-granularities) — `day`, `week`, `month`, `quarter`, `year`, plus `second`, `minute`, and `hour` for time dimensions that expose them.
-You can also write these parameters by hand to open a dashboard in a particular
-state — see [Pre-set dashboard filters via URL][ref-embed-url-filters] for the
-embedded case, which uses the same format.
+You can also write these parameters by hand to open a dashboard in a particular state — see [Pre-set dashboard filters and granularities via URL][ref-embed-url-filters] for the embedded case, which uses the same format.
What does and doesn't travel in the link:
-- **Only what the viewer chose.** Values that came from the control's own
- configuration — a static default, a [default granularity](#default-granularity)
- — are not written into the URL. Every viewer already gets those from the
- dashboard itself, and leaving them out means a link stays correct after the
- dashboard's defaults change.
-- **Never a personalized default.** A value resolved from a
- [user attribute](#user-attribute-default) stays out of the link — whether it
- seeded a filter directly or reached one through a [parent control](#parent)
- opening on the viewer's own option. Sharing a dashboard never pins your
- attribute value onto the recipient; they see it through their own attributes.
-- **Filters and granularities together.** Picking both puts both in the link,
- including when a [parent control](#parent) sets several children at once.
-- **Published dashboards only.** In the dashboard builder the URL is left to
- the editing session, so editing a control there doesn't rewrite it.
-
-When a dashboard opens with these parameters, they are applied on top of whatever
-defaults the controls carry. A parameter is ignored when nothing on the dashboard
-can honor it — there is no matching control for that dimension, or the requested
-granularity isn't in the switcher's [allowed granularities](#allowed-granularities).
+- **Only what the viewer chose.** Values that came from the control's own configuration — a static default, a [default granularity](#default-granularity) — are not written into the URL. Every viewer already gets those from the dashboard itself, and leaving them out means a link stays correct after the dashboard's defaults change.
+- **Never a personalized default.** A value resolved from a [user attribute](#user-attribute-default) stays out of the link — whether it seeded a filter directly or reached one through a [parent control](#parent) opening on the viewer's own option. Sharing a dashboard never pins your attribute value onto the recipient; they see it through their own attributes.
+- **Filters and granularities together.** Picking both puts both in the link, including when a [parent control](#parent) sets several children at once. A parent control isn't serialized itself — the link carries the values its children ended up with, so the recipient sees the same data while the parent dropdown opens on whatever default it resolves for them, which may not be the option the sharer picked.
+- **Written out on published dashboards only.** Reading these parameters works anywhere, including [embedded][ref-embed-url-filters] dashboards; it's the writing that is published-only. In the dashboard builder the URL is left to the editing session, so changing a control there doesn't rewrite it.
+
+When a dashboard opens with these parameters, they are applied on top of whatever defaults the controls carry. A parameter is ignored when nothing on the dashboard can honor it — there is no matching control for that dimension, or the requested granularity isn't in the switcher's [allowed granularities](#allowed-granularities).
## Visibility
diff --git a/docs-mintlify/docs/explore-analyze/notifications.mdx b/docs-mintlify/docs/explore-analyze/notifications.mdx
index 56e2c3f8e0922..63ff9bba5ca1c 100644
--- a/docs-mintlify/docs/explore-analyze/notifications.mdx
+++ b/docs-mintlify/docs/explore-analyze/notifications.mdx
@@ -14,6 +14,8 @@ on the workbook to set up notifications.
Notifications let you send email or Slack messages with a screenshot of a
dashboard after each [scheduled refresh][ref-scheduled-refreshes]. This is useful
for distributing regular updates to stakeholders without requiring them to log in.
+They can optionally carry a short [AI-generated summary](#ai-summary) of what
+changed since the previous notification.
## Creating a notification
@@ -51,7 +53,51 @@ Select the format using the **Attach screenshot as** option. The same
formats are available for ad-hoc [downloads from the dashboard
header][ref-download].
-[ref-download]: /docs/explore-analyze/dashboards#download-as-png-or-pdf
+### AI summary
+
+Turn on **Include AI summary** to add a short "what changed" note to the body of
+the email or Slack message, above the screenshot. It is off by default.
+
+The note is written by the configured [AI agent][ref-agents] and is deliberately
+short — an opening line naming the most important change, then two to four
+bullets, each with a real number and its movement. It is meant to be read in a
+few seconds to decide whether to open the dashboard at all:
+
+```text
+WHAT CHANGED
+Order growth accelerated this week, driven mainly by a surge in returns
+outpacing overall gains.
+- Weekly orders: 416 last full week, up 20% from 346 the week before.
+- Returned orders: 42 last week, up 40% week over week (from 30).
+- Completed orders: 202 last week, up 13% week over week (from 179).
+```
+
+**What it compares against.** Where possible the note describes what changed
+since the *previous notification* for that recipient, rather than what changed
+inside the data — so a daily notification does not repeat the same sentence
+every morning. On the first send, or when there is no earlier note to compare
+with, it falls back to comparing recent periods (week over week, month over
+month) and says so rather than inventing a comparison.
+
+
+
+Each recipient's note is generated under **their own data access**, so it only
+describes rows that recipient is allowed to see. That also means it costs one
+agent run per recipient per send, which is why the option is off by default.
+
+
+
+If the summary can't be generated — the agent is unavailable, or the run takes
+too long — the notification is still delivered, without the note.
+
+
+
+This is not the same as the [AI summary widget][ref-ai-widget], which lives on
+the dashboard, takes a prompt you write, and is cached for everyone who views
+it. The notification summary uses a fixed brief, is generated per recipient, and
+is never shown on the dashboard.
+
+
### Removing a notification
@@ -83,8 +129,9 @@ Under the **Recipients** heading there are two separate controls:
A group is expanded to its current members each time the notification is sent,
so adding or removing members takes effect on the next run without editing the
-schedule. The number beside a group's name is how many members it can currently
-email; a member with no email address is not listed and is never counted.
+schedule. The number beside a group's name counts the members it can currently
+email, so a group can show fewer than its full membership — anyone without an
+email address is left out of both the count and the list.
A recipient who is selected individually and also belongs to a selected group is
emailed only once.
@@ -128,8 +175,11 @@ Before you can send Slack notifications, connect your Slack workspace:
This is a one-time setup. Once connected, you can select any channel your Slack
workspace has access to.
+[ref-download]: /docs/explore-analyze/dashboards#download-as-png-or-pdf
[ref-roles]: /admin/users-and-permissions/roles-and-permissions
[ref-scheduled-refreshes]: /docs/explore-analyze/scheduled-refreshes
[ref-duplicate]: /docs/explore-analyze/scheduled-refreshes#duplicating-a-schedule
[ref-user-groups]: /admin/users-and-permissions/user-groups
[ref-subscribe]: /docs/explore-analyze/scheduled-refreshes#subscribing-to-notifications
+[ref-agents]: /admin/ai
+[ref-ai-widget]: /docs/explore-analyze/dashboards/widgets/ai-summary
diff --git a/docs-mintlify/docs/explore-analyze/scheduled-refreshes.mdx b/docs-mintlify/docs/explore-analyze/scheduled-refreshes.mdx
index 2687f878c6ecd..d19acb8c4229c 100644
--- a/docs-mintlify/docs/explore-analyze/scheduled-refreshes.mdx
+++ b/docs-mintlify/docs/explore-analyze/scheduled-refreshes.mdx
@@ -50,6 +50,8 @@ with the following configuration options.
### Schedule {#frequency}
+Pick how often the refresh runs with the **Schedule** select:
+
| Option | Description |
| --- | --- |
| Hourly | Runs every hour at the specified minute |
@@ -102,11 +104,11 @@ The sidebar lists all existing schedules with the following information:
To create a new schedule based on an existing one — for example, to send the
same dashboard to another Slack channel or a different set of recipients without
-re-entering the frequency, timezone, and notification settings — you can
+re-entering the **Schedule**, timezone, and notification settings — you can
duplicate it. There are two ways:
- **From the sidebar** — click the duplicate (copy) icon on a schedule card. The
- form dialog opens pre-filled with that schedule's frequency, timezone, and
+ form dialog opens pre-filled with its **Schedule**, timezone, and
notification configuration. Adjust anything you need, then click **Save** to
create the new schedule.
- **From the edit dialog** — while editing a schedule, click **Save as copy** in
@@ -131,15 +133,15 @@ group keeps notifying everyone else but stops emailing you. Subscribing reverses
both: it clears those exceptions and adds you back as a recipient in your own
right. The change takes effect on the next run.
-
+
Unsubscribing affects only this schedule. It does not remove you from the user
group, and it does not change any other schedule that group receives.
-
+
-The toggle appears only for schedules that email individual recipients — those
-with notifications enabled and the email delivery channel. A schedule delivers to
+The toggle appears only for schedules that send email — those with
+notifications enabled and the email delivery channel. A schedule delivers to
either individual inboxes or a Slack channel, not both, so a schedule that posts
to Slack (or that has notifications turned off) has nothing to subscribe to. If an
editor switches a schedule to Slack, its individual subscriptions are cancelled
@@ -162,10 +164,13 @@ When a scheduled refresh runs, it progresses through these phases:
2. Fetching credentials
3. Refreshing dashboard
4. Generating screenshot (if notifications are configured)
-5. Sending notifications (if notifications are configured)
+5. Generating AI summary (if the notification has [AI summary][ref-ai-summary]
+ turned on)
+6. Sending notifications (if notifications are configured)
The sidebar shows real-time status updates during execution.
+[ref-ai-summary]: /docs/explore-analyze/notifications#ai-summary
[ref-roles]: /admin/users-and-permissions/roles-and-permissions
[ref-notifications]: /docs/explore-analyze/notifications
-[ref-user-groups]: /admin/users-and-permissions/user-groups
\ No newline at end of file
+[ref-user-groups]: /admin/users-and-permissions/user-groups
diff --git a/docs-mintlify/embedding/iframe/dashboards.mdx b/docs-mintlify/embedding/iframe/dashboards.mdx
index 9d529671cecbb..8cdaccff23ccd 100644
--- a/docs-mintlify/embedding/iframe/dashboards.mdx
+++ b/docs-mintlify/embedding/iframe/dashboards.mdx
@@ -71,8 +71,11 @@ URL parameters:
The `` and `` must match the internal names (not
display titles) of the semantic view and dimension configured on the widget. For
-filters, an omitted filter type defaults to `equals`; granularities are lowercase
-(`day`, `week`, `month`, `quarter`, `year`).
+filters, an omitted filter type defaults to `equals`. Granularities are lowercase
+and must be one of the switcher's [allowed
+granularities](/docs/explore-analyze/dashboards/widgets/controls#allowed-granularities) —
+`day`, `week`, `month`, `quarter`, `year`, plus `second`, `minute`, and `hour`
+for time dimensions that expose them.
Example:
@@ -80,14 +83,20 @@ Example:
https://your-tenant.cubecloud.dev/embed/dashboard/YOUR_DASHBOARD_PUBLIC_ID?session=YOUR_SESSION_ID&f_orders_transactions.users_country={"value":"USA"}&tg_orders_transactions.created_at=week
```
+The filter's JSON value is shown unencoded for readability. Percent-encode it
+before the URL goes anywhere real — pasted as-is into the `src="…"` of the iframe
+snippet above, its raw `"` closes the attribute and truncates the URL.
+
This works on both regular and published (embedded) dashboards. A parameter is
applied only if a matching control for that dimension already exists on the
dashboard, and a granularity outside the switcher's allowed list is ignored.
-The reverse direction works too: when a viewer changes a control, the new value
-is written back into the dashboard's own URL, so the state a link carries and the
-state a viewer reaches by clicking are the same format. See [Controls → Sharing the
-current selection](/docs/explore-analyze/dashboards/widgets/controls#sharing-the-current-selection).
+The reverse direction works on published dashboards: when a viewer changes a
+control there, the new value is written back into the dashboard's own URL, so the
+state a link carries and the state a viewer reaches by clicking are the same
+format. Reading the parameters works anywhere; it's the writing that is
+published-only. See [Controls → Sharing the current
+selection](/docs/explore-analyze/dashboards/widgets/controls#sharing-the-current-selection).
## Allow chart export {#allow-csv-export}