- JavaScript 99.6%
- HTML 0.4%
| docs | ||
| src | ||
| static | ||
| test | ||
| .gitignore | ||
| CHANGELOG.md | ||
| manifest.yml | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
QS Work Item Insights
Forge app (Jira Cloud, Custom UI) that renders live Work Item Insights for any Jira/JSM space — visible to anyone on the site with a Jira license, without requiring JSM agent seats or space membership. Replaces a Power BI export → Teams workflow. Ships as a global page, an admin page, and 8 dashboard gadgets (one per panel), sharing one backend and one frontend panel library across all of them.
New here (human or agent)? Read docs/AGENT_BRIEF.md first, then
docs/DECISIONS.md.
Quickstart
npm install
forge login # Atlassian API token
forge register # assigns an app ID into manifest.yml
forge deploy # builds every static/* resource, then deploys
forge install --site <your-site>.atlassian.net --product jira
npm test # pure-function unit tests (node:test)
The page appears under Apps → Work Item Insights in Jira; the gadgets appear in a dashboard's "Add gadget" picker.
forge tunnel does not reliably preview jira:globalPage/
jira:dashboardGadget's Custom UI auto-resize — it's gotten stuck at
height: 0 in this repo's own testing even though the app was fully correct
underneath (docs/DECISIONS.md #25/#29). Use a real forge deploy to
visually verify anything layout-related in those two module types.
Repo map
manifest.yml Forge module/scopes definition
src/
index.js resolver entry (thin)
lib/
constants.js tuning knobs (poll/TTL/pager/buckets)
filters.js filter model -> JQL (only JQL assembly point)
jira-client.js asApp REST access, defensive pager
access.js blacklist + Browse-permission fallback
panel-registry.js BACKEND PARENT: fetch-once, cache, run panels
panels/
index.js backend panel roster (registerPanel calls)
aging/
aggregate.js pure (issues, ctx) -> data [reference panel]
static/
shared/ workspace package "wii-shared" (no manifest entry)
src/
PanelFrame.jsx FRONTEND PARENT: chrome/loading/error/empty
theme.js view.theme.enable(), called once per resource
layout.jsx CSP-safe Inline/Stack (see DECISIONS.md #27/#28)
ContextMenu.jsx right-click drill-down menu
panels/<name>/Panel.jsx display component, one per panel
main/ resource "main" (jira:globalPage)
src/{main.jsx, Dashboard.jsx, FilterBar.jsx, panelLayout.jsx, ...}
admin/ resource "admin" (jira:adminPage)
gadget/ resource "gadget" (all 8 jira:dashboardGadget)
src/gadgetRegistry.js moduleKey -> which panel to show
gadget-edit/ resource "gadget-edit" (shared config screen)
test/
fixtures/issues.json deterministic issue fixture
*.test.js one file per panel aggregate + lib helper
docs/
AGENT_BRIEF.md full context transfer / architecture rules
DECISIONS.md settled decisions + open items
custom-ui-migration-plan.md the (now complete) UI-Kit -> Custom UI plan
Adding a panel (the whole point)
src/panels/<name>/aggregate.js— pure function(issues, ctx) => datatest/<name>.test.js— fixture teststatic/shared/src/panels/<name>/Panel.jsx— display inside<PanelFrame>- One line each in
src/panels/index.js(backend roster) and, for whichever surfaces should show it,static/main/src/panelLayout.jsx(main dashboard) and/orstatic/gadget/src/gadgetRegistry.js(+ amanifest.ymlgadget entry) forge deploy
If step 6 exists, the architecture is drifting — see AGENT_BRIEF.