mdstore ui - partial implementation

This commit is contained in:
Michele Artini 2023-02-07 15:08:37 +01:00
parent 32c9766db7
commit 1491e8a5d2
9 changed files with 153 additions and 59 deletions

View File

@ -10,19 +10,19 @@ import { DsmSearchComponent, DsmResultsComponent, DsmApiComponent } from './dsm/
import { MdstoreInspectorComponent, MdstoresComponent } from './mdstores/mdstores.component';
const routes: Routes = [
{ path:"" , redirectTo:'info', pathMatch: 'full' },
{ path:"info" , component:InfoComponent },
{ path:"resources/:type" , component:ResourcesComponent },
{ path:"adv_resources/context" , component:ContextsComponent },
{ path:"adv_resources/vocabulary", component:VocabulariesComponent },
{ path:"adv_resources/protocol" , component:ProtocolsComponent },
{ path:"wf_history" , component:WfHistoryComponent },
{ path:"ctx_viewer" , component:ContextViewerComponent },
{ path:"voc_editor" , component:VocabularyEditorComponent },
{ path:"dsm/search" , component:DsmSearchComponent },
{ path:"dsm/results/:page/:size" , component:DsmResultsComponent },
{ path:"mdstores" , component:MdstoresComponent },
{ path:"mdstore/:id/:limit" , component:MdstoreInspectorComponent }
{ path:"" , redirectTo:'info', pathMatch: 'full' },
{ path:"info" , component:InfoComponent },
{ path:"resources/:type" , component:ResourcesComponent },
{ path:"adv_resources/context" , component:ContextsComponent },
{ path:"adv_resources/vocabulary" , component:VocabulariesComponent },
{ path:"adv_resources/protocol" , component:ProtocolsComponent },
{ path:"wf_history" , component:WfHistoryComponent },
{ path:"ctx_viewer" , component:ContextViewerComponent },
{ path:"voc_editor" , component:VocabularyEditorComponent },
{ path:"dsm/search" , component:DsmSearchComponent },
{ path:"dsm/results/:page/:size" , component:DsmResultsComponent },
{ path:"mdstores" , component:MdstoresComponent },
{ path:"mdrecords/:versionId/:limit" , component:MdstoreInspectorComponent }
];
@NgModule({

View File

@ -185,6 +185,6 @@ export interface MDStoreVersion {
writing: boolean,
readCount:number,
lastUpdate:string,
siz: number,
size: number,
hdfsPath: string;
}

View File

@ -261,6 +261,37 @@ export class ISService {
});
}
commitMDStoreVersion(versionId:string, size:number, onSuccess: Function) {
this.client.get<any>('./ajax/mdstores/version/' + encodeURIComponent(versionId) + '/commit/' + size).subscribe({
next: data => onSuccess(data),
error: error => this.showError(error)
});
}
abortMDStoreVersion(versionId:string, onSuccess: Function) {
this.client.get<any>('./ajax/mdstores/version/' + encodeURIComponent(versionId) + '/abort').subscribe({
next: data => onSuccess(data),
error: error => this.showError(error)
});
}
deleteMDStoreVersion(versionId:string, force:boolean, onSuccess: Function) {
let params = new HttpParams();
if (force) { params = params.append('force', true); }
this.client.delete<any>('./ajax/mdstores/version/' + encodeURIComponent(versionId), {params: params}).subscribe({
next: data => onSuccess(data),
error: error => this.showError(error)
});
}
loadMDStoreVersions(mdId:string, onSuccess: Function): void {
this.client.get<MDStoreVersion[]>('./ajax/mdstores/mdstore/' + encodeURIComponent(mdId) + '/versions').subscribe({
next: data => onSuccess(data),
error: error => this.showError(error)
});
}
private showError(error: any, form?: FormGroup) {
const msg = this.errorMessage(error);
if (form) {

View File

@ -13,10 +13,6 @@
vertical-align: top;
}
.dsm-result-table th {
width: 20em;
}
.dsm-result-table td button {
font-size: 0.8em !important;
padding: 0 !important;

View File

@ -1 +1,48 @@
VERSIONS
<h1 mat-dialog-title>MDStore Versions</h1>
<div mat-dialog-content>
<p class="small" style="text-align: right;">
<input type="checkbox" [(ngModel)]="forceDelete" />
force delete
</p>
<table class="mdstore-table small">
<thead>
<tr>
<th style="width: 50%">ID</th>
<th style="width: 20%; text-align: center;">Read Count</th>
<th style="width: 20%; text-align: center;">Last Update</th>
<th style="width: 10%; text-align: right;">Size</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let v of versions" [ngClass]="{'active-row': v.id == data.currentVersion}">
<td>
<mat-icon fontIcon="edit" *ngIf="v.writing" title="writing..."></mat-icon>
<b> {{v.id}}</b>
<br />
<span class="small"><b>Path:</b> {{v.hdfsPath}}</span><br />
<button mat-stroked-button color="primary" (click)="openInspectorPage(v)">inspect</button>
<button mat-stroked-button color="basic" *ngIf="v.writing"
(click)="commitVersion(v)">commit</button>
<button mat-stroked-button color="warn" *ngIf="v.writing"
ng-click="abortVersion(v.id)">abort</button>
<button mat-stroked-button color="warn" *ngIf="v.id != data.currentVersion"
ng-click="deleteVersion(v.id, forceVersionDelete)">delete</button>
</td>
<td style="text-align: center;">
{{v.readCount}}
<button mat-stroked-button color="primary" (click)="resetReading(v)"
[disabled]="v.readCount == 0">reset</button>
</td>
<td style="text-align: center;" title="{{v.lastUpdate}}">{{v.lastUpdate | date:"MMM dd, yyyy 'at' HH:mm"}}</td>
<td style="text-align: right;">{{v.size}}</td>
</tr>
</tbody>
</table>
</div>
<div mat-dialog-actions>
<button mat-stroked-button color="primary" mat-dialog-close>Close</button>
</div>

View File

@ -1,25 +1,33 @@
.mdstore-info-table {
.mdstore-table {
margin-top: 1em;
margin-bottom: 1em;
border-collapse: collapse;
}
.mdstore-info-table tr:not(:last-child) {
.mdstore-table tr:not(:last-child) {
border-bottom: 1pt solid lightgrey;
}
.mdstore-info-table th {
width: 30%;
}
.mdstore-info-table th, .mdstore-info-table td{
.mdstore-table th, .mdstore-table td{
text-align: left;
font-size: 0.9em;
vertical-align: top;
padding-left: 1em;
padding-right: 1em;
}
.mdstore-info-table td button {
.mdstore-table td button, .mdstore-table td a.mdc-button {
font-size: 0.8em !important;
padding: 0 !important;
height: 2.5em !important;
}
.mdstore-table tr.active-row {
background-color: #daffda;
}
.mdstore-table mat-icon {
width: 1em;
height: 1em;
font-size: 1em;
}

View File

@ -13,10 +13,10 @@
<mat-card-subtitle>{{md.datasourceName}}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<table class="mdstore-info-table">
<table class="mdstore-table">
<tr>
<th>Format / Layout / Interpretation</th>
<td>{{md.format}} / {{md.layout}} / {{md.interpretation}}</td>
<th style="width: 30%">Format / Layout / Interpretation</th>
<td style="width: 70%">{{md.format}} / {{md.layout}} / {{md.interpretation}}</td>
</tr>
<tr>
<th>Datasource</th>
@ -53,7 +53,7 @@
</table>
</mat-card-content>
<mat-card-actions>
<a [routerLink]="['/mdstore/' + md.id + '/100']" mat-stroked-button color="primary">inspect</a>
<a [routerLink]="['/mdrecords/' + md.currentVersion + '/50']" mat-stroked-button color="primary">inspect</a>
<button mat-stroked-button color="warn" (click)="deleteMdstore(md)">delete</button>
<button mat-stroked-button color="info">zeppelin</button>
</mat-card-actions>

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MdstoresComponent } from './mdstores.component';
describe('MdstoresComponent', () => {
let component: MdstoresComponent;
let fixture: ComponentFixture<MdstoresComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MdstoresComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(MdstoresComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,6 +1,6 @@
import { Component, Inject, OnInit } from '@angular/core';
import { ISService } from '../common/is.service';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { MatDialog, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { MDStore, MDStoreVersion } from '../common/is.model';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@ -71,11 +71,46 @@ export class MdstoreInspectorComponent {
styleUrls: ['./mdstores.component.css']
})
export class MDStoreVersionsDialog {
constructor(public dialogRef: MatDialogRef<MDStoreVersionsDialog>, @Inject(MAT_DIALOG_DATA) public data: any, public service: ISService) {
forceDelete:boolean = false;
versions:MDStoreVersion[] = [];
constructor(public dialogRef: MatDialogRef<MDStoreVersionsDialog>, @Inject(MAT_DIALOG_DATA) public data: any, public service: ISService, public router: Router) {
this.reload();
}
reload() {
this.service.loadMDStoreVersions(this.data.id, (res:MDStoreVersion[]) => this.versions = res);
}
openInspectorPage(version:MDStoreVersion):void {
const url = this.router.serializeUrl(
this.router.createUrlTree(['/mdrecords/' + encodeURIComponent(version.id) + '/50'])
);
window.open(url, '_blank');
}
resetReading(version:MDStoreVersion):void {
//TODO
}
commitVersion(version:MDStoreVersion):void {
let size:number = parseInt(prompt("New Size", "0") || "0");
if (size >= 0) {
this.service.commitMDStoreVersion(version.id, size, (data:void) => {
this.reload();
//TODO this version should be promoved as current
});
}
}
abortVersion(version:MDStoreVersion):void {
this.service.abortMDStoreVersion(version.id, (data:void) => this.reload());
}
deleteVersion(version:MDStoreVersion):void {
this.service.deleteMDStoreVersion(version.id, this.forceDelete, (data:void) => this.reload());
}
onNoClick(): void {
this.dialogRef.close();
}