Skip to content

feat(station-login): e911 Modal on Desktop Station Login#719

Open
brain-frog wants to merge 4 commits into
webex:nextfrom
brain-frog:CAI-7905
Open

feat(station-login): e911 Modal on Desktop Station Login#719
brain-frog wants to merge 4 commits into
webex:nextfrom
brain-frog:CAI-7905

Conversation

@brain-frog

Copy link
Copy Markdown
Contributor

COMPLETES # https://jira-eng-sjc12.cisco.com/jira/browse/CAI-7905

This pull request addresses

When a user does a "Desktop" station login in agent desktop there is supposed to be a modal asking them to fill out their emergency numbers and a value in user preferences that tracks if the modal has been acknowledged
< DESCRIBE THE CONTEXT OF THE ISSUE >

by making the following changes

Adding the modal and having it pop up in that use case
< DESCRIBE YOUR CHANGES >

https://app.vidcast.io/share/86714212-0e4c-4b4d-9173-6df14d7bf273?playerMode=vidcast

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios were tested

  • The testing is done with the amplify link
    < ENUMERATE TESTS PERFORMED, WHETHER MANUAL OR AUTOMATED >

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Please Specify
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

Checklist before merging

  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the testing document
  • I have tested the functionality with amplify link

Make sure to have followed the contributing guidelines before submitting.

Matthew Olker added 2 commits July 13, 2026 14:20
- Add E911 modal state and methods to store (showE911Modal, isEmergencyModalAlreadyDisplayed)
- Add User Preferences API types and interfaces for fetching/updating preferences
- Implement fetchUserPreferences and updateEmergencyModalAcknowledgment in store wrapper
- Create E911Modal presentational component with checkbox acknowledgment
- Integrate E911Modal into StationLogin widget
- Trigger E911 check after successful BROWSER login
- Add unit tests for E911Modal component and store methods
- Fix isEndTaskEnabled -> isEndCallEnabled typo in test fixtures

The modal displays for BROWSER login if user hasn't previously acknowledged.
User preferences are persisted via SDK userPreference service.

Note: User Preferences API requires SDK update (pending publish of 3.12.0-next.133)

Refs: CAI-7905
…xports

- Rename E911Modal.tsx to e911-modal.tsx for consistency with other files
- Remove index.ts barrel file, import component directly
- Update cc-components index.ts to use direct imports
@brain-frog
brain-frog requested a review from a team as a code owner July 15, 2026 15:11
@brain-frog brain-frog added the validated Indicates that the PR is ready for actions label Jul 15, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f023d32e1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

import React from 'react';
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
import '@testing-library/jest-dom';
import E911Modal from '../../../../src/components/StationLogin/E911Modal/E911Modal';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import the lower-case E911 modal module

The cc-components test script type-checks ./tests, but this import points to src/components/StationLogin/E911Modal/E911Modal; the only file added under that directory is e911-modal.tsx, so on the Linux/PnP workspace the unit suite fails module resolution before these tests can run. Use the actual lower-case module path.

Useful? React with 👍 / 👎.

<Checkbox
data-testid="e911-checkbox"
checked={isChecked}
onChange={handleCheckboxChange}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire the Momentum checkbox change event

For the Momentum Checkbox used elsewhere in this package, the handler is wired through the custom-element onchange prop (see consult-transfer-popover.tsx), not React's normalized onChange. With this wiring, a browser click on the E911 checkbox will not update isChecked, leaving Save & Continue disabled and preventing agents from acknowledging the modal.

Useful? React with 👍 / 👎.

Comment on lines +617 to +622
if (desktopPrefString) {
try {
const desktopPref = JSON.parse(desktopPrefString);
runInAction(() => {
this.store.isEmergencyModalAlreadyDisplayed = desktopPref.isEmergencyModalAlreadyDisplayed ?? false;
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reset the E911 preference when no desktop preference exists

When getUserPreference() returns no desktopPreference, this branch leaves isEmergencyModalAlreadyDisplayed at its previous value. Because the store is a singleton, after one BROWSER login sets the flag to true, a later agent/session with empty preferences can skip the E911 notification entirely; set the observable to false when the preference is missing or unparsable before checking whether to show the modal.

Useful? React with 👍 / 👎.

};

return (
<dialog ref={dialogRef} className="e911-modal" data-testid="e911-modal">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Sync native dialog closes back to the store

A native <dialog> can be closed with Escape, but this element has no close/cancel handler, so that path bypasses handleCancel: the browser hides the E911 modal without saving acknowledgment while showE911Modal remains true, and the effect will not reopen it because isOpen did not change. Add a close/cancel handler that calls the same cancel path or prevents native cancellation.

Useful? React with 👍 / 👎.

- Fix import path in e911-modal.test.tsx to match renamed component file
- Update yarn.lock
@github-actions github-actions Bot removed the validated Indicates that the PR is ready for actions label Jul 15, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5e205c18ad

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

module: 'storeEventsWrapper.ts',
method: 'fetchUserPreferences',
});
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid opening E911 when preferences cannot be saved

When cc.userPreference is absent (the service is typed optional and the public init({webex}) path can receive SDK instances without it), this early return makes fetchUserPreferences() resolve successfully while leaving the default isEmergencyModalAlreadyDisplayed = false. checkE911ModalDisplay() then opens the E911 modal, but updateEmergencyModalAcknowledgment() has the same early-return behavior, so Save & Continue silently leaves the modal open and cannot persist the acknowledgment; suppress the modal or surface a failure instead of treating this as an unchecked preference.

Useful? React with 👍 / 👎.

- Wire Momentum Checkbox via 'onchange' prop instead of React 'onChange'
  (custom element does not fire React's synthetic change event, leaving
  Save & Continue permanently disabled)
- Sync native dialog 'cancel' event (Escape key) back to onCancel so
  store state (showE911Modal) stays consistent with dialog visibility
- Reset isEmergencyModalAlreadyDisplayed to false whenever desktopPreference
  is missing/unparsable, instead of leaving the singleton's stale value,
  which could cause the modal to be skipped for a new agent/session
- Throw instead of silently resolving in fetchUserPreferences and
  updateEmergencyModalAcknowledgment when userPreference service is
  unavailable, so failures are surfaced instead of leaving the modal
  stuck open with no way to persist acknowledgment
- Add regression tests for native cancel handling and preference reset

Addresses review comments on PR webex#719

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 440fa9aef6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +658 to +660
const desktopPreference = JSON.stringify({
isEmergencyModalAlreadyDisplayed: true,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Merge the E911 flag into existing desktop preferences

In updateEmergencyModalAcknowledgment, when a user already has any other fields in desktopPreference, this constructs a brand-new JSON object and sends it as the full preference payload, so acknowledging E911 deletes those sibling settings from the persisted preference record. Since fetchUserPreferences already treats desktopPreference as a JSON object and only reads the E911 property, fetch/parse the current object and spread it before setting isEmergencyModalAlreadyDisplayed.

Useful? React with 👍 / 👎.

@akulakum akulakum added the validated Indicates that the PR is ready for actions label Jul 16, 2026

@cmullenx cmullenx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some comments and some of codex reviews need to be addressed as well

.e911-modal {
padding: 0;
border: none;
border-radius: 8px;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make sure to use rems and not px and momentum colors instead of hex codes and momentum fonts, i dont think you should have to add font weights

};

return (
<dialog ref={dialogRef} className="e911-modal" data-testid="e911-modal">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesnt momentum have a dialog component?


const checkE911ModalDisplay = async () => {
try {
if (deviceType !== 'BROWSER') {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should browser be a const?

@akulakum akulakum left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

station-login-spec.md — Spec not updated

Per repo spec-currency rules, the module spec should be updated in the same change.

Please add E911 modal requirements as new STATION-LOGIN-R-* entries in packages/contact-center/station-login/ai-docs/station-login-spec.md, including:

  • Trigger conditions
  • Persistence via desktopPreference
  • Cancel/dismiss behavior

…and map them to the new tests.

<Text tagname="p" type="body-midsize-regular" className="e911-warning-message">
{E911ModalLabels.WARNING_MESSAGE}
</Text>
<a href="#" className="e911-help-link" data-testid="e911-help-link">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "See help section" link uses href="#", which doesn't navigate anywhere and can cause a page jump.

Please either:

  • Wire a real help URL (via prop or constant), or
  • Remove the link until a destination is available

}
};

const checkE911ModalDisplay = async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Store and modal component are well covered, but checkE911ModalDisplay() has no unit tests.

Please add tests in tests/helper.ts for:

  • Modal shown on successful BROWSER login when isEmergencyModalAlreadyDisplayed is false
  • Modal skipped for non-BROWSER device types (EXTENSION, AGENT_DN, etc.)
  • Modal skipped when preference is already acknowledged
  • Graceful handling when fetchUserPreferences() fails (error logged, modal not shown)

};

return <StationLoginComponent {...props} />;
const handleE911SaveAndContinue = async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If updateEmergencyModalAcknowledgment() fails, the error is only logged — the modal stays open with no user feedback.

Consider showing:

  • Inline error text on the modal, or
  • A toast notification

…so the agent knows Save failed and can retry.

setLoginSuccess(res);
setLoginFailure(undefined);

checkE911ModalDisplay();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two product-behavior questions to confirm:


Trigger scope

checkE911ModalDisplay() only runs in the stationLogin() success callback. It won't fire on:

  • Page refresh when already logged in with BROWSER
  • AGENT_STATION_LOGIN_SUCCESS / relogin events
  • Switching to BROWSER via profile save while logged in

Is that intentional, or should those paths also show the modal?


Cancel / dismiss

Cancel, X, and Escape close the modal without persisting acknowledgment — the agent stays logged in and can place calls.

Is that acceptable for E911 compliance, or should dismiss block calls / require logout until acknowledged?

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

Labels

validated Indicates that the PR is ready for actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants