Clicking a row navigated away to its own page, costing the checker the list and whatever search they had set up. It now opens in a dialog over the list, the same pattern the Disbursement and Closure Requests tabs already use. ViewCheckerInboxComponent gained the optional MatDialogRef/MAT_DIALOG_DATA pair rather than being duplicated, so the direct route still works for a bookmarked link. Two differences follow from being a dialog: - the list rows carry only summary fields, so the detail (which is what has commandAsJson) is fetched here; by route it stays resolver-provided. The template reads checkerInboxDetail.* unguarded, so it is now behind an @if with a loading state -- otherwise a dialog would render against undefined. - commandAsJson is absent on some entries (a DELETE carries no payload) and JSON.parse(undefined) throws. By route that broke the page; in a dialog it would have left an empty shell open. Parsing is now guarded. The list only reloads when something was actually actioned, since reload() re-navigates the route and would otherwise discard the checker's search on a plain close. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
131 lines
5.4 KiB
HTML
131 lines
5.4 KiB
HTML
<!--
|
|
Copyright since 2025 Mifos Initiative
|
|
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
-->
|
|
|
|
<div [class.vci--dialog]="isDialog">
|
|
@if (isDialog) {
|
|
<div class="vci-dialog-bar">
|
|
<span class="vci-dialog-bar__title">{{ 'labels.heading.View Checker Inbox' | translate }}</span>
|
|
<span class="vci-dialog-bar__close" (click)="close()">✕ {{ 'labels.buttons.Close' | translate }}</span>
|
|
</div>
|
|
}
|
|
|
|
<!-- As a dialog the detail is fetched rather than resolved, so nothing below can be rendered
|
|
until it arrives — the template reads checkerInboxDetail.* unguarded. -->
|
|
@if (loading) {
|
|
<div class="vci-loading">{{ 'labels.heading.Loading' | translate }}…</div>
|
|
}
|
|
|
|
@if (checkerInboxDetail) {
|
|
@if (isProductEditEntry) {
|
|
<div class="container m-b-20">
|
|
<div class="mat-elevation-z1" style="padding: 12px 16px; border-left: 4px solid #f59e0b; background: #fffbeb">
|
|
This is a product edit awaiting approval. Approve or reject it from
|
|
<strong>Approvals > Pending Product Edits</strong> instead — actioning it here would not release its lock.
|
|
</div>
|
|
</div>
|
|
} @else {
|
|
<div class="layout-row align-end gap-1percent layout-lt-md-column container m-b-20">
|
|
<button mat-raised-button color="success" (click)="approveChecker()">
|
|
<fa-icon icon="check" class="m-r-10"></fa-icon>{{ 'labels.buttons.Approve' | translate }}
|
|
</button>
|
|
<button mat-raised-button color="warn" (click)="deleteChecker()">
|
|
<fa-icon icon="trash" class="m-r-10"></fa-icon>{{ 'labels.buttons.Delete' | translate }}
|
|
</button>
|
|
<button mat-raised-button color="reject" (click)="rejectChecker()">
|
|
<fa-icon icon="times" class="m-r-10"></fa-icon>{{ 'labels.buttons.Reject' | translate }}
|
|
</button>
|
|
</div>
|
|
}
|
|
|
|
<div class="container">
|
|
<mat-card>
|
|
<mat-card-content>
|
|
<div class="layout-row-wrap responsive-column">
|
|
<h2 class="mat-h2 flex-fill">{{ 'labels.heading.View Checker Inbox' | translate }}</h2>
|
|
|
|
<mat-divider [inset]="true"></mat-divider>
|
|
|
|
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Details' | translate }}</h3>
|
|
|
|
<mat-divider [inset]="true"></mat-divider>
|
|
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.ID' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.id }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Status' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.processingResult }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.User' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.maker }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Action' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.actionName }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Entity' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.entityName }}</span>
|
|
</div>
|
|
|
|
@if (checkerInboxDetail.resourceId) {
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Resource ID' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.resourceId }}</span>
|
|
</div>
|
|
}
|
|
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Date' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.madeOnDate | dateFormat }}</span>
|
|
</div>
|
|
|
|
@if (checkerInboxDetail.officeName) {
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Office' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.officeName }}</span>
|
|
</div>
|
|
}
|
|
|
|
@if (checkerInboxDetail.savingsAccountNo) {
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ 'labels.inputs.Savings Account Number' | translate }}:</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.savingsAccountNo }}</span>
|
|
</div>
|
|
}
|
|
|
|
@if (checkerInboxDetail.groupLevelName) {
|
|
<div class="flex-fill">
|
|
<span class="flex-40"> {{ checkerInboxDetail.groupLevelName }}</span>
|
|
<span class="flex-60">{{ checkerInboxDetail.groupName }}</span>
|
|
</div>
|
|
}
|
|
|
|
@if (displayJSONData) {
|
|
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Command' | translate }}</h3>
|
|
<mat-divider [inset]="true"></mat-divider>
|
|
@for (json of jsondata | keyvalue; track json) {
|
|
<div class="flex-fill">
|
|
<span class="flex-40">{{ json.key }}:</span>
|
|
<span class="flex-60">{{ json.value }}</span>
|
|
</div>
|
|
}
|
|
}
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
</div>
|
|
}
|
|
</div>
|