diff --git a/apps/signage-manager/USER_STORIES.md b/apps/signage-manager/USER_STORIES.md index 8ecda384721..a84e65c4226 100644 --- a/apps/signage-manager/USER_STORIES.md +++ b/apps/signage-manager/USER_STORIES.md @@ -213,13 +213,16 @@ These stories cover the current app workflows: **Acceptance Criteria:** - The templates page shows a searchable template list and loads more templates as the user scrolls. +- The header shows the number of templates that match, including templates that are not loaded yet. +- If the list cannot load, the page shows an error with a retry button, not an empty list. +- A link to a template that is not in the loaded pages opens that template. - Users with create or update permission can create templates and edit their layout items. - Users with create permission can duplicate a template. The copy has the same settings and saved layouts. It is not approved and has no template mappings. - Template rows show approval-required and awaiting-review states. - Users with approval permission can review and approve a selected template. - Users without approval permission can select an approver and request template approval with a message. - The approval preview shows only changed layout items from the pending and approved templates, including the applicable X and Y values. It shows a no-older-version placeholder when no distinct approved version exists. -- Users with update permission can discard pending changes when an approved version exists. +- Users with update permission can discard pending changes when an approved version exists. They must confirm first. - Users must confirm before they leave a template that has unsaved layout changes. Confirming discards the changes. The browser warns before a reload or tab close drops them. --- diff --git a/apps/signage-manager/src/app/shared/template-approve-modal.component.ts b/apps/signage-manager/src/app/shared/template-approve-modal.component.ts index 5e99d7921a2..b21d1590da8 100644 --- a/apps/signage-manager/src/app/shared/template-approve-modal.component.ts +++ b/apps/signage-manager/src/app/shared/template-approve-modal.component.ts @@ -136,21 +136,15 @@ export class TemplateApproveModalComponent { public readonly has_previous_version = () => this.template_versions().length > 1; + /** Discard the pending version. The service asks the user to confirm. */ public async undoChanges() { const previous_version = this.template_versions()[1]; if (!previous_version) return; - this.loading.set(i18n('SIGNAGE_MANAGER.UNDOING_CHANGES')); - this._dialog_ref.disableClose = true; - try { - const undone = await this._template_service.undoTemplateChanges( - this._data.template.id, - previous_version, - ); - if (undone) this._dialog_ref.close(true); - } finally { - this.loading.set(''); - this._dialog_ref.disableClose = false; - } + const undone = await this._template_service.undoTemplateChanges( + this._data.template.id, + previous_version, + ); + if (undone) this._dialog_ref.close(true); } /** Approve the pending version. Blocked when the versions failed to load. */ diff --git a/apps/signage-manager/src/app/shared/template-edit-modal.component.ts b/apps/signage-manager/src/app/shared/template-edit-modal.component.ts index 19b9be997ca..fd3eed73711 100644 --- a/apps/signage-manager/src/app/shared/template-edit-modal.component.ts +++ b/apps/signage-manager/src/app/shared/template-edit-modal.component.ts @@ -308,11 +308,10 @@ export class TemplateEditModalComponent { this._dialog_ref.disableClose = false; this._dialog_ref.close(result); notifySuccess(i18n('SIGNAGE_MANAGER.TEMPLATE_SAVED')); - } catch (e) { + } catch { this._dialog_ref.disableClose = false; this.loading.set(false); notifyError(i18n('SIGNAGE_MANAGER.TEMPLATE_SAVE_ERROR')); - throw e; } }); } diff --git a/apps/signage-manager/src/app/shared/template-mapping-modal.component.ts b/apps/signage-manager/src/app/shared/template-mapping-modal.component.ts index 310dfda9a9d..5a334661c68 100644 --- a/apps/signage-manager/src/app/shared/template-mapping-modal.component.ts +++ b/apps/signage-manager/src/app/shared/template-mapping-modal.component.ts @@ -257,13 +257,12 @@ export class TemplateMappingModalComponent { notifySuccess( i18n('SIGNAGE_MANAGER.SVC_TEMPLATE_MAPPING_SAVED'), ); - } catch (error) { + } catch { this._dialog_ref.disableClose = false; this.loading.set(false); notifyError( i18n('SIGNAGE_MANAGER.SVC_TEMPLATE_MAPPING_SAVE_ERROR'), ); - throw error; } }); } diff --git a/apps/signage-manager/src/app/shared/template-mappings.component.ts b/apps/signage-manager/src/app/shared/template-mappings.component.ts index 96179069300..b627754841a 100644 --- a/apps/signage-manager/src/app/shared/template-mappings.component.ts +++ b/apps/signage-manager/src/app/shared/template-mappings.component.ts @@ -1,5 +1,6 @@ import { Component, computed, inject, input, resource } from '@angular/core'; import { MatRippleModule } from '@angular/material/core'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTooltipModule } from '@angular/material/tooltip'; import { RouterLink } from '@angular/router'; import { i18n } from '@placeos/common'; @@ -52,11 +53,16 @@ export type TemplateMappingTargetType = 'display' | 'zone'; 'SIGNAGE_MANAGER.APPLY_TEMPLATE' | translate " (click)="editMapping()" + [disabled]="opening()" [attr.aria-label]=" 'SIGNAGE_MANAGER.APPLY_TEMPLATE' | translate " > - add + @if (opening()) { + + } @else { + add + } } @@ -320,6 +326,7 @@ export type TemplateMappingTargetType = 'display' | 'zone'; ], imports: [ MatRippleModule, + MatProgressSpinnerModule, MatTooltipModule, AuthenticatedImageDirective, IconComponent, @@ -335,6 +342,7 @@ export class TemplateMappingsComponent { public readonly target_type = input('display'); public readonly target_id = input(''); public readonly can_update = this._context.can_update; + public readonly opening = this._template_service.template_mapping_opening; private readonly _mappings = resource({ params: () => ({ diff --git a/apps/signage-manager/src/app/shared/template-request-approval-modal.component.ts b/apps/signage-manager/src/app/shared/template-request-approval-modal.component.ts index 5f0dcece958..7a5693219bc 100644 --- a/apps/signage-manager/src/app/shared/template-request-approval-modal.component.ts +++ b/apps/signage-manager/src/app/shared/template-request-approval-modal.component.ts @@ -143,9 +143,18 @@ export interface TemplateRequestApprovalModalResult { }} @if (show_preview()) { - + @if (versions_error()) { +

+ {{ + 'SIGNAGE_MANAGER.TEMPLATE_VERSIONS_LOAD_ERROR' + | translate + }} +

+ } @else { + + } }