Skip to content

fix(signage-manager): fix playlist approval, adding media and status - #535

Merged
MrYuion merged 2 commits into
developfrom
fix/signage-manager-playlists
Oct 2, 2026
Merged

MrYuion merged 2 commits into
developfrom
fix/signage-manager-playlists

Conversation

@MrYuion

@MrYuion MrYuion commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

On the playlists page and its modals:

  • Wrong add: adding media to an unloaded distribution playlist sent a raw media id where a schedule-item id was expected.
  • Approval state: selecting a playlist dropped its pending approval request, so a duplicate request was possible.
  • Cleared dates: clearing valid_until was never sent, so expired playlists stayed expired.
  • Approve: it approved the latest revision, not the one reviewed.
  • Silent failures: add-media and item-load failures showed nothing.
  • Status badges: four copies of getStatus disagreed on expiry and wording.
  • Keyboard: items could only be reordered by dragging.
  • Animation: the backend returns indexes, and ts-client turns Default (0) into Cut, so saving could silently change a playlist's animation.

Changes

  • Distribution check: fetches a playlist by id when it is not loaded. Add-media errors notify and return false.
  • Approval state: _setPlaylistMediaState keeps the server's approval_requested.
  • Dates: cleared validity dates send null.
  • Approve: re-checks the revision before approving, and warns and reloads if it changed.
  • Item loading: the resource's own isLoading/error, with <load-error> and Retry. Details shows "—" on error.
  • Deep links: wait for the first page; a failed load warns and clears the selection.
  • Status: one playlistStatus helper for the playlist list, media sidebar, zone and display lists, with one label.
  • Keyboard: Move up/down in the item menu. Row key handlers no longer block controls inside the row.
  • Animation: playlistAnimation() reads ts-client's 'cut' as Default and maps indexes. The modal sends default_animation only when it changes. Options use MediaAnimation names. The S hotkey does not save while a dropdown has focus.
  • Cleanup: shared formatters deduplicated, plus [(ngModel)] and types.

Testing

  • Unit tests for each fix. Each fails without its fix.
  • nx test signage-manager (1001) and nx build signage-manager pass.
  • Local PlaceOS stack: deep links; distribution add via search; add errors; awaiting review kept; approve after a change; cleared dates; item errors and quick switching; keyboard reorder; ended schedules shown as Expired; Default/Cut/Cross Fade round-trip and duplicate.

Notes

  • Upstream ts-client: SignagePlaylist should use data.default_animation ?? MediaAnimation.Cut. After that, playlistAnimation can become a plain index lookup.
  • Shared formatter: playlist-schedule-form still has its own copy of the old no-schedule fallback; it should use the export from fix(signage-manager): match schedule conflicts to the player #537 after both merge.

Independent of the other signage PRs from this review. Based on develop.


Changes made by Claude Opus 5.5 (1M context) in Claude Code, running in T3 Code.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Oct 2, 2026

Copy link
Copy Markdown

Deployment failed for project frontend-templates with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/placeos?upgradeToPro=build-rate-limit

@greptile-apps

greptile-apps Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Fixes playlist approval workflow with media and status display.

The PR is not yet safe to merge because approval can still apply to a revision the reviewer did not see.

Findings

  1. P1 Unseen revision gets approved ▶

Summary

This PR updates playlist adds, approvals, status badges, item controls, and playlist editing in the signage manager. It also makes linked playlists and failed item loads easier to handle, and keeps saved animation choices consistent.

  • Distribution playlists are fetched before media is added, and add failures are shown.
  • Approval checks the revision being reviewed, while status badges use shared rules.
  • Playlist items can be moved with the keyboard, and failed loads can be retried.
  • Cleared dates and saved animation settings are handled in playlist editing.

Reviews (2) · Last reviewed commit: "fix(signage-manager): retry the failed p..."

Comment on lines +215 to +222
if (await playlistChangedSince(playlist_id, shown)) {
notifyWarn(
i18n('SIGNAGE_MANAGER.PLAYLIST_CHANGED_BEFORE_APPROVAL'),
);
this._playlist_versions.reload();
return;
}
await approveSignagePlaylist(playlist_id);

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 Unseen revision gets approved

If someone saves a new media revision after playlistChangedSince() returns but before approveSignagePlaylist() runs, the server can approve media the reviewer never saw. The check and approval are separate requests. Tie approval to the revision shown in the preview.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This can't be fully closed in the app; the API has no way to name the revision. ts-client's approveSignagePlaylist(id) is a bare POST /signage/playlists/{id}/media/approve, and its docs say it approves the latest revision. The modal (playlist-approve-modal.component.ts:215) fetches the latest revision just before approving and compares its id and updated_at with the one in the preview; if they differ, it warns and does not approve. What remains is one round trip, between that check and the approve request. A full fix needs the server to accept the revision being approved (a revision_id, or an If-Match/updated_at precondition answered with 409/412), with a matching ts-client argument.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You're right: with the current bare approveSignagePlaylist(id) endpoint, the modal's reload-and-compare check is the strongest client-side mitigation, but it cannot close the check/approve race. The remaining issue requires an API-level revision precondition (for example revision_id or If-Match/updated_at) and a matching ts-client change. I’m withdrawing this as an app-level finding; it should instead be tracked as a backend/API enhancement.

Comment thread apps/signage-manager/src/app/playlists/playlists.component.ts Outdated
@MrYuion

MrYuion commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator Author

LGTM

- Fetch a playlist by ID to check distribution when it is not loaded.
- Keep a pending approval request when items load.
- Send null for cleared validity dates.
- Re-check the revision before approving.
- Show errors for add-media, item loading and deep links.
- One playlistStatus helper for every playlist status badge.
- Move items up and down with the keyboard.
- Map animation indexes from the backend to their names, and keep a
  playlist's animation unless the user changes it.
- Block the save hotkey while a dropdown has focus.
…ink warnings

- reloadPlaylists() retries the failed page first and reloads from page
  one only when the first page failed, so loaded pages are kept.
- A linked playlist that fails to load after the user moved on no longer
  warns or clears the selection.
@MrYuion
MrYuion force-pushed the fix/signage-manager-playlists branch from c13152c to 7f03208 Compare October 2, 2026 05:47
@MrYuion
MrYuion merged commit 9018edb into develop Oct 2, 2026
1 of 2 checks passed
@MrYuion
MrYuion deleted the fix/signage-manager-playlists branch October 2, 2026 05:58
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