docs
/
Courses — Appmint

Appmint Data Visualization: Queries, Charts and Custom Dashboards

Watch on YouTube ↗

Video chapters
  1. 0:00 Welcome
  2. 0:14 How Dashboard Builder works
  3. 0:37 Part 1 · Your first query: explained
  4. 0:52 Part 1 · Your first query — Data Studio, New Query and a pipeline
  5. 1:40 Part 2 · Charts: explained
  6. 1:54 Part 2 · Charts — Field mapping, chart types, views, save and duplicate
  7. 2:39 Part 3 · Trends: explained
  8. 2:53 Part 3 · Trends — Revenue by month, split and stacked
  9. 3:28 Part 4 · The dashboard: explained
  10. 3:41 Part 4 · The dashboard — Wholesale overview: three cards
  11. 4:09 Part 5 · Date ranges and sharing: explained
  12. 4:23 Part 5 · Date ranges and sharing — Last month, the viewer role and Sam's view
  13. 5:09 Wrap-up

Written guide

Written course script · Core query → chart → saved dashboard verified locally · Advanced branches marked below

This is the Data Visualization / Dashboard Builder course. It is separate from Analytic Center and the customer My Account portal. A saved internal dashboard is not automatically a public share or a customer portal.

Overview

Why this matters

Appmint Data Visualization lets you ask a question of your collections, inspect the answer and turn it into a reusable chart. We'll build a query, map its fields and place the saved result in a dashboard. We'll also cover multiple series, alternative chart types, the AI helper and the checks that keep an attractive chart from telling the wrong story.

Conceptual relationship between a filtered Task query, numeric result and a saved dashboard

Illustration: the one-task result belongs to a deliberately filtered practice query, not a count of the entire organization. The real screenshots below separately verify the application result.

Prepare your practice record

Use your own authorized organization and a disposable Task. The Schedule course creates the record used in these screenshots and changes its status to pending. If you have not followed that course, open Data Explorer, select Task, choose Add, enter a unique Name such as my-dashboard-practice, a readable Title and status new, then Save. Do not select a workflow or customer messaging for this exercise. Reopen the record and check its saved Name and status. Your bar will correctly show new instead of our pending until that record changes.

The recorded example uses Name cedar-schedule-check-20261002. Replace that literal in both queries below with your exact saved Name. Names from this lesson do not create records in your organization. This deliberately small exercise proves the complete connection before you build wider business reporting.

1. Find saved queries and dashboards

Open Dashboard Builder in the Appmint menu. The current page calls itself Data Studio. All, Dashboards and Queries distinguish a saved layout from its reusable query/chart items. An empty home is normal before you save either.

Data Studio home with All, Dashboards, Queries and New Query controls

Start here: choose New Query to define the data. New Dashboard creates the layout that will contain a saved query later.

Why this matters

A query defines the question and its chart. A dashboard arranges saved queries. We'll save both, so the next visit opens something reusable.

Choose New Query. A fresh query may initially be titled New Table; that does not restrict you to a table. Keep the collection selector, editor and results together while you work.

2. Select Task and check the source record

Choose Task in the collection selector. Select the entire existing editor text and paste this JSON array, replacing the Name as described above:

[
  { "$match": { "name": "cedar-schedule-check-20261002" } },
  { "$limit": 3 }
]

Choose Run, wait for the request to finish, and inspect the returned row. Scroll the result horizontally when fields extend beyond the panel. In the recorded organization this returns exactly the Task already verified in Schedule.

Task collection selected with a limited query returning the controlled source record

The result row confirms a matching saved record. This raw table is wider than the visible panel; do not infer every business field from the cropped first columns.

No row means you should check the selected organization, collection and exact Name. Do not remove the match and accidentally report on unrelated records. The editor requires valid JSON array syntax, not a shell command or a single stage object. A request error is different from a successful empty result.

3. Count matching tasks by saved status

Replace the whole pipeline with:

[
  { "$match": { "name": "cedar-schedule-check-20261002" } },
  { "$group": { "_id": "$data.status", "tasks": { "$sum": 1 } } },
  { "$project": { "_id": 0, "status": "$_id", "tasks": 1 } },
  { "$sort": { "status": 1 } }
]

Run again. The recorded result has two fields: tasks: 1 and status: pending. Your own practice Task can have a different status; the count should remain one when your Name is unique. If multiple records share that Name, narrow the match to your actual record identifier before treating the total as a single-record check.

Why this matters

The match selects the record. Group counts records with the same saved status. Project gives the chart a clear status label and a numeric task count. We'll verify that row before interpreting the picture.

A missing status generally points to the wrong field path or a source record without a status. Inspect the saved record first. This observed Task schema stores the business status under data.status; a custom collection may use different fields.

4. Map, save and reopen the chart query

Choose Bar. Under Field Mapping, set Category (X-Axis) to status, Values (Y-Axis) to tasks, and leave Split by as None. Wait for the bar to render, then compare its height with the result row.

One pending task returned beside its bar chart and exact status/tasks field mapping

The table returns pending with tasks=1; the bar reaches 1. Category is the label, Values supplies its height. No unrelated sample chart is used.

Use the display buttons for Split view, Results only or Chart only when you need more room. Auto-detect examines the first row; a numeric-looking string is not necessarily a number. Inspect the actual result types and mapping if a measure is absent.

Enter Course tasks by status in the query-title field and choose Save. Return to Data Studio, open Queries, and select the saved title. Confirm the Task collection, pipeline and mapping survived. Choose Run again to refill the query editor's results after reopening; an initially empty preview does not mean the saved query was erased. The chart screenshot above was captured after this save/reopen/run check.

Duplicate prepares an unsaved query copy. Rename and Save the copy before relying on it as another reusable item.

5. Advanced: add multiple values or split a metric into series

The following extension is documented, not part of the single-Task live proof. Prepare a separate collection of request records with saved data.service and data.status fields before following it. Do not run a service-based pipeline against the Task fixture and expect service results.

Why this matters

Multiple value fields show several measures for each category. Split by shows one measure broken out by another field. Those are different data shapes.

Duplicate the query and group by both service and status, returning service, status and numeric requests. Run it, map service as category, requests as value and status under Split by (optional). Show the resulting series and compare each category/status pair with the table.

The current pivot uses the first matching row for each category/series pair. Therefore aggregate duplicate pairs in the query first; do not assume the chart sums duplicate rows automatically. Missing pairs display zero in this mapping path.

For the multiple-value alternative, return two meaningful numeric measures and choose Add value field. Explain their units before comparing them. Stack series appears for eligible Bar, Line and Area mappings; only stack values whose sum has meaning. Compare stacked totals with the results table and turn stacking off again to show the difference.

6. Select chart types according to the actual implementation

Demonstrate the alternatives with appropriate saved query copies, rather than cycling through all icons over one unsuitable dataset.

ChartDemonstration and mappingCurrent boundary
BarCounts by serviceCategory and numeric values
Line / AreaOrdered periods with a numeric measureSort periods in the query; Area uses a line with fill
Pie / DoughnutService name and request countUses the first value field; confirm parts belong to the same total
ScatterInspect the actual mapped category/value pointsCurrent shared axis path is category-based; do not claim a general numeric X/Y correlation editor
RadarComparable numeric measures for named categoriesCurrent renderer uses up to the first five rows and auto-derived maxima
GaugeA deliberate single result/valueReads the first row's first mapped value; do not feed many rows and call it their total
FunnelNamed stages and numeric valuesThe query must establish stage meaning; a funnel graphic does not infer conversion paths
HeatmapCategory, split-by dimension and numeric valueInspect both axes and the color scale against returned rows
Treemap / SunburstName and valueCurrent Sunburst data is flat with empty children, not an inferred deep hierarchy
Box PlotExplicit precomputed five-number summariesCurrent renderer sorts selected values and chooses positions; it does not calculate robust sample quartiles for arbitrary observations
SankeyCategory as source, Split by as target, first value as flowBoth endpoint fields and a numeric value are needed; inspect each source→target link
MapRegistered geographic definition plus suitable configurationCurrent default displays a bar fallback with a map-registration note; it is not a rendered geographic map

Why this matters

Choose the shape that explains the data you actually have. A new chart type doesn't add missing dimensions or calculate an analysis the query never produced.

Show each actual limitation alongside its control/result briefly. Advanced custom chart overrides and geographic registration need their own verified configuration; keep that branch pending rather than announcing a working map from the selector alone.

7. Create the dashboard and place saved items

Choose New Dashboard. It opens in Editing. In the right Queries sidebar, find Course tasks by status, then drag that saved item onto Empty Dashboard. Wait for the card's data and chart to finish loading.

Saved query dragged into a new dashboard with its table and rendered bar

One section now contains the same pending=1 result. The current card renders both the table and chart; do not promise a chart-only card from the sidebar's Chart label.

Choose the top Save button. On the first save, Save Dashboard opens for the record details. Enter Name course-task-status-dashboard, Title Course task status dashboard, and a useful Description such as Internal course fixture: the saved Task status query. Choose another unique Name if that one is already yours. Keep the generated Sections/card content; do not remove it while filling in the record's identity. Choose Save inside this form.

Save Dashboard form with the dashboard name, title, description and preserved Sections

Name identifies the saved layout; Title is its readable heading. The generated section carries the query reference. Saving only the query earlier did not save this dashboard.

Leave and reopen the dashboard from Data Studio → Dashboards, or reload its saved address within your authorized account. It should reopen in Viewing with the same title, card, row and bar.

Saved dashboard reopened in Viewing with one pending task and its bar

Persistence check: this is the reopened saved dashboard, not the unsaved editor. Both the underlying row and the rendered chart show pending=1.

For more questions, create and save another query and add it as a separate card. The current card loader reads the first item reference; putting several references into one card does not render several independent queries. Existing legacy query/table/chart configurations follow other loading paths and need separate inspection.

Current limitation: the card has a Config gear, but clicking it in this rehearsal did not open a configuration form. Do not depend on that step to finish the basic dashboard, and do not repeatedly click expecting a save. Title/description or presentation settings through that gear remain unverified. The saved core dashboard above works without it.

8. View, duplicate and refresh the dashboard

Switch to Viewing and confirm the intended arrangement without the editing controls. Reopen Editing only when changing the layout. Use Duplicate to prepare a separate dashboard; name and save the copy, then reopen the original to verify it was retained.

Two copy controls have different save behavior: The editor’s Duplicate creates a new unsaved dashboard and switches to Editing; its notice says to save to persist. Name the copy and choose Save before leaving. Clone on a saved sidebar item saves its copy immediately and refreshes the list. Do not click both unless you want two copies. A duplicated dashboard regenerates its section/card identifiers but still references its saved query items: copying the layout does not duplicate or isolate those query definitions. If you intend a different query, duplicate and save the query separately, then place that saved item in the copied dashboard. These distinctions are current-source verified; copy/readback remains part of the pending live extension.

Change one controlled source record through its proper module. On the dashboard use the affected card's Refresh and compare its revised value with the query table and source record. The card has explicit loading/error states; a failed request is not a zero metric. Verify chart rendering in the dashboard itself, since a correct query-editor preview does not prove the card's separate rendering path is correct.

Why this matters

This value changed because the source record changed. Refreshing the card reruns its data path; saving the layout alone doesn't prove the metric is current.

9. Use the scoped AI helper and inspect its changes

With the saved query open, ask the Data Visualization AI helper: Keep this collection. Group requests by their saved status and show counts as a bar chart. Keep the existing query as a separate saved item.

Before submitting, explain that the helper receives the active query/dashboard context and a small result preview, not an assumed complete dataset. Show its working state and resulting proposed/applied changes. Inspect collection, pipeline, field mapping and the returned rows. Save explicitly where required and reopen the intended item.

Why this matters

The helper can work in the context of this editor. We'll still inspect the query it produced and compare the chart with the results, especially if it changes the collection or grouping.

A live editor patch is not automatically a database save. Check whether the helper actually used a persistence action and verify the stored record. If it replaces the wrong item or uses an invalid field, stop that operation, restore the intended saved item and correct the prompt/context. Do not narrate an AI promise as an observed saved result.

10. Verify access and diagnose incorrect totals

Open the saved dashboard as the intended staff account. Inspect whether its underlying collection and query are authorized for that identity. A link copied from the administrator is not a public share grant. Do not use this internal dashboard as evidence that the customer My Account portal is configured.

For an incorrect total, follow the chain: source record → query filter/group → result row → field mapping → chart/card. For missing series, check duplicate category/series pairs and the first-row field shape. For a blank card, inspect its saved item reference and data response. For a stale number, use the card's refresh and reopen the saved query before changing layout settings.

Why this matters

You can now build a reusable question, show its result clearly and bring it into a dashboard. Keep the query and chart connected: every visible value should lead back to the authorized records that produced it.

Limitations and checks

Current code inspected under components/data-viz: home-view.tsx, workspace/query-editor.tsx, workspace/field-mapper.tsx, workspace/chart-type-picker.tsx, workspace/chart-preview.tsx, workspace/index.tsx, workspace/editor.tsx, layout/layout-card.tsx, data-viz-store.ts, data-viz-ai-bar.tsx.

Live proof completed on the local application: matching Task aggregation; grouping by data.status; numeric bar mapping; saved query reopened and rerun; saved dashboard reloaded in Viewing with the same table and bar. Six real screenshots are embedded at their corresponding actions. No external publication or AI request was made.

Remaining live proof: multi-series and alternative chart fixtures, date-range substitution, scoped AI changes and persistence, ordinary-role authorization, source-update refresh, duplication, layout/Config controls. The Config gear produced no visible form in this rehearsal. Geographic registration/custom overrides remain an advanced verification gap. These pending branches do not invalidate the demonstrated core result and must not be presented as tested successes. See the chapter evidence matrix.

BusinessMade Data Visualization: Queries, Charts and Custom Dashboards — supporting guide

BusinessMade entry: Tools → Data viz (/data-viz).

BusinessMade Data viz opens the shared query/chart editor. This is separate from BusinessMade Insights and its built-in metrics. Use an authorized training collection; do not assume the branch selector injects a location filter into a custom aggregation.

Scope: This BusinessMade route uses the shared component whose complete procedures follow. Use the BusinessMade menu and organization throughout. Shared references are implementation evidence, not instructions to switch products. These written steps have not been replayed as a new BusinessMade live walkthrough.

Written course script · documented draft · Current runtime rehearsal pending

This is the Data Visualization / Dashboard Builder course. It is separate from Analytic Center and the customer My Account portal. A saved internal dashboard is not automatically a public share or a customer portal.

Overview

BusinessMade Data Visualization lets you ask a question of your collections, inspect the answer and turn it into a reusable chart. We'll build a query, map its fields and place the saved result in a dashboard. We'll also cover multiple series, alternative chart types, the AI helper and the checks that keep an attractive chart from telling the wrong story.

Prepare

Use an authorized training collection with known values, such as three design_requests records: two with service: room and one with service: whole_home. Know their IDs and status values. Confirm the current aggregation field path with the initial results; the example below assumes business fields are under data. If the deployment returns a different shape, adjust the pipeline from observed data rather than forcing this sample.

1. Find saved queries and dashboards

Open Tools → Data viz. Use All, Dashboards and Items to distinguish a saved layout from its reusable query/chart items. Search for an existing training item and reopen it. Inspect the actual URL for the selected context and test reopening that address in an authorized session.

A query item defines the data and its display. A dashboard arranges saved items. Saving one does not automatically save a changed layout in the other.

Choose New Query for the first data item. The editor has three jobs: choose the collection, define the pipeline, and inspect its returned fields before chart mapping. A saved query and a saved dashboard are separate records, so reopen both when checking persistence.

2. Select a collection and run a small query

Choose the actual collection in Select collection.... Use a limited initial pipeline:

[
  { "$match": {} },
  { "$limit": 3 }
]

BusinessMade Data visualization query editor before choosing a collection or running the pipeline

Historical BusinessMade query-editor capture: Select collection is empty, the pipeline is the default and both results/chart areas are blank. The disabled Run button here does not mean query execution has failed; select a collection first. This is editor orientation, not evidence of the three-record result.

Choose Run, wait for the running state to finish and inspect the returned rows. Confirm that these are the intended collection and organization. Inspect where service and status are stored before composing the grouped query.

I'll start with three records so we can see the shape. Now we know which fields to group and what the saved values look like.

The editor requires a JSON array of stages, not a single object or JavaScript shell expression. Invalid JSON shows Invalid JSON; a non-array shows Pipeline must be a JSON array of stages. A missing collection must be selected before execution. A query failure is not a valid zero count.

3. Group records into the question you want to answer

Replace the initial pipeline with:

[
  { "$group": { "_id": "$data.service", "requests": { "$sum": 1 } } },
  { "$project": { "_id": 0, "service": "$_id", "requests": 1 } },
  { "$sort": { "service": 1 } }
]

Run and inspect service and requests in the results table. With only the prepared three records, the expected counts are room 2 and whole_home 1. If the collection contains more data, use an explicit supported match for the controlled record set before grouping; do not announce fixture totals over a broader dataset.

This query groups by the stored service value and counts the matching records. Before building the chart, we'll compare those totals with the underlying requests.

An empty result can come from a wrong field path or match condition. Return to the limited raw result, check the path and saved option values, correct one stage and run again. Do not remove every filter to make a misleading chart appear.

4. Map fields and verify the chart

Choose Bar. In Field Mapping, set Category (X-Axis) to service and Values (Y-Axis) to requests. Compare each bar with its table row. Use Split view, Results only and Chart only to inspect the same query output at a suitable size.

The category is the service, and the height is its request count. This chart now answers the same question as the table.

Auto-detect inspects the first returned row and treats number values as numeric fields. A numeric-looking string is not necessarily detected as a number. Check the real types and mapping; fix the query's data shape rather than treating a misleading auto-mapping as correct.

Set the query title to Requests by service, choose Save, leave and reopen it. Confirm collection, pipeline, chart type and mapping persist. Use Duplicate for a different question, give the copy a distinct title and Save: duplication creates an unsaved copy, not a persisted item by itself.

5. Add multiple values or split a metric into series

Multiple value fields show several measures for each category. Split by shows one measure broken out by another field. Those are different data shapes.

Duplicate the query and group by both service and status, returning service, status and numeric requests. Run it, map service as category, requests as value and status under Split by (optional). Show the resulting series and compare each category/status pair with the table.

The current pivot uses the first matching row for each category/series pair. Therefore aggregate duplicate pairs in the query first; do not assume the chart sums duplicate rows automatically. Missing pairs display zero in this mapping path.

For the multiple-value alternative, return two meaningful numeric measures and choose Add value field. Explain their units before comparing them. Stack series appears for eligible Bar, Line and Area mappings; only stack values whose sum has meaning. Compare stacked totals with the results table and turn stacking off again to show the difference.

6. Select chart types according to the actual implementation

Demonstrate the alternatives with appropriate saved query copies, rather than cycling through all icons over one unsuitable dataset.

ChartDemonstration and mappingCurrent boundary
BarCounts by serviceCategory and numeric values
Line / AreaOrdered periods with a numeric measureSort periods in the query; Area uses a line with fill
Pie / DoughnutService name and request countUses the first value field; confirm parts belong to the same total
ScatterInspect the actual mapped category/value pointsCurrent shared axis path is category-based; do not claim a general numeric X/Y correlation editor
RadarComparable numeric measures for named categoriesCurrent renderer uses up to the first five rows and auto-derived maxima
GaugeA deliberate single result/valueReads the first row's first mapped value; do not feed many rows and call it their total
FunnelNamed stages and numeric valuesThe query must establish stage meaning; a funnel graphic does not infer conversion paths
HeatmapCategory, split-by dimension and numeric valueInspect both axes and the color scale against returned rows
Treemap / SunburstName and valueCurrent Sunburst data is flat with empty children, not an inferred deep hierarchy
Box PlotExplicit precomputed five-number summariesCurrent renderer sorts selected values and chooses positions; it does not calculate robust sample quartiles for arbitrary observations
SankeyCategory as source, Split by as target, first value as flowBoth endpoint fields and a numeric value are needed; inspect each source→target link
MapRegistered geographic definition plus suitable configurationCurrent default displays a bar fallback with a map-registration note; it is not a rendered geographic map

Choose the shape that explains the data you actually have. A new chart type doesn't add missing dimensions or calculate an analysis the query never produced.

Show each actual limitation alongside its control/result briefly. Advanced custom chart overrides and geographic registration need their own verified configuration; keep that branch pending rather than announcing a working map from the selector alone.

7. Create the dashboard and place saved items

Choose New Dashboard, enter Editing, and open the query/items sidebar. Drag Requests by service into the canvas. Show the resulting section and card. Add the second saved query as another card. Use layout components/sections to arrange them so labels remain readable.

This card uses our saved query item. I'll add the second question alongside it, then save the dashboard layout.

Use card Config to inspect its title, description and available presentation settings. Save the dashboard with Save; the first save opens Save Dashboard for its record details. Enter a recognizable unique name and title, complete the form, leave and reopen.

The current card loader reads the first item in items; do not add several references to one card and promise they all render. Use separate cards for the demonstrated items. Older query-reference and table/chart configurations are supported by separate loading paths; inspect the actual record before editing a legacy dashboard.

8. View, duplicate and refresh the dashboard

Switch to Viewing and confirm the intended arrangement without the editing controls. Reopen Editing only when changing the layout. Use Duplicate to prepare a separate dashboard; name and save the copy, then reopen the original to verify it was retained.

Change one controlled source record through its proper module. On the dashboard use the affected card's Refresh and compare its revised value with the query table and source record. The card has explicit loading/error states; a failed request is not a zero metric. Verify chart rendering in the dashboard itself, since a correct query-editor preview does not prove the card's separate rendering path is correct.

This value changed because the source record changed. Refreshing the card reruns its data path; saving the layout alone doesn't prove the metric is current.

9. Use the scoped AI helper and inspect its changes

With the saved query open, ask the Data Visualization AI helper: Keep this collection. Group requests by their saved status and show counts as a bar chart. Keep the existing query as a separate saved item.

Before submitting, explain that the helper receives the active query/dashboard context and a small result preview, not an assumed complete dataset. Show its working state and resulting proposed/applied changes. Inspect collection, pipeline, field mapping and the returned rows. Save explicitly where required and reopen the intended item.

The helper can work in the context of this editor. We'll still inspect the query it produced and compare the chart with the results, especially if it changes the collection or grouping.

A live editor patch is not automatically a database save. Check whether the helper actually used a persistence action and verify the stored record. If it replaces the wrong item or uses an invalid field, stop that operation, restore the intended saved item and correct the prompt/context. Do not narrate an AI promise as an observed saved result.

10. Verify access and diagnose incorrect totals

Open the saved dashboard as the intended staff account. Inspect whether its underlying collection and query are authorized for that identity. A link copied from the administrator is not a public share grant. Do not use this internal dashboard as evidence that the customer My Account portal is configured.

For an incorrect total, follow the chain: source record → query filter/group → result row → field mapping → chart/card. For missing series, check duplicate category/series pairs and the first-row field shape. For a blank card, inspect its saved item reference and data response. For a stale number, use the card's refresh and reopen the saved query before changing layout settings.

You can now build a reusable question, show its result clearly and bring it into a dashboard. Keep the query and chart connected: every visible value should lead back to the authorized records that produced it.

Limitations and checks

Current code inspected under components/data-viz: home-view.tsx, workspace/query-editor.tsx, workspace/field-mapper.tsx, workspace/chart-type-picker.tsx, workspace/chart-preview.tsx, workspace/index.tsx, workspace/editor.tsx, layout/layout-card.tsx, data-viz-store.ts, data-viz-ai-bar.tsx.

Remaining live proof: aggregation field paths and server authorization, query/dashboard persistence, exact dynamic layout configuration fields, all suitable chart fixtures, card rendering consistency, URL reopening, date-range substitution where available, AI persistence and ordinary-role outcomes. Map registration and custom overrides need additional verified instructions before that advanced branch is considered complete. The embedded editor screenshot is retained historical BusinessMade evidence. No fresh successful aggregation, saved dashboard or AI run is claimed by this pass.

BusinessMade routing and outcome check

The menu and route were checked in packages/ui/src/ui/sidebars/business-made-links.ts and apps/business-made/src/shell/route-registry.ts. Open the module through the route stated at the start, perform the controlled procedure, save, reopen and inspect its actual BusinessMade consumer. Do not infer branch isolation from a header location selection when this shared screen reads organization-wide records. Record any access refusal or consumer mismatch with the exact record identity. No new provider, payment, physical-device or live-tenant action was performed for this adaptation.