diff --git a/README.md b/README.md index 5f5070e..a75e078 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,15 @@ This project was generated with [Angular CLI](https://github.com/angular/angular ## Development server -Remember editing the "proxy.conf.json" file and adapt it to your needings. +Remember editing the "proxy.conf.json" file and adapt it to your needings. Normally this means changing the `172.27.0.1` value to `YOUR_UDS_SERVER_IP` value and nothing more. Currently, you will need to use a running UDS server backend in order to run the development environment. -Run `yarn start` for a dev server. Navigate to `http://[YOUR_IP]:9000/`. The app will automatically reload if you change any of the source files. +Run `yarn start` for a dev server. + +In order to authenticate correctly against the platform, first navigate to `http://[YOUR_IP]:9000/uds/pages/login` so the cookies from backend are correctly implanted. + +Navigate to `http://[YOUR_IP]:9000/`. The app will automatically be reloaded if you change any of the source files. ## Importing into OpenUDS diff --git a/src/app/gui/components/service/service.component.css b/src/app/gui/components/service/service.component.css index ddf8f13..c566c23 100644 --- a/src/app/gui/components/service/service.component.css +++ b/src/app/gui/components/service/service.component.css @@ -63,6 +63,7 @@ .name { margin-top: 0.5em; font-size: 1.2em; + width: calc(100% - 1em); display: flex; flex: 1 0 auto; flex-flow: row; diff --git a/src/app/gui/components/service/service.component.html b/src/app/gui/components/service/service.component.html index 635db18..abba6ed 100644 --- a/src/app/gui/components/service/service.component.html +++ b/src/app/gui/components/service/service.component.html @@ -9,11 +9,11 @@ - - diff --git a/src/app/gui/components/service/service.component.ts b/src/app/gui/components/service/service.component.ts index 2775629..87b52fc 100644 --- a/src/app/gui/components/service/service.component.ts +++ b/src/app/gui/components/service/service.component.ts @@ -31,18 +31,18 @@ export class ServiceComponent implements OnInit { } get serviceTooltip() { - if ( this.service.to_be_replaced !== null ) { + if (this.service.to_be_replaced !== null) { return this.service.to_be_replaced_text; } else if (this.service.maintenance) { return django.gettext('Service is in maintenance'); } else if (this.service.not_accesible) { - return django.gettext('Access to the service is restricted at this time'); + return django.gettext('This service is currently not accessible due to schedule restrictions.'); } return ''; } get serviceClass() { - const klass = ['service']; + const klass = ['service']; if (this.service.to_be_replaced != null) { klass.push('tobereplaced'); } else if (this.service.maintenance) { @@ -50,7 +50,7 @@ export class ServiceComponent implements OnInit { } else if (this.service.not_accesible) { klass.push('forbidden'); } - if (klass.length > 1 ) { + if (klass.length > 1) { klass.push('alert'); } @@ -73,7 +73,7 @@ export class ServiceComponent implements OnInit { return this.service.maintenance === false && this.service.not_accesible === false && (this.hasActions() || this.hasManyTransports()) - ; + ; } notifyNotLaunching(message: string) { @@ -81,14 +81,14 @@ export class ServiceComponent implements OnInit { } launch(transport: JSONTransport) { - if (this.service.maintenance ) { + if (this.service.maintenance) { this.notifyNotLaunching(django.gettext('Service is in maintenance and cannot be launched')); } else if (this.service.not_accesible) { this.notifyNotLaunching('

' + - django.gettext('This service is currently not accesible due to schedule restrictions.') + - '

' + django.gettext('Access limited by calendar') + - '

' + django.gettext('Please, retry access in a while.') + - '

' + django.gettext('This service is currently not accesible due to schedule restrictions.') + + '

' + django.gettext('Access limited by calendar') + + '

' + django.gettext('Please, retry access in a while.') + + '

' ); } else { if (transport === null) { @@ -97,4 +97,40 @@ export class ServiceComponent implements OnInit { this.api.launchURL(transport.link); } } + + action(type: string) { + if (type === 'remove') { + this.api.gui.yesno( + django.gettext('Release service: ') + this.serviceName, + django.gettext('Are you sure?' + )).subscribe((val: boolean) => { + if (val) { + console.log('Releasing service'); + this.api.releaser(this.service.id).subscribe((service) => { + this.api.gui.alert( + django.gettext('Release service: ') + this.serviceName, + django.gettext('Service released') + ); + console.log(service); + }); + } + }); + } else { // 'reset' + this.api.gui.yesno( + django.gettext('Reset service: ') + this.serviceName, + django.gettext('Are you sure?') + ).subscribe((val: boolean) => { + if (val) { + console.log('Reseting service'); + this.api.resetter(this.service.id).subscribe((service) => { + this.api.gui.alert( + django.gettext('Reset service: ') + this.serviceName, + django.gettext('Service Reset') + ); + console.log(service); + }); + } + }); + } + } } diff --git a/src/app/gui/modal/modal.component.html b/src/app/gui/modal/modal.component.html index c8c6386..79a91f6 100644 --- a/src/app/gui/modal/modal.component.html +++ b/src/app/gui/modal/modal.component.html @@ -1,5 +1,8 @@

- + + + + diff --git a/src/app/gui/modal/modal.component.ts b/src/app/gui/modal/modal.component.ts index 4689d4c..651d70b 100644 --- a/src/app/gui/modal/modal.component.ts +++ b/src/app/gui/modal/modal.component.ts @@ -1,11 +1,17 @@ import { Component, OnInit, Inject } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; -import { interval, Subscription } from 'rxjs'; +import { interval, Subscription, Observable } from 'rxjs'; + +export enum DialogType { + alert = 0, + yesno = 1 +} export interface ModalData { title: string; body: string; - autoclose: number; + autoclose?: number; + type: DialogType; } @Component({ @@ -17,11 +23,41 @@ export interface ModalData { export class ModalComponent implements OnInit { extra: string; subscription: Subscription; + yesno: Observable; + yes: () => void; + no: () => void; + close: () => void; constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: ModalData) { this.subscription = null; + this.resetCallbacks(); + // Notifies on case of yes or not to subscriber + this.yesno = new Observable((observer) => { + this.yes = () => { + 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() { + this.yes = this.no = () => { this.close(); }; + this.close = () => { this.doClose(); }; + } /** * Invoked on closed modal component @@ -33,7 +69,7 @@ export class ModalComponent implements OnInit { } } - close(): void { + doClose(): void { this.dialogRef.close(); } @@ -45,7 +81,7 @@ export class ModalComponent implements OnInit { this.extra = ' (' + Math.floor(miliseconds / 1000) + ' ' + django.gettext('seconds') + ') '; } - ngOnInit() { + initAlert() { if (this.data.autoclose > 0) { this.dialogRef.afterClosed().subscribe(res => { this.closed(); @@ -64,4 +100,16 @@ export class ModalComponent implements OnInit { } } + initYesNo() { + // data.autoclose is not used + } + + ngOnInit() { + if ( this.data.type === DialogType.yesno ) { + this.initYesNo(); + } else { + this.initAlert(); + } + } + } diff --git a/src/app/gui/navbar/navbar.component.html b/src/app/gui/navbar/navbar.component.html index 76ef883..ed4c877 100644 --- a/src/app/gui/navbar/navbar.component.html +++ b/src/app/gui/navbar/navbar.component.html @@ -12,9 +12,8 @@ - - + diff --git a/src/app/gui/uds-gui.service.ts b/src/app/gui/uds-gui.service.ts index f14349e..b23d70b 100644 --- a/src/app/gui/uds-gui.service.ts +++ b/src/app/gui/uds-gui.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -import { ModalComponent, ModalData } from './modal/modal.component'; +import { ModalComponent, DialogType } from './modal/modal.component'; import { MatDialog } from '@angular/material'; @Injectable() @@ -12,8 +12,19 @@ export class UDSGuiService { const width = window.innerWidth < 800 ? '80%' : '40%'; const dialogRef = this.dialog.open(ModalComponent, { width: width, - data: { title: title, body: message, autoclose: autoclose }, + data: { title: title, body: message, autoclose: autoclose, type: DialogType.alert }, disableClose: true, }); } + + yesno(title: string, message: string) { + const width = window.innerWidth < 800 ? '80%' : '40%'; + const dialogRef = this.dialog.open(ModalComponent, { + width: width, + data: { title: title, body: message, type: DialogType.yesno }, + disableClose: true, + }); + + return dialogRef.componentInstance.yesno; + } } diff --git a/src/app/helpers/plugin.ts b/src/app/helpers/plugin.ts index cea2694..c85dd8c 100644 --- a/src/app/helpers/plugin.ts +++ b/src/app/helpers/plugin.ts @@ -50,7 +50,7 @@ export class Plugin { this.api.enabler(params[0], params[1]).subscribe(data => { if (data.error !== undefined && data.error !== '') { // TODO: show the error correctly - alert(data.error); + this.api.gui.alert(django.gettext('Error launching service'), data.error); } else { if (window.location.protocol === 'https:') { // Ensures that protocol is https also for plugin, fixing if needed UDS provided info diff --git a/src/app/translate.directive.ts b/src/app/translate.directive.ts index 9300aff..0234f79 100644 --- a/src/app/translate.directive.ts +++ b/src/app/translate.directive.ts @@ -9,8 +9,9 @@ export class TranslateDirective implements OnInit { constructor(private el: ElementRef) { } ngOnInit() { - // Simply substitute outer html with translation - this.el.nativeElement.outerHTML = django.gettext(this.el.nativeElement.innerHTML); + // Simply substitute innter html with translation + + this.el.nativeElement.innerHTML = django.gettext(this.el.nativeElement.innerHTML); } } diff --git a/src/app/types/config.ts b/src/app/types/config.ts index e9aff9f..410c15a 100644 --- a/src/app/types/config.ts +++ b/src/app/types/config.ts @@ -23,6 +23,8 @@ export interface UDSUrls { readonly services: string; readonly admin: string; readonly enabler: string; + readonly resetter: string; + readonly releaser: string; readonly galleryImage: string; readonly transportIcon: string; } diff --git a/src/app/uds-api.service.ts b/src/app/uds-api.service.ts index e175e11..34ab0b0 100644 --- a/src/app/uds-api.service.ts +++ b/src/app/uds-api.service.ts @@ -3,7 +3,7 @@ import { HttpClient } from '@angular/common/http'; import { Router } from '@angular/router'; import { User, UDSConfig, Downloadable } from './types/config'; import { Observable } from 'rxjs'; -import { JSONServicesInformation, JSONEnabledService } from './types/services'; +import { JSONServicesInformation, JSONEnabledService, JSONService } from './types/services'; import { UDSGuiService } from './gui/uds-gui.service'; import { Plugin } from './helpers/plugin'; @@ -41,6 +41,18 @@ export class UDSApiService { return this.http.get(enabler); } + /* Services resetter */ + resetter(serviceId: string) { + const resetter = this.config.urls.resetter.replace('param1', serviceId); + return this.http.get(resetter); + } + + /* Services resetter */ + releaser(serviceId: string) { + const releaser = this.config.urls.resetter.replace('param1', serviceId); + return this.http.get(releaser); + } + /* Images & static related */ galleryImageURL(imageId: string) { return this.config.urls.galleryImage.replace('param1', imageId); diff --git a/src/styles.css b/src/styles.css index a04366b..233d526 100644 --- a/src/styles.css +++ b/src/styles.css @@ -16,3 +16,7 @@ i.material-icons { vertical-align: middle !important; } +/* colors for remmarks */ +.highlight { + color: red; +} \ No newline at end of file