mirror of
https://github.com/bec-project/bec_atlas.git
synced 2025-07-13 22:51:49 +02:00
refactor: scan-table refactoring, running version
This commit is contained in:
3
frontend/bec_atlas/src/app/core/model/scan-count.ts
Normal file
3
frontend/bec_atlas/src/app/core/model/scan-count.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export interface ScanCountResponse {
|
||||||
|
count: number;
|
||||||
|
}
|
@ -15,6 +15,10 @@ export interface ScanDataResponse {
|
|||||||
info?: { [key: string]: any };
|
info?: { [key: string]: any };
|
||||||
timestamp?: number;
|
timestamp?: number;
|
||||||
user_data?: { [key: string]: any };
|
user_data?: { [key: string]: any };
|
||||||
|
name?: string;
|
||||||
user_rating?: number;
|
user_rating?: number;
|
||||||
|
system_rating?: number;
|
||||||
|
user_comments?: string;
|
||||||
|
system_comments?: string;
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import { ServerSettingsService } from '../server-settings.service';
|
|||||||
import { ScanDataResponse } from './model/scan-data';
|
import { ScanDataResponse } from './model/scan-data';
|
||||||
import { Realm } from './model/realm';
|
import { Realm } from './model/realm';
|
||||||
import { Deployment } from './model/deployment';
|
import { Deployment } from './model/deployment';
|
||||||
|
import { ScanCountResponse } from './model/scan-count';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@ -41,7 +42,7 @@ export class RemoteDataService {
|
|||||||
*/
|
*/
|
||||||
protected get<T>(
|
protected get<T>(
|
||||||
path: string,
|
path: string,
|
||||||
params: { [key: string]: string },
|
params: { [key: string]: string | number },
|
||||||
headers: HttpHeaders
|
headers: HttpHeaders
|
||||||
) {
|
) {
|
||||||
return this.httpClient.get<T>(
|
return this.httpClient.get<T>(
|
||||||
@ -153,3 +154,38 @@ export class DeploymentDataService extends RemoteDataService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class ScanCountService extends RemoteDataService {
|
||||||
|
/**
|
||||||
|
* Method for getting the scan count
|
||||||
|
* @param sessionId Unique identifier for the session (Optional)
|
||||||
|
* @param scanName Name of the scan (Optional)
|
||||||
|
* @param datasetNumber Dataset number (Optional)
|
||||||
|
* @returns response from the server with the scan count
|
||||||
|
* @throws HttpErrorResponse if the request fails
|
||||||
|
* @throws TimeoutError if the request takes too long
|
||||||
|
* @throws Error if the response is not a number
|
||||||
|
*/
|
||||||
|
getScanCount(
|
||||||
|
sessionId: string | null = null,
|
||||||
|
scanName: string | null = null,
|
||||||
|
datasetNumber: number | null = null
|
||||||
|
) {
|
||||||
|
let headers = new HttpHeaders();
|
||||||
|
let filters: { [key: string]: string | number } = {};
|
||||||
|
headers = headers.set('Content-Type', 'application/json; charset=utf-8');
|
||||||
|
if (sessionId !== null) {
|
||||||
|
filters['session_id'] = sessionId;
|
||||||
|
}
|
||||||
|
if (scanName !== null) {
|
||||||
|
filters['scan_name'] = scanName;
|
||||||
|
}
|
||||||
|
if (datasetNumber !== null) {
|
||||||
|
filters['dataset_number'] = datasetNumber;
|
||||||
|
}
|
||||||
|
return this.get<ScanCountResponse>('scans/count', filters, headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,31 +1,35 @@
|
|||||||
<div class = "button-container">
|
|
||||||
<button mat-raised-button (click)="ngOnInit()">Refresh</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-toolbar color="primary"> ScanData Table </mat-toolbar>
|
<mat-toolbar color="primary">
|
||||||
|
Table with Scan Data
|
||||||
<!-- <table mat-table *ngIf="tableData | async as data" [dataSource]="data" class="mat-elevation-z8"> -->
|
<span class="spacer"></span>
|
||||||
<table mat-table *ngIf="tableData() as data" [dataSource]="data" class="mat-elevation-z8">
|
<button mat-icon-button (click)="ngOnInit()">
|
||||||
|
<mat-icon>search</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button (click)="ngOnInit()">
|
||||||
|
<mat-icon>refresh</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button mat-icon-button (click)="ngOnInit()">
|
||||||
|
<mat-icon>settings</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-toolbar>
|
||||||
|
<table mat-table *ngIf="tableData() as data" [dataSource]="data" class="mat-elevation-z8">
|
||||||
|
|
||||||
<!-- Create table data dynamically -->
|
<!-- Create table data dynamically -->
|
||||||
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
|
<ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>
|
<th mat-header-cell *matHeaderCellDef> {{ column | titlecase }} </th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<ng-container *ngIf="column === 'timestamp'; else userRating">
|
@if (column === 'timestamp') {
|
||||||
{{ element[column] * 1000| date :'HH:mm:ss'}}
|
{{ element[column] * 1000 | date :'HH:mm:ss'}}
|
||||||
<br>
|
<br>
|
||||||
{{ element[column] * 1000 | date :'dd/MM/yyyy'}}
|
{{ element[column] * 1000 | date :'dd/MM/yyyy'}}
|
||||||
</ng-container>
|
}
|
||||||
<ng-template #userRating>
|
@else if (column === 'user_rating') {
|
||||||
<div *ngIf="column === 'user_rating'; else showData">
|
<star-rating [starType]="'svg'" [rating]="element[column]"></star-rating>
|
||||||
<star-rating [starType]="'svg'" [rating]="element[column]"></star-rating>
|
}
|
||||||
</div>
|
@else{
|
||||||
</ng-template>
|
|
||||||
<ng-template #showData>
|
|
||||||
<p> {{ element[column] }}</p>
|
<p> {{ element[column] }}</p>
|
||||||
</ng-template>
|
}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Header Row -->
|
<!-- Header Row -->
|
||||||
@ -35,5 +39,15 @@
|
|||||||
</table>
|
</table>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<mat-paginator [pageSize]=10 [pageSizeOptions]="[5, 10, 25, 100]" aria-label="Select page"></mat-paginator>
|
<mat-paginator
|
||||||
|
#paginator
|
||||||
|
class="table-paginator"
|
||||||
|
(page) = "handlePageEvent($event)"
|
||||||
|
[length]="totalScanCount"
|
||||||
|
[pageSize]= "limit"
|
||||||
|
[showFirstLastButtons]="true"
|
||||||
|
[pageSizeOptions]="[5, 10, 25, 100]"
|
||||||
|
[pageIndex]="page"
|
||||||
|
aria-label="Select page">
|
||||||
|
</mat-paginator>
|
||||||
</div>
|
</div>
|
@ -10,4 +10,8 @@
|
|||||||
}
|
}
|
||||||
.mat-mdc-row:hover {
|
.mat-mdc-row:hover {
|
||||||
background-color: var(--mat-sys-secondary-container);
|
background-color: var(--mat-sys-secondary-container);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
flex: 1 1 auto;
|
||||||
}
|
}
|
@ -1,91 +1,137 @@
|
|||||||
import { ChangeDetectionStrategy, Component, WritableSignal, signal, ViewChild } from '@angular/core';
|
import {
|
||||||
import { ScanDataService } from '../core/remote-data.service';
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
WritableSignal,
|
||||||
|
signal,
|
||||||
|
ViewChild,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { ScanCountService, ScanDataService } from '../core/remote-data.service';
|
||||||
import { ScanDataResponse } from '../core/model/scan-data';
|
import { ScanDataResponse } from '../core/model/scan-data';
|
||||||
import { firstValueFrom } from 'rxjs';
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
|
import {
|
||||||
|
MatPaginator,
|
||||||
|
MatPaginatorModule,
|
||||||
|
PageEvent,
|
||||||
|
} from '@angular/material/paginator';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { StarRatingModule } from 'angular-star-rating';
|
import { StarRatingModule } from 'angular-star-rating';
|
||||||
|
import { MatSort } from '@angular/material/sort';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-scan-table',
|
selector: 'app-scan-table',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, MatPaginator, MatTableModule, MatIconModule, MatToolbarModule, MatCardModule, MatButtonModule, MatPaginatorModule, StarRatingModule],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MatPaginator,
|
||||||
|
MatTableModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatToolbarModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatPaginatorModule,
|
||||||
|
StarRatingModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
],
|
||||||
templateUrl: './scan-table.component.html',
|
templateUrl: './scan-table.component.html',
|
||||||
styleUrl: './scan-table.component.scss',
|
styleUrl: './scan-table.component.scss',
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class ScanTableComponent {
|
export class ScanTableComponent {
|
||||||
tableData: WritableSignal<ScanDataResponse[]> = signal([]); // Initialize as empty array
|
// private tableData: new MatTableDataSource<ScanDataResponse[]>(); // Initialize as empty array
|
||||||
limit: number = 100;
|
// tableData: ScanDataResponse[] = [];
|
||||||
|
tableData: WritableSignal<ScanDataResponse[]> = signal([]);
|
||||||
|
limit: number = 10;
|
||||||
offset: number = 0;
|
offset: number = 0;
|
||||||
displayedColumns: string[] = ['scan_number', 'status', 'num_points', 'scan_name', 'scan_type', 'dataset_number', 'timestamp', 'user_rating'];
|
totalScanCount: number = 0;
|
||||||
ignoredEntries: string[] = ['scan_report_devices', 'user_metadata', 'readout_priority', 'scan_parameters', 'request_inputs', 'info'];
|
page: number = this.offset / this.limit;
|
||||||
|
pageEvent: PageEvent = new PageEvent();
|
||||||
|
sessionId: string = '';
|
||||||
|
sorting: number = -1;
|
||||||
|
displayedColumns: string[] = [
|
||||||
|
'scan_number',
|
||||||
|
'status',
|
||||||
|
'num_points',
|
||||||
|
'scan_name',
|
||||||
|
'scan_type',
|
||||||
|
'dataset_number',
|
||||||
|
'timestamp',
|
||||||
|
'user_rating',
|
||||||
|
];
|
||||||
|
ignoredEntries: string[] = [
|
||||||
|
'scan_report_devices',
|
||||||
|
'user_metadata',
|
||||||
|
'readout_priority',
|
||||||
|
'scan_parameters',
|
||||||
|
'request_inputs',
|
||||||
|
'info',
|
||||||
|
];
|
||||||
|
|
||||||
@ViewChild(MatPaginatorModule) paginator!: MatPaginatorModule;
|
constructor(
|
||||||
|
private scanData: ScanDataService,
|
||||||
|
private scanCount: ScanCountService
|
||||||
|
) {}
|
||||||
|
|
||||||
constructor(private scanData: ScanDataService) {}
|
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||||
|
@ViewChild(MatSort) sort!: MatSort;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
let sessionId = '6793628df62026a414d9338e';
|
this.sessionId = '6793628df62026a414d9338e';
|
||||||
this.updateTableData(sessionId);
|
this.updateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateTableData(sessionId: string) {
|
handlePageEvent(event: PageEvent) {
|
||||||
let data = await firstValueFrom(
|
this.pageEvent = event;
|
||||||
this.scanData.getScanData(sessionId, this.offset, this.limit, this.displayedColumns, false, { scan_number: -1 })
|
this.offset = event.pageIndex * event.pageSize;
|
||||||
);
|
this.limit = event.pageSize;
|
||||||
console.log('Received data: ', data);
|
this.page = this.offset / this.limit;
|
||||||
for (const entry of data) {
|
this.updateUI();
|
||||||
if (entry.user_data && entry.user_data['user_rating'])
|
}
|
||||||
{
|
|
||||||
entry.user_rating = entry.user_data['user_rating'];
|
updateUI() {
|
||||||
}
|
this.updateTotalScanCount(this.sessionId);
|
||||||
}
|
this.updateTableData(this.sessionId);
|
||||||
console.log('Received data: ', data);
|
}
|
||||||
this.tableData.set(data); // Update the signal value
|
|
||||||
|
updateTableData(sessionId: string) {
|
||||||
|
this.scanData
|
||||||
|
.getScanData(
|
||||||
|
sessionId,
|
||||||
|
this.offset,
|
||||||
|
this.limit,
|
||||||
|
this.displayedColumns,
|
||||||
|
false,
|
||||||
|
{ scan_number: this.sorting }
|
||||||
|
)
|
||||||
|
.subscribe({
|
||||||
|
next: (data) => {
|
||||||
|
console.log('Received data: ', data);
|
||||||
|
for (const entry of data) {
|
||||||
|
if (entry.user_data && entry.user_data['user_rating']) {
|
||||||
|
entry.user_rating = entry.user_data['user_rating'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tableData.set(data);
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
console.error('Error fetching data: ', error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTotalScanCount(sessionId: string) {
|
||||||
|
this.scanCount.getScanCount(sessionId).subscribe({
|
||||||
|
next: (data) => {
|
||||||
|
console.log('Received data: ', data);
|
||||||
|
this.totalScanCount = data.count;
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
console.error('Error fetching data: ', error);
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// @Component({
|
|
||||||
// selector: 'app-scan-table',
|
|
||||||
// standalone: true,
|
|
||||||
// imports: [CommonModule, MatPaginator, MatTableModule, MatIconModule, MatToolbarModule, MatCardModule, MatButtonModule, MatPaginatorModule],
|
|
||||||
// templateUrl: './scan-table.component.html',
|
|
||||||
// styleUrl: './scan-table.component.scss',
|
|
||||||
// changeDetection: ChangeDetectionStrategy.OnPush,
|
|
||||||
// })
|
|
||||||
// export class ScanTableComponent {
|
|
||||||
// tableData!: Promise<ScanDataResponse[]>;
|
|
||||||
// limit: number = 100;
|
|
||||||
// offset: number = 0;
|
|
||||||
// displayedColumns: string[] = ['scan_number', 'status', "num_points", "scan_name", "scan_type", "dataset_number", "timestamp", "user_rating"];
|
|
||||||
// ignoredEntries: string[] = ["scan_report_devices", "user_metadata", "readout_priority", "scan_parameters", "request_inputs", "info"];
|
|
||||||
// // , "scan_name", "scan_type"];
|
|
||||||
|
|
||||||
// @ViewChild(MatPaginatorModule) paginator!: MatPaginatorModule;
|
|
||||||
|
|
||||||
// constructor( private scanData: ScanDataService) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ngOnInit(): void {
|
|
||||||
|
|
||||||
// let sessionId = "6793628df62026a414d9338e";
|
|
||||||
// this.tableData = this.updateTableData(sessionId = "6793628df62026a414d9338e");
|
|
||||||
// // this.tableData = this.scanData.getScanData(sessionId = "6793628df62026a414d9338e");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async updateTableData(sessionId: string, offset: number = 0, limit: number = 100) {
|
|
||||||
// const data = await firstValueFrom(this.scanData.getScanData(sessionId=sessionId, offset=this.offset, limit=this.limit, this.displayedColumns, false, {"scan_number": -1}));
|
|
||||||
// console.log("Received data: ", data);
|
|
||||||
// // this.tableData = data;
|
|
||||||
// return data;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
Reference in New Issue
Block a user