1
0
mirror of https://github.com/dkmstr/openuds-gui.git synced 2024-10-26 08:55:23 +03:00

Moving observables to promises when possible

This commit is contained in:
Adolfo Gómez García 2023-01-12 01:35:23 +01:00
parent 753a59871c
commit 241f2a943d
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
9 changed files with 110 additions and 145 deletions

View File

@ -141,16 +141,14 @@ export class ServiceComponent implements OnInit {
type === 'release' type === 'release'
? django.gettext('Service released') ? django.gettext('Service released')
: django.gettext('Service reseted'); : django.gettext('Service reseted');
this.api.gui this.api.gui.yesno(title, django.gettext('Are you sure?')).then((val) => {
.yesno(title, django.gettext('Are you sure?')) if (val) {
.subscribe((val) => { this.api.action(type, this.service.id).then((service) => {
if (val) { if (service) {
this.api.action(type, this.service.id).subscribe((service) => { this.api.gui.alert(title, action);
if (service) { }
this.api.gui.alert(title, action); });
} }
}); });
}
});
} }
} }

View File

@ -1,8 +1,7 @@
<h4 mat-dialog-title [innerHtml]="data.title | safeHtml"></h4> <h4 mat-dialog-title [innerHtml]="data.title | safeHtml"></h4>
<mat-dialog-content [innerHTML]="data.body | safeHtml"></mat-dialog-content> <mat-dialog-content [innerHTML]="data.body | safeHtml"></mat-dialog-content>
<mat-dialog-actions> <mat-dialog-actions>
<button *ngIf="data.type===0" mat-raised-button mat-dialog-close (click)="close()"> <uds-translate>Close</uds-translate>{{ extra }}</button> <button *ngIf="data.type===0" mat-raised-button mat-dialog-close (click)="resolver(false); close()"> <uds-translate>Close</uds-translate>{{ extra }}</button>
<button *ngIf="data.type===1" mat-raised-button mat-dialog-close (click)="yes()"><uds-translate>Yes</uds-translate></button> <button *ngIf="data.type===1" mat-raised-button mat-dialog-close (click)="resolver(true); close()"><uds-translate>Yes</uds-translate></button>
<button *ngIf="data.type===1" mat-raised-button mat-dialog-close (click)="no()"><uds-translate>No</uds-translate></button> <button *ngIf="data.type===1" mat-raised-button mat-dialog-close (click)="resolver(false); close()"><uds-translate>No</uds-translate></button>
</mat-dialog-actions> </mat-dialog-actions>

View File

@ -15,7 +15,7 @@ export interface ModalData {
title: string; title: string;
body: string; body: string;
autoclose?: number; autoclose?: number;
checkClose?: Observable<boolean>; checkClose?: Promise<boolean>;
type: DialogType; type: DialogType;
username?: string; username?: string;
domain?: string; domain?: string;
@ -30,50 +30,17 @@ export interface ModalData {
export class ModalComponent implements OnInit { export class ModalComponent implements OnInit {
extra: string; extra: string;
subscription: Subscription; subscription: Subscription;
yesno: Observable<boolean>; yesno: Promise<boolean>;
yes: () => void; resolver: (value: boolean) => void;
no: () => void;
close: () => void;
constructor(public dialogRef: MatDialogRef<ModalComponent>, @Inject(MAT_DIALOG_DATA) public data: ModalData) { constructor(public dialogRef: MatDialogRef<ModalComponent>, @Inject(MAT_DIALOG_DATA) public data: ModalData) {
this.subscription = null;
this.resetCallbacks();
// Notifies on case of yes or not to subscriber // Notifies on case of yes or not to subscriber
this.yesno = new Observable<boolean>((observer) => { this.yesno = new Promise<boolean>((resolve) => {
this.yes = () => { this.resolver = resolve;
observer.next(true);
observer.complete();
};
this.no = () => {
observer.next(false);
observer.complete();
};
this.close = () => {
this.doClose();
observer.next(false);
observer.complete();
};
const self = this;
return {unsubscribe: () => self.resetCallbacks()};
}); });
} }
resetCallbacks() { close() {
this.yes = this.no = () => this.close();
this.close = () => this.doClose();
}
/**
* Invoked on closed modal component
* This ensures that we stop subscription to interval
*/
closed(): void {
if (this.subscription !== null) {
this.subscription.unsubscribe();
}
}
doClose(): void {
this.dialogRef.close(); this.dialogRef.close();
} }
@ -86,13 +53,13 @@ export class ModalComponent implements OnInit {
this.extra = ' (' + Math.floor(miliseconds / 1000) + ' ' + django.gettext('seconds') + ') '; this.extra = ' (' + Math.floor(miliseconds / 1000) + ' ' + django.gettext('seconds') + ') ';
} }
initAlert() { async initAlert(): Promise<void> {
if (this.data.autoclose > 0) { if (this.data.autoclose > 0) {
this.dialogRef.afterClosed().subscribe(res => { this.dialogRef.afterClosed().subscribe(res => {
this.closed(); this.close();
}); });
this.setExtra(this.data.autoclose); this.setExtra(this.data.autoclose);
this.subscription = interval(1000).subscribe(n => { interval(1000).subscribe(n => {
const rem = this.data.autoclose - (n + 1) * 1000; const rem = this.data.autoclose - (n + 1) * 1000;
this.setExtra(rem); this.setExtra(rem);
if (rem <= 0) { if (rem <= 0) {
@ -103,26 +70,14 @@ export class ModalComponent implements OnInit {
this.dialogRef.close(); this.dialogRef.close();
}, this.data.autoclose);*/ }, this.data.autoclose);*/
} else if (this.data.checkClose) { } else if (this.data.checkClose) {
this.dialogRef.afterClosed().subscribe(res => { await this.data.checkClose;
this.closed(); this.close();
});
this.subscription = this.data.checkClose.subscribe(res => {
// Invoke the close after, result in fact is not important
window.setTimeout(() => {
this.doClose();
});
});
} }
} }
initYesNo() {
// data.autoclose is not used
}
ngOnInit() { ngOnInit() {
if ( this.data.type === DialogType.yesno ) { if ( this.data.type === DialogType.yesno ) {
this.initYesNo(); ;
} else { } else {
this.initAlert(); this.initAlert();
} }

View File

@ -3,7 +3,9 @@ import { Injectable } from '@angular/core';
import { ModalComponent, DialogType } from './modal/modal.component'; import { ModalComponent, DialogType } from './modal/modal.component';
import { CredentialsModalComponent } from './credentials-modal/credentials-modal.component'; import { CredentialsModalComponent } from './credentials-modal/credentials-modal.component';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { Observable } from 'rxjs'; import { Observable, firstValueFrom } from 'rxjs';
const toPromise = <T>(observable: Observable<T>): Promise<T> => firstValueFrom(observable);
@Injectable() @Injectable()
export class UDSGuiService { export class UDSGuiService {
@ -13,7 +15,7 @@ export class UDSGuiService {
title: string, title: string,
message: string, message: string,
autoclose = 0, autoclose = 0,
checkClose: Observable<boolean> = null checkClose: Promise<boolean> = null
) { ) {
const width = window.innerWidth < 800 ? '80%' : '40%'; const width = window.innerWidth < 800 ? '80%' : '40%';
const dialogRef = this.dialog.open(ModalComponent, { const dialogRef = this.dialog.open(ModalComponent, {
@ -30,7 +32,7 @@ export class UDSGuiService {
return dialogRef; return dialogRef;
} }
yesno(title: string, message: string) { yesno(title: string, message: string): Promise<boolean> {
const width = window.innerWidth < 800 ? '80%' : '40%'; const width = window.innerWidth < 800 ? '80%' : '40%';
const dialogRef = this.dialog.open(ModalComponent, { const dialogRef = this.dialog.open(ModalComponent, {
width, width,
@ -41,13 +43,13 @@ export class UDSGuiService {
return dialogRef.componentInstance.yesno; return dialogRef.componentInstance.yesno;
} }
askCredentials(username: string, domain: string): Observable<{username: string; password: string; domain: string}> { askCredentials(username: string, domain: string): Promise<{username: string; password: string; domain: string}> {
const dialogRef = this.dialog.open(CredentialsModalComponent, { const dialogRef = this.dialog.open(CredentialsModalComponent, {
data: { data: {
username, username,
domain, domain,
}, },
}); });
return dialogRef.afterClosed(); return toPromise(dialogRef.afterClosed());
} }
} }

View File

@ -48,12 +48,12 @@ export class Plugin {
), ),
0, 0,
// Now UDS tries to check status // Now UDS tries to check status
new Observable<boolean>((observer) => { new Promise<boolean>((resolve) => {
let readyTime = 0; let readyTime = 0;
const checker = () => { const checker = () => {
if (alert.componentInstance) { if (alert.componentInstance) {
// Not closed dialog... // Not closed dialog...
this.api.status(params[0], params[1]).subscribe( this.api.status(params[0], params[1]).then(
(data) => { (data) => {
if (data.status === 'ready') { if (data.status === 'ready') {
if (!readyTime) { if (!readyTime) {
@ -89,19 +89,16 @@ export class Plugin {
alert.componentInstance.data.body = django.gettext( alert.componentInstance.data.body = django.gettext(
'Machine ready, waiting for UDS Client' 'Machine ready, waiting for UDS Client'
); );
observer.next(true); resolve(true);
observer.complete();
} else if (data.status === 'running') { } else if (data.status === 'running') {
window.setTimeout(checker, this.delay); // Recheck after delay seconds window.setTimeout(checker, this.delay); // Recheck after delay seconds
} else { } else {
observer.next(true); resolve(true);
observer.complete();
notifyError(); notifyError();
} }
}, },
(error) => { (error) => {
observer.next(true); resolve(true);
observer.complete();
notifyError(error); notifyError(error);
} }
); );
@ -120,7 +117,7 @@ export class Plugin {
}) })
); );
this.api.enabler(params[0], params[1]).subscribe( this.api.enabler(params[0], params[1]).then(
(data) => { (data) => {
if (data.error) { if (data.error) {
state = 'error'; state = 'error';
@ -162,15 +159,14 @@ export class Plugin {
), ),
0, 0,
// Now UDS tries to check status before closing dialog... // Now UDS tries to check status before closing dialog...
new Observable<boolean>((observer) => { new Promise<boolean>((resolve) => {
const checker = () => { const checker = () => {
if (alert.componentInstance) { if (alert.componentInstance) {
// Not closed dialog... // Not closed dialog...
this.api.transportUrl(url).subscribe( this.api.transportUrl(url).then(
(data) => { (data) => {
if (data.url) { if (data.url) {
observer.next(true); resolve(true);
observer.complete(); // Notify window to close...
// Extract if credentials modal is requested // Extract if credentials modal is requested
let username = ''; let username = '';
let domain = ''; let domain = '';
@ -237,9 +233,9 @@ export class Plugin {
if (askCredentials) { if (askCredentials) {
this.api.gui this.api.gui
.askCredentials(username, domain) .askCredentials(username, domain)
.subscribe((result) => { .then((result) => {
// Update transport credentials // Update transport credentials
this.api.updateTransportTicket(ticket, scrambler,result.username, result.password, result.domain).subscribe( this.api.updateTransportTicket(ticket, scrambler,result.username, result.password, result.domain).then(
() => { () => {
openWindow(); openWindow();
} }
@ -249,16 +245,14 @@ export class Plugin {
openWindow(); // Open window openWindow(); // Open window
} }
} else if (!data.running) { } else if (!data.running) {
observer.next(true); resolve(true);
observer.complete();
notifyError(data.error); notifyError(data.error);
} else { } else {
window.setTimeout(checker, this.delay); // Recheck after 5 seconds window.setTimeout(checker, this.delay); // Recheck after 5 seconds
} }
}, },
(error) => { (error) => {
observer.next(true); resolve(true);
observer.complete();
notifyError(error); notifyError(error);
} }
); );
@ -273,7 +267,7 @@ export class Plugin {
text: string, text: string,
info: string, info: string,
waitTime: number, waitTime: number,
checker: Observable<boolean> = null checker: Promise<boolean> = null
) { ) {
return this.api.gui.alert( return this.api.gui.alert(
django.gettext('Launching service'), django.gettext('Launching service'),

View File

@ -84,7 +84,7 @@ export class ServicesComponent implements OnInit {
// Obtain services list // Obtain services list
this.api this.api
.getServicesInformation() .getServicesInformation()
.subscribe((result: JSONServicesInformation) => { .then((result: JSONServicesInformation) => {
this.servicesInformation = result; this.servicesInformation = result;
this.autorun(); this.autorun();

View File

@ -19,22 +19,22 @@ export interface UDSApiServiceType {
enabler( enabler(
serviceId: string, serviceId: string,
transportId: string transportId: string
): Observable<JSONEnabledService>; ): Promise<JSONEnabledService>;
/* Service status */ /* Service status */
status( status(
serviceId: string, serviceId: string,
transportId: string transportId: string
): Observable<JSONStatusService>; ): Promise<JSONStatusService>;
/* Services resetter */ /* Services resetter */
action(action: string, serviceId: string): Observable<JSONService>; action(action: string, serviceId: string): Promise<JSONService>;
/* transport url */ /* transport url */
transportUrl(url: string): Observable<JSONTransportURLService>; transportUrl(url: string): Promise<JSONTransportURLService>;
/* Transport ticket credentials updater */ /* Transport ticket credentials updater */
updateTransportTicket(ticketId: string, scrambler: string, username: string, password: string, domain: string): Observable<any>; updateTransportTicket(ticketId: string, scrambler: string, username: string, password: string, domain: string): Promise<any>;
/* Go to admin dashboard */ /* Go to admin dashboard */
gotoAdmin(): void; gotoAdmin(): void;
@ -45,7 +45,7 @@ export interface UDSApiServiceType {
/** /**
* Gets services information * Gets services information
*/ */
getServicesInformation(): Observable<JSONServicesInformation>; getServicesInformation(): Promise<JSONServicesInformation>;
/** /**
* Executes custom javascript for service launch if it is available * Executes custom javascript for service launch if it is available

View File

@ -2,7 +2,8 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { User, UDSConfig, Downloadable, Info } from './types/config'; import { User, UDSConfig, Downloadable, Info } from './types/config';
import { Observable } from 'rxjs'; import { firstValueFrom, Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';
import { import {
JSONServicesInformation, JSONServicesInformation,
JSONEnabledService, JSONEnabledService,
@ -23,7 +24,12 @@ declare const csrf: any;
const DARK_THEME = 'dark-theme'; const DARK_THEME = 'dark-theme';
const LIGHT_THEME = 'light-theme'; const LIGHT_THEME = 'light-theme';
const TIMEOUT = 10000;
const toPromise = <T>(observable: Observable<T>, wait?: number): Promise<T> => {
wait = wait || TIMEOUT;
return firstValueFrom(observable.pipe(timeout(wait)));
};
@Injectable() @Injectable()
export class UDSApiService implements UDSApiServiceType { export class UDSApiService implements UDSApiServiceType {
@ -88,45 +94,50 @@ export class UDSApiService implements UDSApiServiceType {
} }
/* Client enabler */ /* Client enabler */
enabler(serviceId: string, transportId: string) { enabler(serviceId: string, transportId: string): Promise<JSONEnabledService> {
const enabler = this.config.urls.enabler const enabler = this.config.urls.enabler
.replace('param1', serviceId) .replace('param1', serviceId)
.replace('param2', transportId); .replace('param2', transportId);
return this.http.get<JSONEnabledService>(enabler); return toPromise(this.http.get<JSONEnabledService>(enabler));
} }
/* Check userService status */ /* Check userService status */
status( status(serviceId: string, transportId: string): Promise<JSONStatusService> {
serviceId: string,
transportId: string
): Observable<JSONStatusService> {
const status = this.config.urls.status const status = this.config.urls.status
.replace('param1', serviceId) .replace('param1', serviceId)
.replace('param2', transportId); .replace('param2', transportId);
return this.http.get<JSONStatusService>(status); return toPromise(this.http.get<JSONStatusService>(status));
} }
/* Services resetter */ /* Services resetter */
action(action: string, serviceId: string) { action(action: string, serviceId: string): Promise<JSONService> {
const actionURL = this.config.urls.action const actionURL = this.config.urls.action
.replace('param1', serviceId) .replace('param1', serviceId)
.replace('param2', action); .replace('param2', action);
return this.http.get<JSONService>(actionURL); return toPromise(this.http.get<JSONService>(actionURL));
} }
transportUrl(url: string): Observable<JSONTransportURLService> { transportUrl(url: string): Promise<JSONTransportURLService> {
return this.http.get<JSONTransportURLService>(url); return toPromise(this.http.get<JSONTransportURLService>(url));
} }
updateTransportTicket(ticketId: string, scrambler: string, username: string, password: string, domain: string): Observable<any> { updateTransportTicket(
ticketId: string,
scrambler: string,
username: string,
password: string,
domain: string
): Promise<any> {
const url = this.config.urls.updateTransportTicket const url = this.config.urls.updateTransportTicket
.replace('param1', ticketId) .replace('param1', ticketId)
.replace('param2', scrambler); .replace('param2', scrambler);
return this.http.post<any>(url, { return toPromise(
username, this.http.post<any>(url, {
password, username,
domain, password,
}); domain,
})
);
} }
/* Images & static related */ /* Images & static related */
@ -149,15 +160,17 @@ export class UDSApiService implements UDSApiServiceType {
/** /**
* Gets services information * Gets services information
*/ */
getServicesInformation(): Observable<JSONServicesInformation> { getServicesInformation(): Promise<JSONServicesInformation> {
return this.http.get<JSONServicesInformation>(this.config.urls.services); return toPromise(this.http.get<JSONServicesInformation>(this.config.urls.services));
} }
/** /**
* Gets error string from a code * Gets error string from a code
*/ */
getErrorInformation(errorCode: string): Observable<JSONErrorInformation> { getErrorInformation(errorCode: string): Observable<JSONErrorInformation> {
return this.http.get<JSONErrorInformation>(this.config.urls.error.replace('9999', errorCode)); return this.http.get<JSONErrorInformation>(
this.config.urls.error.replace('9999', errorCode)
);
} }
/** /**
@ -206,5 +219,4 @@ export class UDSApiService implements UDSApiServiceType {
}); });
body.classList.add(dark ? DARK_THEME : LIGHT_THEME); body.classList.add(dark ? DARK_THEME : LIGHT_THEME);
} }
} }

File diff suppressed because one or more lines are too long