1
0
mirror of https://github.com/dkmstr/openuds-gui.git synced 2025-01-10 05:17:35 +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 {
flex: 1 0 auto;
width: 80%;
margin: 4rem auto 0 auto;
margin: 64px auto 0 auto;
}
/* responsive part */

View File

@ -37,6 +37,7 @@ import { SafeHtmlPipe } from './gui/safe-html.pipe';
import { AboutComponent } from './pages/about/about.component';
import { DownloadsComponent } from './pages/downloads/downloads.component';
import { LauncherComponent } from './pages/launcher/launcher.component';
import { FilterComponent } from './gui/components/filter/filter.component';
@NgModule({
@ -57,6 +58,7 @@ import { LauncherComponent } from './pages/launcher/launcher.component';
DownloadsComponent,
LauncherComponent,
StaffInfoComponent,
FilterComponent,
],
imports: [
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;
}
.name {
margin-top: 0.5em;
font-size: 1.2em;
font-size: 1.05rem;
width: calc(100% - 1em);
display: flex;
flex: 1 0 auto;
flex-flow: row;
align-items: center;
justify-content: center;
height: 1.5em;
padding: 0 0.5em;
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 {

View File

@ -34,7 +34,7 @@
<img [src]="serviceImage">
</div>
<div class="name">
{{ serviceName }}
<span [ngClass]="serviceNameClass">{{ serviceName }}</span>
</div>
<div class="menu">
<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;
const MAX_NAME_LENGTH = 56;
const MAX_NAME_LENGTH = 32;
@Component({
selector: 'uds-service',
@ -64,6 +64,16 @@ export class ServiceComponent implements OnInit {
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) {
return this.api.transportIconURL(transId);
}

View File

@ -11,7 +11,7 @@
transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
}
.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;
flex-flow: 0 0 auto;
}

View File

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

View File

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

View File

@ -49,40 +49,49 @@ export class ServicesComponent implements OnInit {
// Obtain services list
this.api.getServicesInformation().subscribe((result: JSONServicesInformation) => {
this.servicesInformation = result;
console.log(result);
// Fill up groupedServices
this.group = [];
this.autorun();
let current: GroupedServices = null;
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);
this.updateServices();
});
}
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() {
if (this.api.config.urls.launch) {
this.api.logout();