added support for material dropdown and autocompletion (work in

progress)
This commit is contained in:
Maria Teresa Paratore 2023-10-18 18:17:59 +02:00
parent b61cd64a03
commit affff0e800
6 changed files with 196 additions and 30 deletions

View File

@ -1,13 +1,11 @@
package org.gcube.fullstackapps.informationsystemmonitor.service;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.authorization.utils.manager.SecretManager;
import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
import org.gcube.common.authorization.utils.secret.JWTSecret;
import org.gcube.common.authorization.utils.secret.Secret;
import org.gcube.informationsystem.contexts.impl.entities.ContextImpl;
import org.gcube.informationsystem.contexts.reference.entities.Context;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient;
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory;
@ -45,6 +43,17 @@ public class InformationSystemService {
log.debug("AllContext: {}",contexts);
return contexts;
}
public List<Context> testResources(String rootCtx) throws Exception {
log.debug("GetAllContext: [rootCtx=]",rootCtx);
ResourceRegistryClient resourceRegistryClient= ResourceRegistryClientFactory.create(rootCtx);
//TODO: cosa ritornano questi metodi?
//resourceRegistryClient.getFilteredResources(null, null, null, false, null);
//resourceRegistryClient.getFilteredResources(rootCtx, rootCtx, rootCtx, false, null)
List<Context>contexts=resourceRegistryClient.getAllContext();
log.debug("AllContext: {}",contexts);
return contexts;
}
}

View File

@ -28,6 +28,8 @@ import { ErrorComponent } from './layouts/error/error.component';
import { SortableDirective } from './table-nodes/sortable.directive';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { RawjsonPaneComponent } from './rawjson-pane/rawjson-pane.component';
import { ClipboardModule } from '@angular/cdk/clipboard';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
imports: [
@ -43,7 +45,9 @@ import { RawjsonPaneComponent } from './rawjson-pane/rawjson-pane.component';
TranslationModule,
SortableDirective,
NgbModule,
RawjsonPaneComponent
RawjsonPaneComponent,
ClipboardModule,
BrowserAnimationsModule
],
providers: [
Title,

View File

@ -1,30 +1,71 @@
<div class="row">
<div class="col-md-3">
<jhi-rsc-tree></jhi-rsc-tree>
<div class="d-flex flex-row py-4" id="riga-superiore-controlli">
<div id="btn-group" class="col-md-3 mt-3">
<button mat-raised-button color="primary"><mat-icon>source</mat-icon> <span>File</span></button>
<button mat-raised-button color="primary"><mat-icon>edit</mat-icon> <span>Edit</span></button>
<button mat-raised-button color="primary"><mat-icon>explore</mat-icon> <span>View</span></button>
<button mat-raised-button color="primary"><mat-icon>help</mat-icon><span>Help</span></button>
<div id="restree" class="m-3">
<h4>Available Resources</h4>
<div class="col-md-3" id="tree-view">
<jhi-rsc-tree></jhi-rsc-tree>
</div>
</div>
</div>
<div class="col-md-9">
<h1 class="display-4"><span jhiTranslate="home.title">Welcome!</span></h1>
<div [ngSwitch]="account !== null">
<div class="alert alert-success" *ngSwitchCase="true">
<span id="home-logged-message" *ngIf="account" jhiTranslate="home.logged.message"
[translateValues]="{ username: account.login }">You are logged in as user "{{
account.login}}".</span>
<div>
<div>
<div class="d-inline-block" ngbDropdown #myDrop="ngbDropdown">
<button name="contexts" type="button" class="btn btn-outline-primary me-2" id="dropdownManual"
ngbDropdownAnchor (focus)="myDrop.open()">Your Contexts
</button>
<div ngbDropdownMenu aria-labelledby="dropdownManual">
<div *ngFor="let context of getContexts();let i = index" [attr.data-index]="i">
<button ngbDropdownItem value="{{context}}">{{context|contexttransform}}</button>
</div>
</div>
[translateValues]="{ username: account.login }">You are logged in as user "{{account.login}}".</span>
</div>
<div class="d-inline-block my-3">
<mat-form-field>
<mat-label>Your Contexts</mat-label>
<mat-select>
<mat-option *ngFor="let context of getContexts()" [value]="context">
{{context|contexttransform}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div>
<!--TODO: formattare correttamente per visualizzare in pagina-->
<div class="d-inline-block my-3" ngbDropdown #myDrop="ngbDropdown" >
<div class="col-md-9 mt-2">
<form [formGroup]="chooseContextForm">
<mat-form-field appearance="outline" class="form-field">
<mat-label for="namefield" class="ml-4 flex-grow-1">Context name</mat-label>
<input matInput #contextInput (keyup)="(0)" [matAutocomplete]="auto" placeholder="Name" type="text" [formControl]="namefield" />
<mat-error>{{ checkForErrorsIn(namefield) }}</mat-error>
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn.bind(this)">
<mat-option *ngFor="let fctx of filteredContextsStr | async" [value]="fctx">
<span>{{fctx}}</span>
<!--
<span>{{ ctx.name }}</span>
<small> | ID: {{ ctx.id }}</small>
-->
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-form-field appearance="outline" class="form-field">
<mat-label for="uidfield">Context UUID</mat-label>
<input matInput id="uidfield" type="text" placeholder="UUID" formControlName="uidfield" readonly [value]="namefield.value.id" />
</mat-form-field>
<button mat-button (click)="copyUid(namefield)" color="primary" matTooltip="copy UUID" matTooltipPosition="below">
<mat-icon class="icon-wide2">content_copy</mat-icon>
</button>
</form>
</div>
<div class="my-3">
<jhi-table-nodes></jhi-table-nodes>
</div>
<div>
@ -33,6 +74,4 @@
</div>
</div>
</div>
</div>
</div>

View File

@ -1,3 +1,4 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
/* eslint-disable @typescript-eslint/restrict-plus-operands */
import { Component, OnInit } from '@angular/core';
@ -5,21 +6,114 @@ import { Component, OnInit } from '@angular/core';
import { LoginService } from 'app/login/login.service';
import { AccountService } from 'app/core/auth/account.service';
import { Account } from 'app/core/auth/account.model';
import { AbstractControl, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Clipboard } from '@angular/cdk/clipboard'
import { Observable, map, startWith } from 'rxjs';
import { IContextNode } from 'app/services/i-context-node';
@Component({
selector: 'jhi-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
styleUrls: ['./home.component.scss'],
})
export class HomeComponent implements OnInit {
account: Account | null = null;
constructor(private accountService: AccountService, private loginService: LoginService) { }
stringCtxs: string[];
//contexts: IContextNode[];
//public filteredContexts: Observable<IContextNode[]> | undefined;
public filteredContextsStr: Observable<string[]>| undefined;
chooseContextForm: FormGroup | any;
constructor(
private accountService: AccountService,
private loginService: LoginService,
private fb: FormBuilder,
private clipboard: Clipboard) {
//this.contexts = [];
this.stringCtxs = [];
this.chooseContextForm = this.fb.group({
namefield: ['', [Validators.required]],
uidfield: [''],
});
}
get namefield(): any {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return this.chooseContextForm.get('namefield');
}
get uidfield(): any {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return this.chooseContextForm.get('uidfield');
}
ngOnInit(): void {
//questo identifica l'utente e riempie il campo account
this.accountService.identity().subscribe(account => (this.account = account));
//caso semplificato con contesti solo stringhe
this.stringCtxs = this.getContexts();
console.debug("***stringCtxs..."+this.stringCtxs);
this.filteredContextsStr = this.chooseContextForm.get('namefield').valueChanges.pipe(
startWith(''),
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
map(ctx => (ctx ? this.filterContexts(ctx) : this.stringCtxs.slice()))
);
/*
this.resLoader.getResourcesByContext().subscribe(res => {
this.nestedDataSource.data = res;
});
// per la form dei contesti
this.ctxLoader.getData().subscribe(res => {
this.contexts = res;
console.log('*******numero contesti...', res.length);
});
this.filteredContexts = this.chooseContextForm.get('namefield').valueChanges.pipe(
startWith(''),
map(ctx => (ctx ? this.filterContexts(ctx) : this.contexts.slice()))
);*/
}
//mettere ANY come tipo dell'argomento per evitare errore TypeScript nella map!!
/*
filterContexts(name: any): IContextNode[] {
return this.contexts.filter(ctx => ctx.name.toLowerCase().includes(name.toLowerCase()));
}*/
//TEMPORANEO: CTX E' TEMPORANEAMENTE UNA STRINGA (NON A REGIME)
filterContexts(name: any): string[] {
return this.stringCtxs.filter(ctx => ctx.toLowerCase().includes(name.toLowerCase()));
}
//PER VALIDAZIONE FORM
checkForErrorsIn(formControl: AbstractControl): string {
if (formControl.hasError('required')) {
return 'Value is required!';
}
return '';
}
/*
displayFn(ctx: IContextNode): string {
return ctx.name ? ctx.name + ' | ' + ctx.id : '';
}
*/
displayFn(ctx: string): string {
const tmp = ctx ? ctx + ' (poi ci va id) ': '';
console.log("***"+tmp);
return tmp;
}
getContexts(): string[] {
if (this.account != null && this.account.resourceAccessDTO != null) {
@ -27,10 +121,9 @@ export class HomeComponent implements OnInit {
var sc=this.account.resourceAccessDTO.resourceAccess;
var contexts=Array.from(Object.keys(sc));
contexts=contexts.filter(element=>
element!==null&&element.startsWith("%2F"));
element!==null&&element.startsWith("%2F"));
contexts=contexts.sort();
// eslint-disable-next-line no-console
console.log("*****contexts..."+contexts);
return contexts;
} else {
@ -38,6 +131,16 @@ export class HomeComponent implements OnInit {
}
}
copyUid(val: any): void {
if (val instanceof FormControl) {
this.clipboard.copy(val.getRawValue().id);
} else {
//this.clipboard.copy('invalid value');
this.clipboard.copy('invalid value');
}
}
login(): void {
this.loginService.login();
}

View File

@ -8,9 +8,21 @@ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { TableNodesModule } from 'app/table-nodes/table-nodes.module';
import { RscTreeModule } from 'app/rsc-tree/rsc-tree.module';
import { RawjsonPaneComponent } from 'app/rawjson-pane/rawjson-pane.component';
import { ClipboardModule } from '@angular/cdk/clipboard';
import { MatTabsModule } from '@angular/material/tabs';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
imports: [SharedModule, RouterModule.forChild([HOME_ROUTE]),NgbDropdownModule, TableNodesModule, RscTreeModule,RawjsonPaneComponent],
imports: [SharedModule,
RouterModule.forChild([HOME_ROUTE]),
NgbDropdownModule,
TableNodesModule,
RscTreeModule,
RawjsonPaneComponent,
ClipboardModule,
MatTabsModule,
BrowserAnimationsModule
],
declarations: [HomeComponent],
schemas:[CUSTOM_ELEMENTS_SCHEMA]
})

View File

@ -1,4 +1,3 @@
<h2 class="display-8" id="tree-title"><span>Available Resources</span></h2>
<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="example-tree">
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
<button mat-button (click)="loadTable(node)">