Skip to content

MWPW-185892: Show referring collections and projects in fragment details - #1199

Open
Axelcureno wants to merge 21 commits into
mainfrom
MWPW-185892
Open

MWPW-185892: Show referring collections and projects in fragment details#1199
Axelcureno wants to merge 21 commits into
mainfrom
MWPW-185892

Conversation

@Axelcureno

Copy link
Copy Markdown
Member

Adds a References section to the Studio fragment details panel: the collections, promo / bulk-publish / localization projects, and cards that reference the open fragment, grouped by type in collapsible sections, each row a link. Uses the AEM GET-by-id referencedBy endpoint (returns id + model, so rows are link-ready in one call rather than 1+N fetches). References classify by model.path, consistent across all types. Epic MWPW-186018, layer 4B.

Also prototypes (epic 4A / MWPW-185891) a collapsed Usage (last 7 days) section: consumer / locale / country request counts from Akamai CDN logs via a new fragment-usage IO proxy that keeps the Grafana service token server side. Marked PROTOTYPE. It degrades to hidden when the proxy or token is absent, so it never affects the shipped References list.

Resolves https://jira.corp.adobe.com/browse/MWPW-185892
QA Checklist: https://wiki.corp.adobe.com/display/adobedotcom/M@S+Engineering+QA+Use+Cases

Please do the steps below before submitting your PR for a code review or QA

  • C1. Cover code with Unit Tests
  • C2. Add a Nala test (double check with #fishbags if nala test is needed)
  • C3. Verify all Checks are green (unit tests, nala tests)
  • C4. PR description contains working Test Page link where the feature can be tested
  • C5: you are ready to do a demo from Test Page in PR
  • C.6 read your Jira one more time to validate that you've addressed all AC's and nothing is missing

Test URLs:

Reviewer notes:

  • References (4B) is testable on the After URL directly (pure Studio frontend, no IO needed). Open any card that belongs to a collection; the References section lists it grouped by type with working links.
  • Usage (4A prototype) needs the fragment-usage IO action. The Grafana service token is now sourced from Vault (aio-studio/common) in CI. Not exercised by the standard studio URL until deployed to the masstudio namespace; validated live against a personal namespace.
  • Page and experience-fragment parents are intentionally excluded (out of scope, that is the 4A Akamai story).
  • A few pure helpers in references-repository.js are exported and unit-tested but not yet wired into production; kept as covered helpers.

- add getReferencedByFragmentId (GET by-id referencedBy) to the AEM client; it
  returns link-ready parents with id and model, plus cursor pagination
- new references-repository: filters out pzn/promo/self-locale/cross-surface
  refs, groups collections by locale, buckets bulk-publish projects separately
- render a "Referenced by" section in the fragment editor: collections link to
  the card editor, projects link to the bulk-publish editor, with locale counts
  and status chips
- monotonic load-token plus abort controller guard against rapid fragment switches
…oxy)

- usage-repository: pure buildUsageQuery + parseUsageResponse for the Grafana
  ClickHouse ds/query (org 750, trafficpeak read-only), unit-tested with mocked
  response fixtures, no token or network needed
- fetchFragmentUsage targets a future IO Runtime proxy action and degrades to
  { available: false } on any failure (no proxy yet, auth, CORS, network)
- gated "Usage" section in the fragment editor: renders only when usage data is
  available, so it stays invisible until the proxy exists and never affects the
  shipped reference list
- the glsa_ service token must live only in the IO action inputs, never the
  browser; direct browser to Grafana is both a secret leak and CORS-blocked
- new io/studio fragment-usage action: validates the caller IMS token, builds the
  ClickHouse query server side (client cannot inject SQL), and forwards to Grafana
  with the glsa_ service token read from the GRAFANA_TRAFFICPEAK_TOKEN deploy input
- the token lives only in the action input, never in source, logs, or the response;
  action test asserts it reaches the Grafana auth header but never leaks in the body
- studio usage-repository now posts { fragmentId } to the action and parses the
  Grafana response; still degrades to { available: false } until the action is
  deployed, so the shipped reference list is unaffected
- default Grafana host set to adobe-grafana.trafficpeak.live (old grafana-us retired)
…tion

- rename the "Referenced by" block to "References" and move it below grouped
  variations in the editor
- bucket references by model type in display order: Collections, Cards, Promo
  Projects, Bulk Publish Projects, Localization Projects, Other
- each type is its own collapsible row with a count, collapsed by default
- promo and localization project rows deep-link to their editors; add
  buildPromoProjectDeepLink and buildTranslationProjectDeepLink
Match the deploy .env var name (GRAFANA_SERVICE_TOKEN / GRAFANA_SERVICE_URL) so
the fragment-usage action's inputs resolve. Deployed and verified: both inputs
inject from .env, endpoint returns 401 without a bearer.
…ndly)

Usage hits the shared Grafana/Hydrolix cluster, so stop auto-loading it on every
fragment open. It is now a collapsed "Usage" section below References that fetches
only when the author expands it, and caches the result per fragment id for the
session so re-expanding never re-queries. Cuts query volume from one-per-fragment-
browsed to one-per-fragment-actually-inspected.
Constrain the References container to a fixed width and reduce vertical padding so
it sits cleanly below grouped variations.
The epic's assumed schema (fragment_id/locale/api_key columns, datasource
fdyta6qpga2o0d) does not exist on the migrated adobe-grafana instance. Derived the
real shape from the "M@S - web_commerce_artifact" dashboard:
- datasource ffmjsr3rpsrnkc, table akamai.logs, time column reqTimeSec
- fragment id and api_key live in the query string (queryStr), not columns
- match a fragment by reqPath/queryStr LIKE, group by api_key + country
- default window tightened 30d -> 7d, plus hdx exec-time cap and an attribution
  comment, since a per-fragment LIKE scan on raw CDN logs is not cheap

Deploy intentionally held pending ops sign-off on query scale. The reqTimeSec
filter form and api_key extraction were derived from the dashboard, not executed
(cluster probes are gated), so validate on first live run.
FluffyJaws (M@S monitoring wiki + MWPW-185891 + Slack) corrected the query the
dashboard guess produced:
- endpoint is reqPath = '/mas/io/fragment' (exact), not the web_commerce_artifact
  WCS path
- extract id/locale/api_key from the query string with extractURLParameter, and
  match the fragment by exact id, not a substring LIKE (avoids false positives)
- group by api_key, locale, country (locale is a real dimension); referer-page
  URLs stay out of scope per the story
- deploy still held pending ops sign-off on scale

Design note for the feature owner: the story's intended shape is a materialized
hourly/daily/weekly rollup behind an IO action refreshed ~hourly, not a raw-log
scan per panel open. This prototype does on-demand + per-session cache, which is
fine for v1 but the rollup is the scalable target.
Match mas-related-variations: each type/usage collapsible is a standalone
gray-50 rounded card with the same toggle styling, instead of one bordered box
with thin inner rows. Also fix the usage label to "last 7 days" (matches the
action's default window).
Add grafana_service_token to the shared-service-secrets fetch from
merch-at-scale/aio-studio/common. The vault-secrets action uppercases it to
GRAFANA_SERVICE_TOKEN, which the fragment-usage action reads. Keeps the token in
Vault only, out of .env and the repo.
Local Studio can point the IO base at any personal namespace via ?io.ns=
(e.g. merchatscale-axel when a dev deploy lands there instead of masstudio-axel).
Gated to localhost so prod Studio can never be redirected to another runtime host.
…ct ternary

- parseUsageResponse: rename ai/lo/ci/ni/f to descriptive index names.
- toggleReferenceType: if/else instead of a ternary used for its side effect.
No behavior change.
The referencedBy endpoint returns model.path as the plain path (the *_MODEL_ID
constants are the base64 of that path, used by the fragment-model API). Matching
promo / bulk-publish / localization projects by model.id never hit, so they all
fell into the non-linkable "Other" bucket. Match by model.path, like
collections and cards, so those rows classify correctly and get their deep links.

Also reword the empty usage state to "No usage found for this fragment
(last 7 days)"; update fixtures to the real model.path shape.
@aem-code-sync

aem-code-sync Bot commented Sep 1, 2026

Copy link
Copy Markdown

Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch.
In case there are problems, just click the checkbox below to rerun the respective action.

  • Re-sync branch
Commits

Resolve studio/src/utils.js import conflict by keeping both PAGE_NAMES
(this branch) and PZN_FOLDER (main); both are used in the file.
@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.38404% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.83%. Comparing base (2f2e131) to head (42444e4).

Files with missing lines Patch % Lines
studio/src/mas-fragment-editor.js 89.49% 23 Missing ⚠️
io/studio/src/fragment-usage/usage.js 97.29% 3 Missing ⚠️
studio/src/references/references-repository.js 99.14% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1199      +/-   ##
==========================================
+ Coverage   90.71%   90.83%   +0.11%     
==========================================
  Files         318      321       +3     
  Lines      101712   102513     +801     
==========================================
+ Hits        92271    93118     +847     
+ Misses       9441     9395      -46     
Files with missing lines Coverage Δ
studio/src/aem/aem.js 53.47% <100.00%> (+1.27%) ⬆️
studio/src/references/usage-repository.js 100.00% <100.00%> (ø)
io/studio/src/fragment-usage/usage.js 97.29% <97.29%> (ø)
studio/src/references/references-repository.js 99.14% <99.14%> (ø)
studio/src/mas-fragment-editor.js 89.17% <89.49%> (+0.11%) ⬆️

... and 9 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2f2e131...42444e4. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant