What this is
This is an OX.DH demonstration of the OX. waiting room browser-based video consultation platform, in the Cardiff and Vale University Health Board (CAVUHB) house style. It reproduces the public video consultation page and the full patient journey, so the experience can be shown to evaluators without a live clinical service.
Everything runs in a single self-contained HTML file. No patient data is sent anywhere and no real consultation takes place. The OX.DH Demo watermark sits behind every screen.
How the patient journey works
1. Waiting rooms. The front page lists every CAVUHB service alphabetically. Selecting one starts the journey.
2. Validate Access. The patient confirms they want to proceed.
3. Details. The patient enters the details configured for that service. Name, country code and phone are always asked; date of birth, email, OTP verification and an additional-information box appear only if enabled for that waiting room.
4. Terms and Conditions. The bilingual Welsh and English terms are shown and must be accepted.
5. Waiting room. The patient waits to be admitted. The prominent message tells them a team member will admit them shortly. They can test their audio, video and connection, read any signposting links, watch any configured video, and hear any configured audio, with the microphone in its configured entry state. On admission the OX. waiting room join link opens, carrying the collected patient data if configured.
Testing audio, video and connection
On the details step (before joining) and in the waiting room, the patient can test their audio, video and connection. The test shows a camera preview and a microphone level bar, and checks the connection to the OX.wr service (Azure Communication Services). The browser asks for camera and microphone permission the first time.
Prompts, OTP and validation
- Email, DoB, Additional info are per-service prompt toggles in the table. OTP verification is turned on by ticking OTP SMS and/or OTP email — there is no separate OTP column.
- Name, phone, date of birth and email are validated. The phone must be 7 to 15 digits, the date of birth (when asked) must be a real date not in the future, and the email must be a valid address before the patient can join.
- OTP delivery can be by SMS, email, or both. Where both are enabled the patient chooses. For this demo the accepted code is 0000.
- OTP is enabled by its delivery channel. Tick OTP SMS and/or OTP email to require one-time-code verification for a Waiting Room — that is all that is needed.
Languages (Welsh, English and more)
The patient journey is multilingual. Out of the box every waiting room offers English and Welsh together, plus Italian, Polish, French and German — the whole journey (validate, details, terms, waiting and the end-of-consultation message) is translated.
- Per waiting room. Open a room's Notes & description (the ⋮ button on the row, or right-click on desktop) and tick the languages it should offer. Choose both/all together to stack the languages bilingually, or let the patient pick one.
- Language picker. When a room offers more than one language, a picker appears at the top of the patient journey; the patient can switch to a single language or view them together (“All languages”).
- Default for every device. The multilingual default is built in, so the languages appear even on a device that has never loaded a saved configuration (e.g. a patient's phone). Translations come from the shipped
oxwr_i18n.json; English is always the fallback.
- Edit wording / add a language. In the config toolbar, 🌐 Languages & wording opens an editor for the patient-facing text per language (English shows as the placeholder). You can also add a new language. Changes preview immediately; Save keeps them on this device, and Save to server publishes both the wording and the language selection to everyone — no redeploy.
On a phone
On small screens the right-hand tabs (Configure, Group sessions, Teams test, Help) collapse behind a ☰ menu button in the top-right, so they never cover the patient's form. Tap ☰ to reach them.
Per-waiting-room columns
Every option is a column on the service's own row, so each waiting room is configured in one place. Each row has a ⋮ options button (and right-click on desktop) for Notes & description, Clone, Draft and Delete. The OX.wr join URL and Audio URL now live inside Notes & description (⋮ → Notes) to keep the main grid uncluttered; a 🔗 marker on the row name shows when a custom join URL is set.
- Group. Marks the waiting room as a shared group session. An individual (non-group) room creates a new appointment for each patient who joins; a group room puts every patient who clicks the link into the same waiting room, and each is recorded as a participant. See "Group consultations" below.
- Email, DoB, Add. info. The details the patient is prompted for. DoB asks the patient for their date of birth on the details step. (OTP verification is enabled via the OTP SMS / OTP email columns.)
- OTP SMS, OTP email. How the one-time code is delivered when OTP is enabled. Either or both.
- Mute entry. Sets the patient's default microphone state on reaching the waiting room.
- Pass data. Appends the details the patient entered, as JSON, to the join link. The parameter name is set in the toolbar (default
patientData).
- Debug. When on, the waiting room shows testing detail: the collected summary, the join URL and JSON, a diagnostics panel (session type, configured link, whether Pass data is on, the final launch URL, plus warnings — e.g. when a short link may drop the
patientData query), an Open configured link only button that opens the link without patientData, a Copy diagnostics button, and a live debug log that records each “Enter waiting room” click, whether a pop-up was blocked, and any JavaScript errors. When off, the patient sees a clean waiting room. Off by default.
- Draft. When on, the Waiting Room is hidden from the published front page until it is published (draft unticked). Drafts still appear in this configuration table with a DRAFT tag.
- Video URLs. One or more video links, separated by a comma or semicolon, shown to the patient on entry. A YouTube link embeds where possible; when the file is opened directly from disk (file://) YouTube is shown as a click-to-open link instead, which avoids the browser security error. A direct media file plays inline. Anything else is shown as a click-to-open link.
- Audio URL. An audio file that starts playing when the patient enters the waiting room. The patient can pause or play it. Type the word
demo to use a built-in sample that plays anywhere, including when the file is opened directly from disk. For your own audio when opening from disk (file://), put the file in the same folder as this page and enter just its file name; audio hosted online may be blocked by the browser until the demo is served over http(s).
- Signposting. One or more links to documents or websites, separated by a comma or semicolon, that the patient can read while waiting. Clicking one shows a reminder that it opens in a separate window and to be ready to return, then opens it in a smaller window (a new tab on some mobile devices) so the waiting room stays open behind it.
- Waiting message. An optional message shown while the patient waits.
Group consultations
A group session lets many patients join one shared waiting room, rather than each patient getting their own appointment. Tick Group on a waiting room (or the Group session default in the toolbar) to turn it into a group session. Group rooms show a GROUP tag on the front page and in the config table.
- Patient side. The patient journey is the same for single and group rooms (validate → details → terms) and only branches at the join. For a group room the patient then sees a picker of today's published group sessions for that service (e.g. a 19:30 and a 20:30 session), with the session starting soonest highlighted; the Status and patient Name are not shown. They choose which session to attend and join it. If no group sessions are set up for the current day, a message (in the patient's chosen language) says so. Their details are still recorded as a participant. The list comes from the live group-sessions endpoint when configured (
group.sessionsUrl, filtered to appointment type 102 and doctor status Accepted/Arrived); with none configured the demo shows example sessions (toggle Demo group sessions in Configure to see the empty state).
- What is recorded. Each patient becomes a participant record shaped like the backend's
bcrm_groupparticipant (name, mobile, email, status, joined time) plus a bcrm_participantdata JSON blob holding everything they entered at join — date of birth, notes and the verification result. This is the JSON captured for the clinician.
- Clinician side — the Group sessions console. Open 👥 Group sessions on the right. Pick a session to see its fixed join URL and a live list of everyone who has joined, with their captured JSON, and an Admit action per patient (Waiting → Admitted). You can export all participants as JSON or clear the session.
- Try it. Make a room a group room and save, open its join URL (or click it on the front page) in two or three browser tabs and complete the details each time, then watch them all appear in the same waiting room and in the Group sessions console. Admitting a patient in the console updates their waiting screen.
- Individual rooms are unchanged. Leave Group unticked and the room behaves exactly as before — one appointment per patient.
Scheduling a group session in Teams (current method)
The sessions the patient picker shows are not created here — OX.wr only lists the group sessions that already exist for the day. A scheduled group session is created in the clinical/booking system, which provisions the Microsoft Teams meeting. Today the flow is:
- Create the group appointment in OX.vc. In the OX.vc booking system open the Group sessions area, choose the service (e.g.
Assessment or CovidV2), set the date and time, and assign the clinician who will host. Saving it creates a group appointment — appointmentType = 102 (Group), doctorStatus = Accepted.
- The Teams meeting is provisioned automatically. When the group appointment is created the backend books a Microsoft Teams meeting for it and stores that meeting's join URL on the appointment (
teamsURL / bcrm_teamsurl). If a clinician instead schedules the Teams meeting themselves (in Teams or Outlook — a normal scheduled meeting or a channel meeting), its join link is attached to the group appointment the same way.
- OX.wr lists it automatically. Any waiting room here that is marked Group and named the same as that service (the room name must match the service, e.g.
Assessment, CovidV2) reads the day's sessions from GetAllCrmAppointmentsByDates (group.sessionsUrl) — filtered to type 102, Accepted/Arrived — and shows them in the patient picker, soonest first.
- Joining. When the patient picks a session, OX.wr records them on that appointment (
AddParticipantInAppointment, using the details already collected — a placeholder e-mail is generated if none was given) and opens the session's real Teams meeting through the ACS join wrapper. Everyone who picked that session lands in the same Teams call.
In short: schedule in OX.vc / Teams → appears in OX.wr. Marking a room Group here only tells OX.wr to show the picker for that service; it does not create the meeting.
Descriptions, deleting rooms & the join button
- Description. Right-click a row (or use its menu) and choose Notes & description. The description is a longer, patient-facing text shown on the waiting screen under the service name; notes stay internal. Both save with the configuration and export in the JSON (a room's
description).
- Delete a waiting room. Each config row has a 🗑 button (also on the right-click menu). Deleting a room you created removes it; deleting a built-in room hides it (re-import a config or Reset to bring it back). Deletions are remembered in the config's
removed list.
- Enter waiting room button. On the waiting screen the join button now sits near the top, right under the service name, so it is easy to reach.
Teams meeting test (ACS)
The 🧪 Teams test tab joins a Microsoft Teams meeting from this page using Azure Communication Services (ACS), mirroring the Microsoft quickstart “Join your calling app to a Teams meeting”. It lets you enter a waiting room as the patient would — over ACS — without a separate app. The ACS SDK loads on demand from a CDN, so this page needs internet access; if it is opened straight from disk and the browser blocks the cross-origin module load, serve the file over http(s).
Step-by-step — test a waiting room end to end:
- Open the tab. Press 🧪 Teams test on the right (on a phone it is behind the ☰ menu, top-right).
- Step 1 — Create the waiting room. Choose a room in “— pick a waiting room —”, then press ➕ Create waiting room & load parameters.
- For an individual room this calls the same backend the patient journey uses —
CheckAndCreatePatient → CreateTentativeAppointment — and auto-fills the two things needed to join: the ACS user access token and the appointment's Teams meeting join link (bcrm_teamsurl, returned in the appointment's responseMessage).
- For a group room it calls
GetAllCrmAppointmentsByDates and lists today's published group sessions (each with its JSON); pick one to use its real Teams link.
- The Log shows the full response so you can see exactly which field carries the link. This step needs the live backend — with no access to it, skip to Step 2 and paste an ACS token and a Teams link by hand.
- Step 2 — Initialise, then enter. Press 1 · Initialise to ready the call agent, then 2 · Enter Waiting Room to join the lobby as the patient. Grant camera/microphone when the browser asks. You are then admitted just like a real patient.
- In the call. Use the in-call controls below to try mute, camera, chat, live captions and the rest.
Tip. Any waiting room that is Teams-enabled on its D365 service record (a Teams meeting/channel, or a Teams join link) can be tested — it does not have to be shown in the patient directory. Teams-only rooms stay pickable here even when they are hidden from the public A–Z list.
Show the call inline on the patient page (optional, parallel to the existing path). The ACS call can be shown on the patient waiting page, above the signposting and videos, so the patient watches the material while waiting to be admitted — instead of the right-hand split panel. Turn it on per waiting room in ⋮ → Notes & description → Patient join method (only that room is affected; all others keep the existing OX. waiting room path). For quick tests you can also add ?acs=inline to the URL (session-only, all rooms) or set acs.inlineJoin: true in the config (all rooms). It reuses the same engine and is fully reversible.
In-call controls. The patient joins as an attendee (an anonymous participant admitted from the lobby, with no organiser or presenter role) using the default camera, microphone and speaker. Once joined, the tab shows the same controls as the patient app: device selection; mute and camera on/off; reactions; raise hand; present (screen share); a more menu with hold, live captions and layout (Dynamic, Speaker, Gallery); a participant list; and the meeting chat. Live captions are shown large and high-contrast, and where the meeting offers it a Translate to language can be chosen so captions appear in the patient's language. A clinician's shared screen is shown on a large stage; when the patient presents, a clear banner and a one-click Stop presenting control are shown. These run on the Azure Communication Services calling SDK in the browser, so this lightweight tab can stand in for the separate ACS app. Availability of individual controls depends on the meeting and the SDK build; the Log records anything unsupported. (Meeting chat additionally needs the ACS resource endpoint, either returned by the token service or set as acs.endpoint in the configuration.)
Notes, new and cloned waiting rooms
- Tap the ⋮ button on any row (or right-click the row on desktop) for a menu: Notes & description for that Waiting Room (which also holds its join URL, audio URL and languages), clone it, toggle draft, or delete it (created rooms only). The ⋮ button is the reliable option on phones, where long-press does not open the browser context menu. A row with notes shows a small pencil next to its name.
- + New waiting room creates a room from scratch. Clone copies an existing room's settings. New and cloned rooms start as draft so they do not appear on the published page until you publish them.
Defaults, saving and JSON
- The toolbar sets the defaults for prompts, OTP delivery and waiting-room behaviour. Apply defaults to all services copies them onto every row.
- Save keeps settings in this browser. Export JSON downloads the full configuration, which lists every waiting room shown on the landing page; Import JSON loads it back. View/Edit JSON shows the whole configuration, with a search box and a Single waiting room mode for editing one room at a time. Set
"draft": true on a room to hide it from the landing page, or add an entry with "custom": true to add one. Reset returns per-service settings to the defaults while keeping custom rooms and notes.
Finding a waiting room
Patients can use the search box above the A to Z list on the landing page to find a waiting room by name. The list filters as they type.
Powered by
![OX. Digital Health]()
![OX. waiting room]()