@@ -0,0 +1,75 @@
|
||||
<div class="page">
|
||||
<div class="flex flex-wrap gap-3 items-end mb-4">
|
||||
<label class="flex flex-col gap-1">
|
||||
Search / 搜尋
|
||||
<kendo-textbox placeholder="Message / category" [(ngModel)]="search"
|
||||
(keydown.enter)="applyFilter()"></kendo-textbox>
|
||||
</label>
|
||||
<label class="flex flex-col gap-1">
|
||||
Min Level / 最低等級
|
||||
<kendo-dropdownlist [data]="levels" textField="label" valueField="value" [valuePrimitive]="true"
|
||||
[(ngModel)]="minLevel" [defaultItem]="{ value: null, label: 'All Levels/全部等級' }">
|
||||
</kendo-dropdownlist>
|
||||
</label>
|
||||
<label class="flex flex-col gap-1">
|
||||
From / 起
|
||||
<kendo-datepicker [(ngModel)]="from"></kendo-datepicker>
|
||||
</label>
|
||||
<label class="flex flex-col gap-1">
|
||||
To / 迄
|
||||
<kendo-datepicker [(ngModel)]="to"></kendo-datepicker>
|
||||
</label>
|
||||
<button kendoButton themeColor="primary" (click)="applyFilter()">Apply / 套用</button>
|
||||
</div>
|
||||
|
||||
<kendo-grid [data]="{ data: rows, total: total }" [loading]="loading" [pageable]="true" [skip]="skip"
|
||||
[pageSize]="pageSize" (pageChange)="onPageChange($event)">
|
||||
|
||||
<kendo-grid-column title="Time / 時間" [width]="170">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>{{ dataItem.timestamp | date:'short' }}</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column title="Level / 等級" [width]="110">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<span [class]="levelClass(dataItem.level)">{{ dataItem.level }}</span>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="category" title="Source / 來源" [width]="240"></kendo-grid-column>
|
||||
<kendo-grid-column title="Message / 訊息">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<span class="msg">{{ dataItem.message }}</span>
|
||||
<span *ngIf="dataItem.hasException" class="exc-flag" title="Has exception">⚠</span>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="statusCode" title="Status" [width]="90"></kendo-grid-column>
|
||||
<kendo-grid-column title="" [width]="90">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<button kendoButton fillMode="flat" themeColor="primary" (click)="view(dataItem)">View</button>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
</kendo-grid>
|
||||
|
||||
<!-- Detail dialog -->
|
||||
<kendo-dialog *ngIf="detail" title="System Log #{{ detail.id }}" [width]="720" (close)="detail = null">
|
||||
<div class="p-2 flex flex-col gap-2 text-sm">
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div><strong>Time:</strong> {{ detail.timestamp | date:'medium' }}</div>
|
||||
<div><strong>Level:</strong> <span [class]="levelClass(detail.level)">{{ detail.level }}</span></div>
|
||||
<div class="col-span-2"><strong>Source:</strong> {{ detail.category }}</div>
|
||||
<div *ngIf="detail.httpMethod"><strong>Request:</strong> {{ detail.httpMethod }} {{ detail.requestPath }}</div>
|
||||
<div *ngIf="detail.statusCode"><strong>Status:</strong> {{ detail.statusCode }}</div>
|
||||
<div *ngIf="detail.userId"><strong>User:</strong> {{ detail.userId }}</div>
|
||||
<div *ngIf="detail.ipAddress"><strong>IP:</strong> {{ detail.ipAddress }}</div>
|
||||
<div class="col-span-2" *ngIf="detail.correlationId"><strong>Correlation:</strong> {{ detail.correlationId }}</div>
|
||||
</div>
|
||||
<div><strong>Message</strong></div>
|
||||
<pre class="detail-block">{{ detail.message }}</pre>
|
||||
<ng-container *ngIf="detail.exception">
|
||||
<div><strong>Exception / Stack Trace</strong></div>
|
||||
<pre class="detail-block detail-block--exc">{{ detail.exception }}</pre>
|
||||
</ng-container>
|
||||
</div>
|
||||
<kendo-dialog-actions>
|
||||
<button kendoButton (click)="detail = null">Close / 關閉</button>
|
||||
</kendo-dialog-actions>
|
||||
</kendo-dialog>
|
||||
</div>
|
||||
Reference in New Issue
Block a user