15 KiB
ingress-ui Specification
Purpose
The Ingress page: the list of ingress definitions with summary tiles, filters, search and live refresh; the Ingress detail page is locked in CE.
Requirements
Requirement: Ingress page URL state
Edition: CE. /ingress SHALL read its whole state from the query parameters status, inputType, q, from, to,
tz, sort, order, cursor and limit as the shell's URL-state rules describe; sort accepts createdAt,
totalDuration, sessions and lastSession; invalid values fall back silently, and so does a metric sort with a range
wider than the ranked-sort limit, which falls back to createdAt.
Scenario: Deep link reproduces the view
- GIVEN
/ingress?status=publishing&inputType=rtmp&q=cam&from=now-7d&to=now&tz=UTC&order=asc&limit=50 - WHEN it is opened in a new browser session
- THEN the search box reads
cam, the input select shows RTMP, the status select shows Publishing, the range picker shows the 7-day preset in UTC, the table is sorted by Created ascending and shows 50 rows
Scenario: Metric sort deep link
- GIVEN
/ingress?sort=lastSession&from=now-24h&to=now - WHEN it is opened
- THEN the table is sorted by Last session descending and the Last session header shows the sort
Scenario: Metric sort beyond the limit
- GIVEN
/ingress?sort=sessions&from=now-30d&to=nowand the default 7-day limit - WHEN it is opened
- THEN the table is sorted by Created descending, the Sessions header is disabled with its tooltip and no list
request carries
sort=sessions
Scenario: Filter change drops the cursor
- GIVEN the list on its third page
- WHEN the user selects the WHIP input type
- THEN the URL has
inputType=whip, nocursor, and Back returns to the third page
Scenario: Defaults
- WHEN
/ingressopens without query parameters - THEN it uses every status and input type,
sort=createdAt,order=desc, the global range and the stored page size
Scenario: Any state change drops the cursor
- GIVEN
/ingresswith acursorin the URL - WHEN a filter, the search, the range, the sort or the page size changes
- THEN
cursoris dropped and a history entry is created
Requirement: Ingress summary tiles
Edition: CE. The Ingress page SHALL show four KPI tiles from the summary endpoint above the filters: Publishing now, Ingress in range (with the input type breakdown as hint), Sessions in range and Total duration; approximate values carry a tooltip saying the numbers are hour-aligned; tiles keep their value while the list reloads or fails.
Scenario: Tiles of a range
- GIVEN the summary answers
{ publishingNow: 2, ingressesInRange: 5, byInputType: { rtmp: 3, whip: 2, url: 0 }, sessionsInRange: 12, totalDurationMs: 21600000, approximate: true } - WHEN the tiles render
- THEN they read "Publishing now 2", "Ingress in range 5" with hint "RTMP 3 · WHIP 2 · URL 0", "Sessions in range 12" and "Total duration 6 h 00 m", the last two with the approximate tooltip
Scenario: Failed list keeps the tiles
- GIVEN tiles already rendered
- WHEN the list request fails
- THEN the tiles keep their values and the error banner appears over the table only
Requirement: Status and input type filters
Edition: CE. The Ingress page SHALL offer, after the search box and in this order, an input type select (All, RTMP,
WHIP, URL) bound to inputType and a status select (All, Publishing, Buffering, Idle, Error, Complete, Deleted)
bound to status; both write the URL on change and show their current value from the URL.
Scenario: Filter order
- WHEN the Ingress page renders
- THEN the filter bar reads, from the start, the search box labelled "Ingress name or ID", Input and Status
Scenario: Status select writes the URL
- WHEN the user selects Idle
- THEN the URL has
status=inactiveand the table shows idle ingresses only
Scenario: Labels map to statuses
- GIVEN
?status=inactive - WHEN the page renders
- THEN the status select shows Idle
Requirement: Ingress search
Edition: CE. The Ingress page SHALL offer the shared list search box labelled "Ingress name or ID" for an ingress name
prefix or an IN_ ID, which writes q after a 300 ms debounce, shows the hint "Type at least 2 characters" and
writes nothing on one character, shows the hint "Exact ID: range and filters ignored · Enter opens it" on an exact
IN_ ID, and opens that ingress with the current range when Enter is pressed on it.
Scenario: Prefix search
- WHEN the user types
ca - THEN after 300 ms the URL has
q=ca, nocursor, and the table shows the matching ingresses
Scenario: Exact id
- GIVEN
?status=publishing - WHEN the user types
IN_ab12cd - THEN the URL has
q=IN_ab12cd, the table shows that single ingress whatever its status and the hint reads "Exact ID: range and filters ignored · Enter opens it"
Scenario: Enter on an exact id
- GIVEN the search box holds
IN_ab12cd - WHEN the user presses Enter
- THEN
/ingress/IN_ab12cdopens with the currentfrom,toandtz
Scenario: One character
- WHEN the user types
c - THEN no request is sent and the hint reads "Type at least 2 characters"
Requirement: Ingress table
Edition: CE. The Ingress table SHALL render, in this order, the columns Ingress ID, Name, Room, Input, Status, Created (sortable, default desc), Total duration (sortable), Sessions (sortable) and Last session (sortable); Ingress ID, Status and Created cannot be hidden, Created and Last session carry the time-zone header hint, and narrow widths use the card layout.
Scenario: Publishing row
- GIVEN a reusable RTMP ingress
cam-1publishing intodemo-roomwith 3 sessions - WHEN the row renders
- THEN it shows, in order,
IN_c3d4once, as a link to/ingress/IN_c3d4with its copy button,cam-1with its copy button,demo-roomlinking to/rooms?q=demo-room, the "RTMP" badge, the publishing badge without a live chip, the creation time, the total duration counting up every second,3and the last session time
Scenario: Deleted row
- GIVEN an ingress with
status: "deleted" - WHEN the row renders
- THEN the status cell shows the neutral "deleted" status badge with the deletion time in its tooltip
Scenario: Idle ingress with an error
- GIVEN an ingress with
status: "inactive"andhasError: true - WHEN the row renders
- THEN the status cell shows the "idle" badge in the neutral colour with the error icon and the tooltip "Last session ended with an error"
Scenario: Disabled ingress
- GIVEN an idle ingress with
enabled: false - WHEN the row renders
- THEN the status cell shows the "idle" badge followed by a "disabled" badge in the same badge style, not plain text
Scenario: Never used
- GIVEN an ingress with
sessions: 0and nolastSessionAt - WHEN the row renders
- THEN Sessions reads
0, Total duration reads—and Last session reads—
Scenario: Columns
- WHEN the Ingress table renders a row
- THEN Ingress ID links to the detail with a copy button, Name has a copy button ("—" without a name), Room links to
/rooms?q=<roomName>carrying the range, Input shows the kind badge, Status shows the status badge, idle in the neutral colour and deleted with the deletion time in its tooltip, followed by the error icon whenhasErrorand a "disabled" badge when not enabled, and Total duration counts up live while a session runs
Requirement: Ingress pagination
Edition: CE. The Ingress page SHALL use the cursor paginator with Prev/Next bound to prevCursor/nextCursor, the page
size select bound to limit (10, 25, 50, 100) and "Showing x–y of total" when total is present, and hide the
paginator while the first page is empty.
Scenario: Next page
- GIVEN the first page of 25 with
nextCursorset - WHEN the user clicks Next
- THEN the URL has that
cursor, the table shows rows 26-50 and the paginator reads "Showing 26–50 of 60"
Scenario: Long range without total
- GIVEN
?from=now-30d - WHEN the page renders
- THEN the paginator reads "Showing 1–25" without a total
Scenario: Empty first page
- GIVEN a filter that matches no ingress
- WHEN the list answers no items
- THEN the empty state is shown and no paginator is rendered under it
Requirement: Ingress live refresh
Edition: CE. The Ingress page SHALL be a live view following the shell's auto-refresh policy (default 10 s): each tick reloads the summary and the current page in place; publishing rows are told by their status badge, without a live chip; refresh pauses while the tab is hidden and skips ticks while a request is in flight.
Scenario: In-place refresh
- GIVEN the list showing 25 ingresses with the scroll at row 20
- WHEN a refresh completes with a session count changed on one row
- THEN the rows update without skeletons, the scroll position is kept and no row flashes
Scenario: Session ends during refresh
- GIVEN a row with the publishing badge
- WHEN a refresh returns that ingress as
inactive - THEN the status badge reads "idle" in the neutral colour and its Total duration stops counting up
Requirement: Ingress page states
Edition: CE. The Ingress page SHALL show skeleton rows equal to the page size only until the first response, keep the rows or the empty state on screen during a refresh, show the shared list empty state "No ingress match" when no row matches, "Ingress was not found" with "Clear search" when an exact ingress ID finds nothing, and the error banner with retry and request id while keeping the previous rows when a load fails.
Scenario: Empty filtered list
- GIVEN
?status=error&q=zzz - WHEN the list answers no items
- THEN the empty state reads "No ingress match" and offers "Clear filters" (removes
status,inputTypeandq) and "Widen range" (opens the range picker)
Scenario: Unknown ingress id
- GIVEN the user searches
IN_missing - WHEN the list answers no items
- THEN the page reads "Ingress IN_missing was not found" with "Clear search", which empties the search box and
drops
q
Scenario: Failed refresh
- GIVEN rows from the previous load
- WHEN the next request fails with
500 - THEN the rows stay visible under the error banner showing the
X-Request-Idand a Retry action
Scenario: No match hint and actions
- WHEN no row matches
- THEN the shared list empty state "No ingress match" shows the hint "Change the filters or widen the time range." and the actions "Clear filters" and "Widen range"
Requirement: Ingress detail route and CE lock
Edition: CE. /ingress/:ingressId SHALL be registered in CE as a timed route that is not range-scoped and declares the
feature ingress-detail, and in CE render the full-page lock over a dimmed silhouette of three tiles and one block,
under the breadcrumbs and a header holding only the title (the name, or the ID without one) with its copy button and
the status badge; the header has no refresh control and no PRO endpoint is called.
Scenario: Locked from the list
- GIVEN CE and the user follows the
IN_c3d4link from the list - WHEN the page renders
- THEN the breadcrumbs read
Ingress / IN_c3d4, the title readscam-1with its copy button followed by the status badge from the list data, no input badge, facts or refresh control are shown, the lock card reads "Ingress detail is available in OpenVidu PRO" with "Learn about OpenVidu PRO" and "Back to ingress", and no request to/api/v1/ingresses/IN_c3d4is sent
Scenario: Locked deep link
- GIVEN CE and
/ingress/IN_c3d4opened directly - WHEN the page renders
- THEN the header is filled from
GET /api/v1/ingresses?q=IN_c3d4and the lock card is shown
Scenario: Ingress without name
- GIVEN CE and an ingress
IN_c3d4without name - WHEN the locked page renders
- THEN the title reads
IN_c3d4with its copy button
Scenario: Header data source
- GIVEN CE and the locked page of
IN_c3d4 - WHEN its header renders
- THEN the header is filled from the list cache or, when the cache has no entry, from
GET /api/v1/ingresses?q=IN_c3d4
Requirement: Ingress range by activity
Edition: CE. With a range, the Ingress list SHALL hold the ingress created in it, the ingress whose last session started in it, and the ingress publishing now that were created before its end, so an ingress created long before the range that streamed inside it is listed.
Scenario: Old ingress used in the range
- GIVEN the last 24 h, ingress
cam-1created 10 days ago whose last session started 2 hours ago and has ended, ingresscam-2created 30 days ago and publishing since 3 days ago, and ingresscam-3created 5 days ago and unused since - WHEN the list loads
- THEN it holds
cam-1andcam-2, and notcam-3
Scenario: Ingress created in the range
- GIVEN the last 24 h and an ingress created an hour ago that never published
- WHEN the list loads
- THEN the ingress is listed with Sessions
0
Requirement: Ingress sort keys
Edition: CE. The ingress table SHALL sort by Created (sort=createdAt, the default, newest first, for any range),
Total duration (sort=totalDuration, the running session included), Sessions (sort=sessions) or Last session
(sort=lastSession), in the order the header toggles; the three metric sorts rank the ingress of the range with
their values at the first page's request time, which the cursor keeps for the following pages.
Scenario: Sort by total duration
- GIVEN the Ingress page on the default 24 h range with a publishing ingress
- WHEN the user activates the Total duration header
- THEN the URL has
sort=totalDurationandorder=descwithoutcursor, and the publishing ingress is placed by its stored total plus the time its running session has been publishing
Scenario: Next page keeps the ranking
- GIVEN the list sorted by Total duration with a publishing ingress on the first page
- WHEN the user presses Next a minute later
- THEN the second page continues the ranking of the first page and no row of the first page reappears
Scenario: Created on a long range
- GIVEN
from=now-90d&to=now - WHEN the user toggles the Created header
- THEN the list is sorted by Created ascending, whatever the length of the range
Requirement: Ingress ranked sort limit
Edition: CE. While the resolved range is wider than the ranked-sort limit of GET /info
(limits.rankedSortMaxRangeMs, 7 days by default), the Total duration, Sessions and Last session headers, and their
options in the sort select of the card layout, SHALL be disabled with the tooltip "Narrow the range to to
sort by "; Created SHALL stay sortable for any range.
Scenario: Thirty-day range
- GIVEN
from=now-30d&to=nowand the default limit - WHEN the user hovers or focuses the Sessions header
- THEN the header is disabled and its tooltip reads "Narrow the range to to sort by Sessions", with naming the 7-day limit, while the Created header toggles the order