# GB5 Dashboards, Pages & Portlets: Admin & End-User Guide

## Who this is for

Implementation/admin team members setting up dashboards for a client, and end users who want to
personalize the dashboards they already see. If you're extending the underlying code, see
[PortletDashboardFramework_TechnicalGuide.md](PortletDashboardFramework_TechnicalGuide.md) instead.

## Status note (please read before following the steps below)

Everything described here is real, working backend functionality, live-verified on GB5DEMO. The
admin/dev screens described below exist and pass TypeScript checks, but **have not yet been
click-tested in a browser** — the shared dev machine used to build this ran out of memory before
the app finished compiling (an environment issue, not a code problem — see the Technical Guide's
"Known gaps" section). Screens are described from their exact source configuration, and every
field name below matches the real form. Treat any `[Screen: …]` block as a placeholder for a
screenshot that will be added once browser verification is possible.

Four screens — Dashboard Admin, Portlet Type Version Manager, and the two Entitlement mapping
screens — now have real GB5 menu entries in addition to their dev route, granted today to the
platform administrator role. Any user holding that role sees them directly in the normal menu;
if you don't see one and believe you should, ask your GB5 administrator to grant your role
access via the standard Role↔Menu screen (this is the same role-based mechanism every other
GB5 menu item already uses — nothing special about these four). Every other screen below is
still dev-route-only — reached today via a direct URL, not by clicking through the app's menu.

## The mental model

- A **Dashboard** is a named collection of tabs.
- Each tab is a **Page** — a page can be shared across more than one dashboard.
- Each page holds one or more **Portlets** — a portlet is one widget (a chart, a KPI card, a
  table, …).
- Every portlet is an instance of a **Portlet Type** — the catalog entry that defines *what kind*
  of widget it is and what it's capable of.
- A **filter** set at the Dashboard level flows down to every Page and Portlet inside it, unless
  a more specific level explicitly overrides it. Order of authority:
  **Dashboard → Page → Portlet → whatever the end user picks on screen right now.**

## For implementation/admin: setting up a Dashboard

1. Open the Dashboard admin screen at `/dev/dashboard`.
2. Fill in the Dashboard's basic details: **Dashboard Code**, **Dashboard Name**, **Dashboard
   Type**, the owning **Module**, an **Owner**, an optional **Image**, **Sort Order**, and
   **Remarks**.
3. Optionally set a **Default Criteria Config Id** — a number referencing an already-authored
   filter (a "Criteria Config"). Every page and portlet on this dashboard will use this filter
   by default unless it overrides it (see below). Either enter the id of a filter that already
   exists, or click **+ New Filter** to open a small dialog, name a new filter, pick from the
   available attributes (today: Status, Organization Unit), give each a comparison and a value,
   and save — the new filter's id is filled in automatically.
4. Save. The success message includes the new **Dashboard Id** — you'll need it for the next
   step.

*[Screen: Dashboard master form — Dashboard Code/Name/Type fields, Module/Owner/Image pickers,
Sort Order, Remarks, and the Default Criteria Config Id field, with a Save button.]*

### Assigning Pages to the Dashboard

Still on the same screen, below the Dashboard form, is a Page-assignment panel:

1. Search for and select the Dashboard you just saved by its code or name — its pages load
   automatically once selected.
2. Search for and select an existing Page to add, and set:
   - **Sl No** — determines tab order (also drag-and-drop reorderable).
   - **Is Default Tab** — which page opens first when a user opens this dashboard.
   - **Is Visible** — hide a page from this dashboard without removing the assignment.
3. Reorder assigned pages by dragging them; the new order saves automatically.
4. Remove a page's assignment from this dashboard without affecting the page itself elsewhere.

*[Screen: Page-assignment panel below the Dashboard form — a draggable list of assigned pages
with Sl No, Is Default Tab, Is Visible controls, and a search-and-select box for adding a page.]*

A Page itself (reached via its own existing menu-driven screen, not this Dashboard admin screen)
has the identical **Default Criteria Config Id** + **+ New Filter** pair — a page-level default
that every portlet on it inherits, unless a portlet's own filter overrides it.

## For implementation/admin: setting up a Portlet

Portlets are created and edited on the existing Portlet screen. As of this roadmap, it supports
full create/edit/delete (previously it only supported creating a brand-new portlet):

1. Use the **Load Existing Portlet** dropdown to search for and open an existing portlet, or
   leave it on "New Portlet" to create one.
2. Fill in **Portlet Code**, **Portlet Name**, and pick a **Portlet Type** from the dropdown.
3. If the Portlet Type is "Analysis", additional fields appear to pick a **Dataset**,
   **Dimension**, and **Measure**, with a live preview of the resulting chart/table/KPI card.
4. Optional **Cross-portlet Pub/Sub** fields — set these if you want this portlet to broadcast
   a value other portlets on the same page can react to (Publish Channel/Field), or to react to
   another portlet's broadcast (Subscribe Channel/Field). Leave all four blank for a portlet
   that doesn't need to talk to any other portlet. If you set one of a pair (e.g. Publish
   Channel without Publish Field), the save will be rejected — both or neither.
5. Optional **Default Filter**: a **Default Criteria Config Id** (same reference-or-author-new
   mechanism as the Dashboard screen — **+ New Filter** is available here too) and an **Override
   Page/Dashboard filter tiers** flag (enter `1` to make this portlet's own filter win over the
   Page's and Dashboard's, `0` to let theirs apply as normal).
6. Save. If something's wrong with the save, the screen now shows the real error message
   (previously, save failures were silently swallowed and looked like success).
7. Delete is available once you've loaded an existing portlet.

*[Screen: Portlet form — Load Existing Portlet dropdown, Portlet Code/Name/Type fields, the
Analysis-type dataset/dimension/measure cascade with live preview, the Pub/Sub fieldset, the
Default Filter fieldset, and Save/Delete buttons.]*

## For implementation/admin: Portlet Types and versions

A **Portlet Type** is the catalog entry (Chart, KPI Card, Table, Analysis, Search, …) — most
implementation teams won't create new ones day-to-day, but two things are worth knowing:

- Every portlet type now carries a **Tenant Id** and an **Is Registry Managed** flag on its
  master screen — these existed in the database since this roadmap's first phase but were
  silently ignored by the save/load logic until this pass; they now round-trip correctly.
- A portlet type's capabilities can be versioned: search for and select the Portlet Type by
  code or name, then draft a new version's schema, list all versions, and explicitly activate
  one when it's ready — at `/dev/portlettype-version`, or through the normal GB5 menu if your
  role has been granted access. Activating a version updates the portlet type's live
  capabilities immediately.

*[Screen: Portlet Type Version manager — a search-and-select box for the Portlet Type, a list
of its versions, a "draft new version" text area for the schema JSON, and an Activate button
per version.]*

## For implementation/admin: controlling visibility by license (Entitlement)

If your organization licenses GB5 features individually, you can restrict which **Standard**
portlet types or dashboards a client can see based on what they're licensed for. ("Standard"
means the portlet type/dashboard was built by the Framework/DevAdmin team; anything built by an
implementation team, a client admin, or an end user is always visible — licensing gates only
apply to Standard, platform-provided items.)

- `/dev/ent-portlettypemap` (or the normal GB5 menu, if your role has access) — map a **Feature
  Code** (the license feature's identifier) to a Portlet Type. A client not licensed for that
  feature won't see that portlet type offered.
- `/dev/ent-dashboardmap` (or the normal GB5 menu, if your role has access) — same idea, mapping
  a Feature Code to a Dashboard.

If the licensing service is unreachable for any reason, GB5 always **fails open** — it shows the
Standard portlet type/dashboard rather than silently hiding something a client should be able to
see. This is a deliberate safety choice, not a bug.

*[Screen: Feature-to-PortletType mapping screen — Feature Code text field, Portlet Type
picker, Save/Delete — and its Dashboard-mapping twin, visually identical apart from the picker.]*

## For end users: personalizing "My Dashboards"

Any user can pin their favorite dashboards to the top of their list and reorder the rest, without
needing an admin:

1. Open the "My Dashboards" panel via the small icon added to the dashboard tab bar.
2. **Pin** a dashboard to move it to the top of your list, ahead of everything unpinned.
3. **Drag and drop** to reorder any of your unpinned dashboards — your custom order is
   remembered, separate from every other user's.
4. **Reset to default** on any dashboard to drop your personal override and go back to
   whatever order/pin state the platform assigns by default.

This is entirely personal — it doesn't change what any other user sees, and it doesn't move or
delete the dashboard itself.

*[Screen: My Dashboards dialog — a list of available dashboards with pin toggles, drag handles,
and a reset-to-default action per row.]*

## Common mistakes to avoid

- Entering `true`/`false` instead of `0`/`1` for a filter-override flag — these fields are
  plain numbers, not checkboxes.
- Setting only one of a Publish/Subscribe channel-and-field pair — the save will be rejected;
  set both, or leave both blank.
- Assuming every screen listed above is reachable from the normal GB5 menu today — only
  Dashboard Admin, Portlet Type Version Manager, and the two Entitlement mapping screens have a
  real menu entry so far (visible to whichever role your GB5 administrator grants it to, the
  same way every other menu item works); everything else still requires typing its dev-route
  URL directly.
- Leaving the new-filter dialog's **Filter Name** blank, or not checking at least one attribute
  and giving it a value — the save is rejected until both are set.

## What's coming next

- Real menu-driven navigation to the remaining screens (Portlet, Page, PortletType masters).
- Live screenshots of every screen above, once browser verification is unblocked.
