Implemented OpenSpec and created and updated its artifacts
This commit is contained in:
341
README.md
341
README.md
@@ -2,30 +2,94 @@
|
||||
|
||||
Browser extension that adds the "Opportunities Extension" shortcut to the permitted Oracle Fusion pages, retrieves opportunities, and displays them in a filterable table or calendar.
|
||||
|
||||
See [Release Notes](RELEASE_NOTES.md) for version history and
|
||||
[Architecture](docs/architecture.md) for execution, authentication and storage contracts.
|
||||
|
||||
## OpenSpec Workflow
|
||||
|
||||
The [twelve durable capability specifications](openspec/specs/) define the reviewed
|
||||
behavioral baseline for this checkout. The initial
|
||||
[`document-project-baseline` change](openspec/changes/archive/2026-10-31-document-project-baseline/proposal.md)
|
||||
was completed and archived on 2026-10-31. Its
|
||||
[design and evidence map](openspec/changes/archive/2026-10-31-document-project-baseline/design.md)
|
||||
connect the baseline to source and tests, and its
|
||||
[tracked tasks](openspec/changes/archive/2026-10-31-document-project-baseline/tasks.md)
|
||||
record the completed application work. Use the durable specifications as the
|
||||
starting point for subsequent capability changes.
|
||||
|
||||
For subsequent work, explore the problem, propose a change with the affected
|
||||
capabilities, apply its tasks, verify the outcome, then archive. In Codex these
|
||||
steps use `$openspec-explore`, `$openspec-propose`, `$openspec-apply-change` and
|
||||
`$openspec-archive-change`. Application and archival are separate actions.
|
||||
|
||||
```bash
|
||||
openspec list --json
|
||||
openspec list --specs --json
|
||||
openspec validate --specs --strict
|
||||
```
|
||||
|
||||
Keep setup/usage guidance here, behavioral requirements in OpenSpec, execution
|
||||
details in the architecture document and historical releases in RELEASE_NOTES.md.
|
||||
|
||||
## Opportunity Views
|
||||
|
||||
**Overview** is the default table view. **Calendar** displays opportunities
|
||||
by Close Date (`EffectiveDate`) with month and week views only. Both views share
|
||||
Reference, search and all existing filters; switching views does not send requests.
|
||||
Events use date-only values without time-zone shifts, stage colors, and a read-only
|
||||
detail with an opportunity link and copy button. Invalid or missing dates appear
|
||||
in a separate list. Calendar navigation does not change the selected Reference.
|
||||
**Overview** is the default table view. It gives Name and Customer greater width
|
||||
priority, uses customer `PartyName`, and labels win probability **Prob.**. Monetary
|
||||
values and headers align right; other headers align left. Counts and stage amounts
|
||||
follow the filtered opportunities.
|
||||
|
||||
Overview and **Calendar** share Reference, search, Customer, Owner, Status, Stage,
|
||||
Booking/Workload and eligible SR/Action filters. Selecting Customers narrows the
|
||||
available Owners, and selecting Owners narrows Customers, using loaded data.
|
||||
Clicking one choice while all choices are selected isolates that choice; subsequent
|
||||
clicks can add others. This also applies to Booking/Workload badges. The SR below
|
||||
4h option has its own exclusive behavior, described under Workload Actions.
|
||||
|
||||
Calendar displays Close Date (`EffectiveDate`) in vertically scrolling months
|
||||
restricted to Reference. There are no previous/next buttons or month/week switch.
|
||||
Every matching opportunity has a card; crowded days scroll internally instead of
|
||||
using a hidden-event overflow link. Switching views and filtering loaded records
|
||||
do not send new opportunity requests. When today is inside Reference, the view
|
||||
positions around its week with one preceding and one following week where the
|
||||
Reference allows; otherwise it starts at the beginning of the range.
|
||||
|
||||
Cards preserve the API calendar day without timezone shifts and use stage colors.
|
||||
Clicking opens read-only details with an opportunity link and copy action. Invalid
|
||||
or missing close dates remain accessible in a separate collapsible list. Fiscal
|
||||
labels use `FY27-Q2-W19`: June-May fiscal years, Sunday-Saturday weeks, and W1 for
|
||||
the week containing June 1. The week's Sunday determines its quarter, except W1
|
||||
belongs to Q1.
|
||||
|
||||
Table sorting remembers the last column and direction independently for Overview,
|
||||
Installed Base, Service Requests, Rate Card, Consumption projection and Manage Time.
|
||||
Preferences are restored when reopening each view and survive page reloads in the
|
||||
same browser profile. Opportunity product tables retain their original order.
|
||||
Each day shows a filtered opportunity count, at most two events and an overflow
|
||||
link to the remaining events. The grid fits the available height and reduces
|
||||
visible events to one or zero when needed to keep every week visible. Missing
|
||||
close dates are available in a collapsible list below the calendar.
|
||||
Fiscal labels use `FY27-Q2-W19`: June-May fiscal
|
||||
years, Sunday-Saturday weeks, and W1 for the week containing June 1. A quarter is
|
||||
assigned by the week's Sunday, except the first fiscal week which belongs to Q1.
|
||||
Installed Base, Service Requests, Rate Card, Consumption projection, contact
|
||||
opportunities and Manage Time. Preferences survive reopening and page reloads in
|
||||
the same browser profile. Opportunity product tables retain their original order.
|
||||
|
||||
FullCalendar Standard 6.1.19 is bundled locally under `src/vendor/fullcalendar/`
|
||||
with its MIT license. It is initialized only on first use, without a runtime CDN.
|
||||
|
||||
## Products, Workloads and Projections
|
||||
|
||||
Product counts and details load in the background after opportunities are shown.
|
||||
Workloads are retrieved per distinct customer account, paginated and matched to
|
||||
products by `RevnId`. Valid workload cache entries are reused across modal openings
|
||||
and token renewals according to Cache duration.
|
||||
|
||||
When a nonempty product list contains only blank or `-` Workload names, the ramp
|
||||
badge becomes **Booking**, with its own color. If any product has a Workload name,
|
||||
the ramp behavior remains. Booking and Workload badges beside the view tabs filter
|
||||
these categories.
|
||||
|
||||
Clicking a ramp badge opens **Consumption projection** even when there is no
|
||||
forecast discrepancy. Difference alerts sit between the ramp and SR badges;
|
||||
products without a workload record show an unavailable alert in a disabled color.
|
||||
Projection calculates monthly amounts from adjusted ACR and ramp months, including
|
||||
first-month proration, and compares `forecast - calculated` at cent precision.
|
||||
|
||||
**Update estimates** asks for confirmation before sending the Calculated values
|
||||
to SPA. It prevents duplicate submission, reports success or failure, refreshes
|
||||
the comparison after success and invalidates the affected workload cache.
|
||||
|
||||
## Customer Organization Charts
|
||||
|
||||
The organization-chart icon beside **View customer service requests** opens a
|
||||
@@ -53,9 +117,29 @@ changes require confirmation before closing. The extension background stores
|
||||
JSON-compatible records in IndexedDB, scoped by current user and customer ID in
|
||||
the current browser profile. Records include schema version, revision, update
|
||||
timestamp and a flat node array (`id`, `parentId`, `name`, `jobTitle`, `notes`,
|
||||
`collapsed`, and optional `contactPartyId`). Concurrent stale saves are rejected. Charts are local and do not
|
||||
sync between devices or write to Oracle services. They support up to 500 people
|
||||
and 60 reporting levels, with required name and optional notes.
|
||||
`collapsed`, and optional `contactPartyId` and `PartyNumber`). PartyNumber is
|
||||
preserved as an identifier, including alphanumeric values such as `A4KCS2P`.
|
||||
Person details persists a returned PartyNumber so it can be reused by subsequent
|
||||
opportunity lookups. Concurrent stale saves are rejected. Saving the hierarchy
|
||||
does not write it to Oracle or synchronize it between devices. Charts support up
|
||||
to 500 people and 60 reporting levels, with required name and optional notes.
|
||||
|
||||
The opportunities icon beside the person's delete action opens
|
||||
**Opportunities | <name>**. It uses that person's stored PartyNumber in
|
||||
`OpportunityContact.ContactPartyNumber`, resolving it through contact lookup when
|
||||
missing. It loads all pages while `hasMore=true`, shows a loading skeleton and
|
||||
provides sortable results. Clicking an opportunity Name opens its corresponding
|
||||
Fusion opportunity in a new tab. Unresolved identifiers produce an explicit error
|
||||
instead of an unfiltered opportunity query.
|
||||
|
||||
The Create Contact button at the right of **Name** opens an Oracle contact form.
|
||||
First Name, Last Name and Email Address are required. Job Title and Work/Mobile
|
||||
Phone are optional; supplied country codes and numbers are combined as
|
||||
`55-99999999999`. Email and phone consent selections map to the corresponding
|
||||
Do/DoNot flags. Account identifiers come from the current customer, and absent
|
||||
optional values are omitted. Save submits directly to the contact API, without a
|
||||
payload preview. Contact creation is a separate Oracle write from local chart
|
||||
persistence.
|
||||
|
||||
The interaction is inspired by [OrgChart](https://github.com/dabeng/OrgChart).
|
||||
Layout uses bundled [D3 Hierarchy 3.1.2](https://d3js.org/d3-hierarchy/tree), with
|
||||
@@ -74,7 +158,7 @@ check below.
|
||||
|
||||
- `src/content/`: page integration, modal shell, theme and content composition.
|
||||
- `src/background/`: synchronous message registration and background composition.
|
||||
- `src/features/`: opportunities, products, consumption, AI summaries, preferences and debug.
|
||||
- `src/features/`: opportunities, products, consumption, customer tables, organization charts, Manage Time, preferences and debug.
|
||||
- `src/auth/`: credential-specific selection, reuse and session recovery.
|
||||
- `src/services/`: Fusion/SPA operations and background HTTP/JSON transport.
|
||||
- `src/platform/`: narrow browser messaging, cookies, tabs and storage adapters.
|
||||
@@ -85,52 +169,66 @@ check below.
|
||||
- `dist/chromium/`: output for Google Chrome and Microsoft Edge.
|
||||
- `dist/firefox/`: output for Firefox.
|
||||
|
||||
## Authentication and Access
|
||||
|
||||
Before dependent data requests, the extension establishes a valid SPA identity.
|
||||
Concurrent consumers share acquisition; Reference changes and modal reopenings
|
||||
reuse success. Identity also has a background browser-session cache, partitioned
|
||||
by Firefox cookie store and private-browsing context, so a page reload does not
|
||||
necessarily fetch identity again. The validated API response must contain user
|
||||
id, name, roles and a token; the reusable identity stores only id, name and roles.
|
||||
Failures keep dependent requests waiting and retry with backoff.
|
||||
|
||||
Users with **SALES_REP** do not load CRM SR or Workload Actions data or see their
|
||||
badges. **Manage Time** is also hidden and its data request entry points are
|
||||
blocked. Independent SR session bootstrap may still run; readiness does not grant
|
||||
access to restricted activity data.
|
||||
|
||||
When identity requires session recovery, the extension opens
|
||||
`https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/ui/index.html?ojr=whitespace`
|
||||
in an inactive auxiliary tab. SPA inspection rejects error documents, SAML/login
|
||||
forms and OAuth callbacks before an identity probe. HTTP 200, cookies or elapsed
|
||||
time alone do not prove readiness. Rejected callbacks restart at this bootstrap
|
||||
URL. Recovery preserves the originating browser context and cleans up its owned
|
||||
tab; its bounded cycle can be retried by the waiting identity gate.
|
||||
|
||||
Consumer-token recovery uses the same SPA bootstrap URL for invalid JSON and
|
||||
HTTP 401/403, with up to five HTTP attempts. Token Relay uses the Fusion XSRF
|
||||
cookie, has a 30-second request timeout and bounded cookie recovery; it cannot
|
||||
remain indefinitely pending when the timeout fires.
|
||||
|
||||
SR session preparation can run concurrently with SPA preparation through
|
||||
`https://comcipapic-oalprod.integration.ocp.oraclecloud.com/ic/builder/rt/SeaaS_initiation/live/webApps/external/`.
|
||||
It reports **SR session ready** on success, waits up to 70 seconds, and offers
|
||||
Retry after failure. Eligible users' resource data is consumed after both identity
|
||||
and SR preparation finish. See the architecture document for service-specific
|
||||
credentials and the distinction between session navigation and API requests.
|
||||
|
||||
## CRM Service Request Badges
|
||||
|
||||
The header's **Refresh all** button (between theme and Preferences) invalidates
|
||||
persisted Products and activity caches and clears in-memory data views. It reloads
|
||||
the selected Reference, fetching fresh products and then the permitted SR/Actions
|
||||
queries. Customer details, rate cards, consumption charts and AI summaries are
|
||||
The header's **Refresh all** button invalidates persisted Products and activity
|
||||
caches and clears related in-memory data views. It reloads the selected Reference,
|
||||
displays opportunities first, then starts permitted SR and product enrichment.
|
||||
Actions follow their SR/product prerequisites. Customer details, rate cards and consumption charts are
|
||||
requested again when opened. Preferences, cookies and authentication are preserved.
|
||||
The button is disabled during invalidation and list reload; product/activity badges
|
||||
continue to show subsequent background progress. Cache-clear failures are surfaced
|
||||
instead of silently reusing cached data, and stale product responses cannot restore
|
||||
an invalidated cache.
|
||||
|
||||
On the first Opportunities modal opening in a page session, `requestCurrentUser`
|
||||
fetches SPA identity before tokenrelay or opportunity requests. Concurrent calls,
|
||||
Reference changes and modal reopenings reuse that result. Users with `SALES_REP`
|
||||
do not trigger CRM Service Request or Workload Actions queries or see their badges.
|
||||
Identity must contain a valid user (id, name, roles) and token before dependent
|
||||
requests start. Failed identity validation keeps those requests waiting and retries
|
||||
with backoff. Reload the page to refresh identity/roles.
|
||||
The identity token is retained in debug responses and hidden by default; the
|
||||
explicit sensitive-values toggle reveals the original value.
|
||||
Opportunity retrieval first calls `requestOpportunitiesSavedSearch` and requires
|
||||
exactly one valid `isDefault=true` item. Its `savedSearchNumber` becomes
|
||||
`copiedFrom: queries/<savedSearchNumber>` for every opportunity page. A missing or
|
||||
ambiguous default blocks the dependent query instead of using a hard-coded value.
|
||||
|
||||
After an initial identity failure, recovery opens `https://spa.oracle.com/` in one
|
||||
inactive auxiliary tab. The top-frame-only `spa-page.js` content script inspects
|
||||
the page without sending HTTP requests. It rejects error pages, SAML/login forms,
|
||||
OAuth callbacks and incomplete documents; cookies, HTTP 200 and elapsed time alone
|
||||
do not establish readiness. After a stable loaded document is verified, identity
|
||||
is fetched in that tab's same-origin context, at most once per document. A failed
|
||||
read requires a fresh verified navigation before retrying. Rejected callbacks
|
||||
restart at the SPA home URL, never at the one-use callback URL. A two-minute
|
||||
readiness timeout ends the cycle without an additional API probe. The owned tab
|
||||
and observers are cleaned up on success or failure. Debug metadata records the
|
||||
page state, wait reason and `spa-tab` execution context; sensitive values remain
|
||||
hidden by default. Reload the extension after changes to the manifest or script.
|
||||
|
||||
Consumer token recovery also handles HTTP 401/403, in addition to HTTP 200 with
|
||||
invalid JSON. It opens the existing SPA session URL in an inactive temporary tab,
|
||||
preserves the originating window and Firefox cookie store, and retries within
|
||||
the same five-attempt limit. Debug entries retain the HTTP status and recovery
|
||||
reason. The auxiliary tab is closed after valid JSON or exhausted retries.
|
||||
|
||||
After a completed product-loading cycle with fresh API results, `resquestCrmServiceRequest` fetches all pages of
|
||||
`CRMServiceRequest` records with `SVC_PENDING_DELIVERY` and `ORA_SVC_MY_SR_TEAM_SRS`,
|
||||
using the existing general tokenrelay Bearer. It uses the Fusion `searchResources/latest`
|
||||
query endpoint, independently of the opportunity query version. Calls appear in
|
||||
the Service Requests debug category with masked credentials.
|
||||
After all opportunity pages are displayed, SR and product enrichment start in the
|
||||
background. Before the first `resquestCrmServiceRequest` page,
|
||||
`requestSRSearchResources` retrieves CRMServiceRequest searches with the general
|
||||
Token Relay Bearer. The first item's `savedSearchNumber` supplies SR `copiedFrom`;
|
||||
this is independent of Opportunity's default-search selection.
|
||||
SR fetches all pages of `SVC_PENDING_DELIVERY` / `ORA_SVC_MY_SR_TEAM_SRS` records
|
||||
through Fusion `searchResources/latest`. Each page can update badges while the
|
||||
remaining pages load. These requests appear in the Service Requests debug category.
|
||||
After a complete successful SR query (HTTP 200 with valid responses on all pages),
|
||||
its result is reused for subsequent Reference/product cycles in the current page
|
||||
session. Refresh all explicitly clears it. Failed pages are retried up to five
|
||||
@@ -150,12 +248,12 @@ SR snapshots are stored separately by update timestamp so changing Reference doe
|
||||
not overwrite a previous period's snapshot. Expired snapshots are removed on
|
||||
subsequent SR cache writes; Refresh all invalidates every snapshot.
|
||||
No credentials, request headers or debug envelopes are stored in this cache.
|
||||
Products loaded from cache restore matching activity entries without network calls.
|
||||
Missing, expired or mismatched entries are not treated as confirmed empty results;
|
||||
they wait for a real product refresh before a new activity query is allowed.
|
||||
Empty and entirely failed product cycles do not query activities. In mixed cycles,
|
||||
only fresh products permit activity API calls on cache misses; an already-loaded
|
||||
SR result is reused and associated with the new product update.
|
||||
Matching activity entries can be restored without network calls. Missing, expired
|
||||
or mismatched entries remain unknown until queried, and cache-miss activity
|
||||
lookups are allowed even when the products came from cache. A completed SR result
|
||||
is reused and can be associated with the current product update. Empty or entirely
|
||||
failed product cycles do not start product-dependent Actions; independently started
|
||||
SR loading does not depend on a successful product cycle.
|
||||
Activity lookups do not advance the existing Last update timestamp.
|
||||
Closing and reopening the modal preserves results and does not
|
||||
reload products or trigger these lookups. Already-running product requests may
|
||||
@@ -196,19 +294,33 @@ Workload Actions are queried in the background after the product cycle completes
|
||||
and only after SR has completed successfully (or was restored/reused). If SR is
|
||||
unavailable, Actions are not requested and remain unknown rather than absent.
|
||||
Each failed workload lookup gets up to five total attempts, stopping on success
|
||||
or when its session is superseded. Cached products still do not trigger network
|
||||
lookups. Each distinct `RevnId` uses `requestWlActions` with
|
||||
or when its session is superseded. Valid activity cache entries are reused;
|
||||
cache misses can trigger lookups for cached products. Each distinct `RevnId` uses `requestWlActions` with
|
||||
the `WWB-TS` credential in `Wwb-Provider-Authorization`. The Act badge beside SR
|
||||
aggregates all products: green means an action's `owner` matches the general
|
||||
tokenrelay response's `principal`; red means no matching owner was found. `Act ?`
|
||||
means ownership could not be confirmed (including a missing principal). Tooltips
|
||||
retain all returned actions, regardless of owner. Credentials stay in memory only;
|
||||
the principal is used to scope persisted activity entries.
|
||||
retain all returned actions, regardless of owner. The principal scopes persisted
|
||||
activity entries; this data cache excludes credentials and debug envelopes.
|
||||
Queries are shared per product cycle (up to four concurrently). Reference changes
|
||||
that load products from cache do not refresh activities.
|
||||
reuse matching activity data or load missing data as needed.
|
||||
Only the first page is requested for now; `hasNext` is indicated in the tooltip.
|
||||
The debug panel groups these requests under Actions, with credentials masked.
|
||||
|
||||
## Manage Time
|
||||
|
||||
Eligible users can open **Manage Time** once the SR session is ready. It restores
|
||||
the selected reference date, moves by seven days and preserves local week drafts
|
||||
while navigating within the modal. Service Request, Activity and Task Type use
|
||||
searchable dependent selections; Service and Non Service rows use their respective
|
||||
task types. Duplicate SR selections are rejected with row feedback.
|
||||
|
||||
Daily hours must be numeric and between 0 and 24 inclusive. Save creates new
|
||||
entries, updates changed saved entries and applies queued deletions. Deleting an
|
||||
unsaved row is local; deleting a saved row waits for Save. Partial failures retain
|
||||
unfinished work without repeating confirmed writes. Loading uses skeletons and
|
||||
errors expose retry. The feature is unavailable for SALES_REP.
|
||||
|
||||
## Build
|
||||
|
||||
Use Node.js:
|
||||
@@ -227,14 +339,12 @@ after updating; clear historical extension errors to check for new failures.
|
||||
Do not edit files under `dist` directly. Both targets use Manifest V3, with a
|
||||
Chromium service worker and Firefox background scripts. The build composes classic
|
||||
factory modules from `scripts/sources.cjs` into one isolated IIFE per execution
|
||||
context. It serializes `src/content/styles/redwood.css` followed by the scoped
|
||||
`src/features/debug/styles.css`, `src/features/opportunities/styles.css`,
|
||||
`src/features/install-base/styles.css`, `src/features/service-requests/styles.css`
|
||||
`src/features/consumption/plan-detail.css` and `src/features/ratecard/styles.css` at
|
||||
build time. There is no
|
||||
context. CSS is serialized at build time in the order defined by
|
||||
`scripts/compose.cjs`, including feature styles followed by shared table and modal
|
||||
overrides in `src/content/styles/tables.css` and `dialogs.css`. There is no
|
||||
runtime module loader, browser-side eval, ES-module requirement or new dependency.
|
||||
|
||||
## Tests and Maintenance
|
||||
## Customer Insights
|
||||
|
||||
Installed Base and Service Requests include a search input above their tables.
|
||||
Search filters loaded records across every displayed column, including raw and
|
||||
@@ -256,8 +366,12 @@ It uses the existing OCICONS-TS `uiaasHeader.value` in `G2m-Authorization` and i
|
||||
logged in the Consumption debug category with the existing credential masking.
|
||||
The eleven requested fields are displayed, including percentage discounts and
|
||||
USD prices with at least four decimal places. Search includes raw and formatted
|
||||
values; prices, quantities, percentages and dates sort by value. Only the drawer
|
||||
table scrolls, horizontally when its available width is below 1100px.
|
||||
values; prices, quantities, percentages and dates sort by value. An **Order Number**
|
||||
multiselect beside Search groups distinct order numbers and supports selecting all
|
||||
or several orders. Clicking one order while all are selected isolates that order.
|
||||
Order selections and text search combine locally.
|
||||
Shared table styles remove the old fixed minimum width, tighten cell spacing and
|
||||
allow multiword headers to wrap at word boundaries so the table fits the drawer.
|
||||
Closing the drawer, changing plans or closing Cloud Consumption discards late UI
|
||||
updates. Concurrent requests for the same plan are shared; reopening after completion
|
||||
fetches again. Errors remain local. No new persisted cache, permissions, token
|
||||
@@ -296,7 +410,8 @@ and formats status as a badge and dates using the existing date formatter.
|
||||
Debug contains a Service Requests category; credential headers are masked before
|
||||
delivery to content. This feature adds no permissions or authentication retries.
|
||||
|
||||
The Installed Base action sits beside customer consumption below Customer. It
|
||||
The Installed Base action sits beside customer consumption below Customer. The
|
||||
customer appears in its modal header rather than a repeated Customer column. It
|
||||
opens a skeleton dialog, then calls `requestAccountSummary` with ACCP-TS and uses
|
||||
the returned `registryId` in `requestInstallBase`. The latter uses the SAIB-TS
|
||||
`uiaasHeader.label` and `uiaasHeader.value`, and loads pages of 25 until `hasMore`
|
||||
@@ -306,15 +421,23 @@ headers in this flow are masked before delivery to the content script. No new
|
||||
cache, permissions or session recovery logic is introduced. Amounts use two
|
||||
decimal places without inferring a currency from the separate LC fields.
|
||||
|
||||
The opportunities table places product counts below Name and the customer
|
||||
consumption action below Customer, without a separate Actions column. Compact
|
||||
columns retain their values; Name and Customer share the remaining width while
|
||||
Owner is fixed at 132px. Both text cells reserve at least two text lines, and
|
||||
their controls stay anchored 10px above the row bottom, including while products
|
||||
load. Longer text can grow the row without overlapping controls. Horizontal
|
||||
scrolling is reserved for table containers below
|
||||
1120px. The scoped table stylesheet does not change product-table column widths
|
||||
or the existing light/dark colors.
|
||||
The opportunities table places product counts and badges below Name and customer
|
||||
actions below Customer. Their spacing is coordinated; longer names can grow the
|
||||
row without overlapping controls. Shared table and modal styles provide consistent
|
||||
titles, typography, borders, padding and loading skeletons in both themes.
|
||||
|
||||
## Debug Requests
|
||||
|
||||
Request records are persisted in page localStorage under a tab-specific namespace.
|
||||
Closing the main modal preserves them. The reset occurs immediately before the
|
||||
first `requestOpportunities` page of a new query; subsequent pages preserve that
|
||||
query's history. Requests logged before that reset, including its saved-search
|
||||
lookup, are removed by the same boundary.
|
||||
|
||||
The hidden debug panel does not prebuild request details. Opening it loads the
|
||||
summaries and expanding an entry constructs its details. Storage is updated in
|
||||
batches of changed records; quota or access failures retain the session's records
|
||||
in memory with explanatory feedback rather than interrupting API requests.
|
||||
|
||||
Product HTTP requests appear in Debug Requests (Ctrl+Shift+D) as soon as they start.
|
||||
Each entry identifies the opportunity and page offset, stays `running` while
|
||||
@@ -325,7 +448,8 @@ tab/frame; this change adds no timeout, retry or authentication behavior.
|
||||
|
||||
Debug Requests opens as a full-page view inside the extension using Ctrl+Shift+D, without
|
||||
opening a browser tab or entering native browser fullscreen. Close, Escape or Ctrl+Shift+D
|
||||
returns to the underlying view. Header/category navigation remains above the
|
||||
returns to the underlying view. Debug stays above other extension modals.
|
||||
Header/category navigation remains above the
|
||||
scrollable timeline; expanded details use two columns on wide screens and one on
|
||||
narrow screens. Theme-specific colors distinguish success, failure, running,
|
||||
HTTP methods/statuses, request/response sections and JSON tokens. Highlighting
|
||||
@@ -336,15 +460,20 @@ are captured in full, preserving indentation, highlighting and sensitive-field
|
||||
masking. Original sensitive values are retained for explicit reveal, including
|
||||
identity, tokenrelay and catalog tokens. Already incomplete
|
||||
or invalid JSON remains plain text. The visibility toggle retains its existing
|
||||
behavior. Focus, expansion and timeline scroll position survive log updates.
|
||||
behavior. This is display masking, not encryption or guaranteed redaction at rest:
|
||||
captured records can retain original sensitive values in localStorage. Focus,
|
||||
expansion and timeline scroll position survive log updates.
|
||||
|
||||
Debug tabs group Authentication, Opportunities, Products, AI, Consumption, Installed Base and Service Requests
|
||||
Debug tabs group Authentication, Opportunities, Contacts, Products, Consumption,
|
||||
Installed Base, Service Requests and Actions
|
||||
requests; unknown request types appear under Other. Only categories with entries
|
||||
are shown. All preserves the complete timeline. Every tab sorts by request start
|
||||
time, retaining original request IDs and showing start times in collapsed rows.
|
||||
Counts and running states update without changing the selected category or
|
||||
collapsing expanded details. Use arrow keys, Home and End to navigate the tabs.
|
||||
|
||||
## Tests and Maintenance
|
||||
|
||||
```bash
|
||||
npm test
|
||||
npm run check
|
||||
@@ -354,21 +483,25 @@ Tests use built-in Node.js modules and synthetic credentials, without real Fusio
|
||||
requests. The characterization suite verifies manifests, source/output equality,
|
||||
fiscal dates, payloads, preferences, pagination, cache/progress and both browser API
|
||||
styles. Architecture tests enforce source inclusion, explicit factory dependencies,
|
||||
isolated state and unchanged CSS. These complement consumption, session recovery
|
||||
and AI suites. `check` also fails if generated packages are stale.
|
||||
isolated state and unchanged CSS. These complement consumption, session recovery,
|
||||
organization-chart and Manage Time suites. `check` also fails if generated packages are stale.
|
||||
There is no separate lint configuration or runtime dependency installation.
|
||||
|
||||
See [architecture and contracts](docs/architecture.md) and the
|
||||
[incremental refactoring record](docs/refactoring.md) for execution boundaries,
|
||||
authentication, storage, known risks and verification limits.
|
||||
Mock-based tests do not replace testing the installed extension in each browser.
|
||||
Calendar week positioning, responsive tables, modal dragging and print pagination
|
||||
still need visual checks in installed browsers; synthetic tests alone do not
|
||||
certify those layouts or live Oracle authentication.
|
||||
|
||||
Without npm, run `node scripts/build.mjs`, `node scripts/test.cjs` and
|
||||
`node scripts/build.mjs --check`. Development checks were run with Node 24.19.0.
|
||||
`node scripts/build.mjs --check`. The documentation-baseline checks use Node 22.15.0;
|
||||
the build has no runtime dependency installation step.
|
||||
|
||||
For a local UI smoke test, run `node scripts/preview.mjs` and open the loopback URL
|
||||
printed by the command. The fixture uses synthetic opportunities, tokens, products,
|
||||
AI text and consumption; unexpected requests fail closed. It does not authenticate
|
||||
and consumption data; unexpected requests fail closed. It does not authenticate
|
||||
against Fusion or read real extension storage. `/consumption-trend.html` provides
|
||||
a focused chart fixture. Stop the server with Ctrl+C when finished.
|
||||
|
||||
@@ -394,4 +527,24 @@ a focused chart fixture. Stop the server with Ctrl+C when finished.
|
||||
|
||||
When it finds the `#yourapps_groupNode_sales` group, the extension adds the tile before the `.flat-grid-cell.flat-grid-cell-addicon` item. Clicking the tile opens the opportunities interface.
|
||||
|
||||
With the Opportunities Extension modal open, press Ctrl+Shift+F to choose a browser bookmarks folder and save the extension shortcut.
|
||||
Opening the saved shortcut ending in `#opportunities-extension` also opens the
|
||||
modal without clicking the Sales group. Its intent is captured before Fusion can
|
||||
rewrite the URL, then consumed once when the extension is ready.
|
||||
|
||||
## Favorites, Modal Interaction and Printing
|
||||
|
||||
With the main modal open, **Ctrl+Shift+F** opens a searchable browser bookmark
|
||||
folder picker. Choose the destination and Save; the extension uses the bookmarks
|
||||
API rather than the browser's native Add Favorite dialog. If the shortcut is not
|
||||
bookmarked, a prominent hint appears for 20 seconds and disappears immediately
|
||||
after saving. **Last update** remains the first header badge.
|
||||
|
||||
Non-full-page modals can be dragged from any noninteractive area of their title
|
||||
bar. Up to 70% of their width and height can move beyond the viewport; title-bar
|
||||
buttons keep their normal actions. Full-page views remain fixed.
|
||||
|
||||
The print icon beside **Booking** and **Workload** opens a report containing the
|
||||
current filters, counts, stage amounts and opportunity list. Unrestricted Customer
|
||||
and Owner selections are labeled **All customers** and **All owners**. The report
|
||||
requests A4 landscape with page margins and supports the browser's Print / Save PDF
|
||||
dialog. Browser print settings can override the requested orientation and paper.
|
||||
|
||||
Reference in New Issue
Block a user