1
0
mirror of https://github.com/dkmstr/openuds-gui.git synced 2025-01-24 18:03:34 +03:00

Improvememts to user interface:

* Added filter for services
* Added multiple levels for visual names (sizes)
This commit is contained in:
Adolfo Gómez García 2020-08-06 12:44:10 +02:00
parent 2191106fc3
commit 323aecfbbc
12 changed files with 129 additions and 50 deletions

View File

@ -16,7 +16,7 @@
.content { .content {
flex: 1 0 auto; flex: 1 0 auto;
width: 80%; width: 80%;
margin: 4rem auto 0 auto; margin: 64px auto 0 auto;
} }
/* responsive part */ /* responsive part */

View File

@ -37,6 +37,7 @@ import { SafeHtmlPipe } from './gui/safe-html.pipe';
import { AboutComponent } from './pages/about/about.component'; import { AboutComponent } from './pages/about/about.component';
import { DownloadsComponent } from './pages/downloads/downloads.component'; import { DownloadsComponent } from './pages/downloads/downloads.component';
import { LauncherComponent } from './pages/launcher/launcher.component'; import { LauncherComponent } from './pages/launcher/launcher.component';
import { FilterComponent } from './gui/components/filter/filter.component';
@NgModule({ @NgModule({
@ -57,6 +58,7 @@ import { LauncherComponent } from './pages/launcher/launcher.component';
DownloadsComponent, DownloadsComponent,
LauncherComponent, LauncherComponent,
StaffInfoComponent, StaffInfoComponent,
FilterComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -0,0 +1,6 @@
.filter {
margin-top: 0.5rem;
display: flex;
justify-content: flex-end;
font-size: 0.8rem;
}

View File

@ -0,0 +1,8 @@
<div class="filter">
<mat-form-field class="nav-input-field" floatLabel="auto">
<mat-label>Filter</mat-label>
<input matInput type="text" #input>
<i class="material-icons" matSuffix>search</i>
</mat-form-field>
</div>

View File

@ -0,0 +1,33 @@
import { Component, OnInit, Output, EventEmitter, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { fromEvent } from 'rxjs';
import { filter, debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
@Component({
selector: 'uds-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.css']
})
export class FilterComponent implements AfterViewInit {
@Output() updateEvent = new EventEmitter<string>();
@ViewChild('input', {static: true}) input: ElementRef;
constructor() { }
ngAfterViewInit() {
fromEvent(this.input.nativeElement, 'keyup')
.pipe(
filter(Boolean),
debounceTime(1000),
distinctUntilChanged(),
tap(() => { this.update(this.input.nativeElement.value); })
).subscribe();
}
update(fltr: string) {
this.updateEvent.emit(fltr.toLowerCase());
}
}

View File

@ -59,19 +59,35 @@
z-index: 10; z-index: 10;
} }
.name { .name {
margin-top: 0.5em; margin-top: 0.5em;
font-size: 1.2em; font-size: 1.05rem;
width: calc(100% - 1em); width: calc(100% - 1em);
display: flex; display: flex;
flex: 1 0 auto; flex: 1 0 auto;
flex-flow: row; flex-flow: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 1.5em;
padding: 0 0.5em; padding: 0 0.5em;
overflow: hidden; overflow: hidden;
height: 2.4em;
text-align: center;
}
.small-16 {
font-size: 1.05rem;
}
.small-20 {
font-size: 1.0rem;
}
.small-24 {
font-size: 0.95rem;
}
.small-28 {
font-size: 0.9rem;
} }
.menu { .menu {

View File

@ -34,7 +34,7 @@
<img [src]="serviceImage"> <img [src]="serviceImage">
</div> </div>
<div class="name"> <div class="name">
{{ serviceName }} <span [ngClass]="serviceNameClass">{{ serviceName }}</span>
</div> </div>
<div class="menu"> <div class="menu">
<button mat-icon-button [matMenuTriggerFor]="menu" *ngIf="hasMenu()"><i class="material-icons">menu</i></button> <button mat-icon-button [matMenuTriggerFor]="menu" *ngIf="hasMenu()"><i class="material-icons">menu</i></button>

View File

@ -4,7 +4,7 @@ import { UDSApiService } from '../../../uds-api.service';
declare var django: any; declare var django: any;
const MAX_NAME_LENGTH = 56; const MAX_NAME_LENGTH = 32;
@Component({ @Component({
selector: 'uds-service', selector: 'uds-service',
@ -64,6 +64,16 @@ export class ServiceComponent implements OnInit {
return klass; return klass;
} }
get serviceNameClass() {
const klass = [];
const len = Math.min(Math.floor((this.service.visual_name.length - 1) / 4) * 4, 28);
if (len >= 16) {
klass.push('small-' + len.toString());
}
console.log(this.service.visual_name, len, klass);
return klass;
}
getTransportIcon(transId: string) { getTransportIcon(transId: string) {
return this.api.transportIconURL(transId); return this.api.transportIconURL(transId);
} }

View File

@ -11,7 +11,7 @@
transition: all 0.3s cubic-bezier(.25, .8, .25, 1); transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
} }
.services-group-title img { .services-group-title img {
width: 2em; /* By using em, will also inherit font size & font size animations */ height: 2.2em; /* By using em, will also inherit font size & font size animations */
margin: 0 9px 0 0; margin: 0 9px 0 0;
flex-flow: 0 0 auto; flex-flow: 0 0 auto;
} }

View File

@ -1,4 +1,5 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
@ -9,22 +10,11 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MatToolbarModule } from '@angular/material/toolbar'; import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip';
import { MAT_LABEL_GLOBAL_OPTIONS } from '@angular/material/core'; import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
@NgModule({ @NgModule({
imports: [
MatToolbarModule,
MatButtonModule,
MatMenuModule,
MatTooltipModule,
MatExpansionModule,
MatDialogModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatCheckboxModule,
],
exports: [ exports: [
FormsModule,
MatToolbarModule, MatToolbarModule,
MatButtonModule, MatButtonModule,
MatMenuModule, MatMenuModule,
@ -37,7 +27,10 @@ import { MAT_LABEL_GLOBAL_OPTIONS } from '@angular/material/core';
MatCheckboxModule, MatCheckboxModule,
], ],
providers: [ providers: [
{provide: MAT_LABEL_GLOBAL_OPTIONS, useValue: {float: 'always'}} {
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: { floatLabel: 'always' }
}
] ]
}) })
export class AppMaterialModule { } export class AppMaterialModule { }

View File

@ -4,4 +4,6 @@
</mat-accordion> </mat-accordion>
</div> </div>
<uds-filter (updateEvent)="update($event)"></uds-filter>
<uds-staff-info></uds-staff-info> <uds-staff-info></uds-staff-info>

View File

@ -49,40 +49,49 @@ export class ServicesComponent implements OnInit {
// Obtain services list // Obtain services list
this.api.getServicesInformation().subscribe((result: JSONServicesInformation) => { this.api.getServicesInformation().subscribe((result: JSONServicesInformation) => {
this.servicesInformation = result; this.servicesInformation = result;
console.log(result);
// Fill up groupedServices
this.group = [];
this.autorun(); this.autorun();
let current: GroupedServices = null; this.updateServices();
this.servicesInformation.services.sort(
(a, b) => {
if (a.group.priority !== b.group.priority) {
return a.group.priority - b.group.priority;
} else {
if (a.group.id > b.group.id) {
return 1;
} else if (a.group.id < b.group.id) {
return -1;
}
}
return 0;
}).forEach(element => {
if (current === null || element.group.id !== current.group.id) {
if (current !== null) {
this.group.push(current);
}
current = new GroupedServices(element.group);
}
current.services.push(element);
});
if (current !== null) {
this.group.push(current);
}
console.log(this.group);
}); });
} }
private updateServices(filter: string = '') {
// Fill up groupedServices
this.group = [];
let current: GroupedServices = null;
this.servicesInformation.services.filter(
(value) => !filter || value.visual_name.toLowerCase().includes(filter) || value.group.name.toLowerCase().includes(filter)
).sort(
(a, b) => {
if (a.group.priority !== b.group.priority) {
return a.group.priority - b.group.priority;
} else {
if (a.group.id > b.group.id) {
return 1;
} else if (a.group.id < b.group.id) {
return -1;
}
}
return 0;
}).forEach(element => {
if (current === null || element.group.id !== current.group.id) {
if (current !== null) {
this.group.push(current);
}
current = new GroupedServices(element.group);
}
current.services.push(element);
});
if (current !== null) {
this.group.push(current);
}
}
update(filter: string) {
this.updateServices(filter);
}
ngOnInit() { ngOnInit() {
if (this.api.config.urls.launch) { if (this.api.config.urls.launch) {
this.api.logout(); this.api.logout();