mirror of
https://github.com/dkmstr/openuds-gui.git
synced 2024-12-21 13:33:48 +03:00
fixing and refactoring frontend
This commit is contained in:
parent
6bb8239e84
commit
23389fca6a
@ -5,8 +5,7 @@
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
> 0.2%
|
||||
> 0.2% and not dead
|
||||
last 2 versions
|
||||
last 4 years
|
||||
Firefox ESR
|
||||
not dead
|
||||
|
7
.hintrc
7
.hintrc
@ -7,5 +7,10 @@
|
||||
"axe/text-alternatives": "off",
|
||||
"button-type": "off",
|
||||
"typescript-config/consistent-casing": "off"
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults",
|
||||
"not ie 11",
|
||||
"not ie <= 10"
|
||||
]
|
||||
}
|
@ -51,7 +51,7 @@ export class ModalComponent implements OnInit {
|
||||
this.extra = ' (' + Math.floor(miliseconds / 1000) + ' ' + django.gettext('seconds') + ') ';
|
||||
}
|
||||
|
||||
async initAlert(): Promise<void> {
|
||||
async initAlert() {
|
||||
const autoclose = this.data.autoclose || 0;
|
||||
if (autoclose > 0) {
|
||||
this.dialogRef.afterClosed().subscribe((res) => {
|
||||
|
@ -15,7 +15,7 @@ export class Plugin {
|
||||
this.delay = api.config.launcher_wait_time;
|
||||
}
|
||||
|
||||
async launchURL(url: string): Promise<void> {
|
||||
async launchURL(url: string) {
|
||||
// If uds url...
|
||||
if (url.substring(0, 7) === 'udsa://') {
|
||||
await this.processUDSUrl(url);
|
||||
@ -45,27 +45,7 @@ export class Plugin {
|
||||
* @param url uds url to be lauhcned
|
||||
*/
|
||||
private launchUDSUrl(url: string) {
|
||||
let elem: HTMLIFrameElement = document.getElementById(
|
||||
'hiddenUdsLauncherIFrame'
|
||||
) as HTMLIFrameElement;
|
||||
if (elem === null) {
|
||||
const i = document.createElement('div');
|
||||
i.id = 'testID';
|
||||
i.innerHTML =
|
||||
'<iframe id="hiddenUdsLauncherIFrame" src="about:blank" style="display:none"></iframe>';
|
||||
document.body.appendChild(i);
|
||||
elem = document.getElementById(
|
||||
'hiddenUdsLauncherIFrame'
|
||||
) as HTMLIFrameElement;
|
||||
}
|
||||
// Ensure all is ok
|
||||
if (elem === null) {
|
||||
throw new Error('Unable to create hidden iframe');
|
||||
}
|
||||
if (elem.contentWindow === null) {
|
||||
throw new Error('Unable to get content window');
|
||||
}
|
||||
elem.contentWindow.location.href = url;
|
||||
this.api.download(url);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,7 +54,7 @@ export class Plugin {
|
||||
* @param url uds url (udsa://serviceId/transportId)
|
||||
* @returns nothing
|
||||
*/
|
||||
private async processUDSUrl(url: string): Promise<void> {
|
||||
private async processUDSUrl(url: string) {
|
||||
// Extract params from url, serviceId and transportId
|
||||
const params = url.split('//')[1].split('/');
|
||||
if (params.length !== 2) {
|
||||
@ -96,7 +76,7 @@ export class Plugin {
|
||||
// Connect close dialog to "cancel" variable
|
||||
toPromise(dialog.afterClosed()).then(() => (cancel = true));
|
||||
|
||||
let readyTime = -1;
|
||||
let readySinceTime = -1;
|
||||
try {
|
||||
// Enable service
|
||||
const enabledData = await this.api.enabler(serviceId, transportId);
|
||||
@ -119,7 +99,7 @@ export class Plugin {
|
||||
while (!cancel) {
|
||||
const data = await this.api.status(serviceId, transportId);
|
||||
// Wait 5 times the default delay before notifying that client is not installed
|
||||
if (readyTime > 0 && Date.now() - readyTime > this.delay * 5) {
|
||||
if (readySinceTime > 0 && Date.now() - readySinceTime > this.delay * 5) {
|
||||
dialog.componentInstance.data.title =
|
||||
django.gettext('Service ready') +
|
||||
' - ' +
|
||||
@ -137,9 +117,9 @@ export class Plugin {
|
||||
'</a>';
|
||||
}
|
||||
if (data.status === 'ready') {
|
||||
if (readyTime === -1) {
|
||||
if (readySinceTime === -1) {
|
||||
// Service is ready, wait for client, update dialog text
|
||||
readyTime = Date.now(); // Milisecodns
|
||||
readySinceTime = Date.now(); // Milisecodns
|
||||
dialog.componentInstance.data.title =
|
||||
django.gettext('Service ready');
|
||||
dialog.componentInstance.data.body = django.gettext(
|
||||
@ -167,7 +147,7 @@ export class Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
private async processExternalUrl(url: string): Promise<void> {
|
||||
private async processExternalUrl(url: string) {
|
||||
const dialog = await this.showAlert(
|
||||
django.gettext('Please wait until the service is launched.'),
|
||||
django.gettext(
|
||||
@ -281,7 +261,7 @@ export class Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
private async notifyError(error?: any): Promise<void> {
|
||||
private async notifyError(error?: any) {
|
||||
let msg: string = django.gettext(
|
||||
'Error communicating with your service. Please, retry again.'
|
||||
);
|
||||
|
@ -1,8 +1,8 @@
|
||||
<div class="about">
|
||||
<h1>Universal Desktop Services {{ api.config.version }} build {{ api.config.version_stamp }}</h1>
|
||||
<h3><a href="http://www.udsenterprise.com" target="_blank"> © 2012-{{ year }} Virtual Cable S.L.U.</a></h3>
|
||||
<h3><a rel="noopener noreferrer" href="http://www.udsenterprise.com" target="_blank"> © 2012-{{ year }} Virtual Cable S.L.U.</a></h3>
|
||||
<h4>
|
||||
<uds-translate>You can access UDS Open Source code at</uds-translate> <a href="https://github.com/dkmstr/openuds"
|
||||
<uds-translate>You can access UDS Open Source code at</uds-translate> <a rel="noopener noreferrer" href="https://github.com/dkmstr/openuds"
|
||||
target="_blank">OpenUDS github repository</a>
|
||||
</h4>
|
||||
<div class="components">
|
||||
@ -10,15 +10,15 @@
|
||||
<uds-translate>UDS has been developed using these components:</uds-translate>
|
||||
</h2>
|
||||
<ul>
|
||||
<li><a href="https://www.python.org/">Python</a></li>
|
||||
<li><a href="https://www.typescriptlang.org/" target="_blank">TypeScript</a></li>
|
||||
<li><a href="https://www.djangoproject.com/" target="_blank">Django</a></li>
|
||||
<li><a href="https://angular.io" target="_blank">Angular</a></li>
|
||||
<li><a href="https://guac-dev.org/" target="_blank">Guacamole</a></li>
|
||||
<li><a href="https://weasyprint.org/" target="_blank">weasyprint</a></li>
|
||||
<li><a href="https://kde-look.org/content/show.php/Crystal+Project?content=60475)" target="_blank">Crystal project
|
||||
<li><a rel="noopener noreferrer" href="https://www.python.org/" target="_blank">Python</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://www.typescriptlang.org/" target="_blank">TypeScript</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://www.djangoproject.com/" target="_blank">Django</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://angular.io" target="_blank">Angular</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://guac-dev.org/" target="_blank">Guacamole</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://weasyprint.org/" target="_blank">weasyprint</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://kde-look.org/content/show.php/Crystal+Project?content=60475)" target="_blank">Crystal project
|
||||
icons</a></li>
|
||||
<li><a href="https://github.com/NitruxSA/flattr-icons" target="_blank">Flattr Icons</a></li>
|
||||
<li><a rel="noopener noreferrer" href="https://github.com/NitruxSA/flattr-icons" target="_blank">Flattr Icons</a></li>
|
||||
</ul>
|
||||
<p><small>* <uds-translate>If you find that we missed any component, please let us know</uds-translate></small></p>
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@
|
||||
</div>
|
||||
|
||||
<div class="plugins">
|
||||
<div [class]="css(p)" *ngFor="let p of api.plugins" (click)="download(p.url)">
|
||||
<div [class]="css(p)" *ngFor="let p of api.plugins" (click)="api.download(p.url)">
|
||||
<div class="image">
|
||||
<img [src]="img(p.name)">
|
||||
</div>
|
||||
|
@ -15,10 +15,6 @@ export class ClientDownloadComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
download(url: string) {
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
img(image: string) {
|
||||
return this.api.staticURL( 'modern/img/' + image + '.png');
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
</div>
|
||||
|
||||
<div class="actors">
|
||||
<div [class]="css(p.name)" *ngFor="let p of actors" (click)="download(p.url)">
|
||||
<div [class]="css(p.name)" *ngFor="let p of actors" (click)="api.download(p.url)">
|
||||
<div class="image">
|
||||
<img [src]="img(p.name)">
|
||||
</div>
|
||||
|
@ -5,31 +5,27 @@ import { Downloadable } from '../../types/config';
|
||||
@Component({
|
||||
selector: 'uds-downloads',
|
||||
templateUrl: './downloads.component.html',
|
||||
styleUrls: ['./downloads.component.scss']
|
||||
styleUrls: ['./downloads.component.scss'],
|
||||
})
|
||||
export class DownloadsComponent implements OnInit {
|
||||
|
||||
actors: Downloadable[] = [];
|
||||
|
||||
constructor(public api: UDSApiService) { }
|
||||
constructor(public api: UDSApiService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.actors = []; // Put legacy at end of downloadables...
|
||||
// Sort legacy actors to the end of the list
|
||||
this.actors = []; // Put legacy at end of downloadables...
|
||||
const legacy: Downloadable[] = [];
|
||||
this.api.actors.forEach(a => {
|
||||
for (const a of this.api.actors) {
|
||||
if (a.name.includes('legacy')) {
|
||||
legacy.push(a);
|
||||
} else {
|
||||
this.actors.push(a);
|
||||
}
|
||||
});
|
||||
legacy.forEach(l => {
|
||||
}
|
||||
for (const l of legacy) {
|
||||
this.actors.push(l);
|
||||
});
|
||||
}
|
||||
|
||||
download(url: string) {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
img(filename: string) {
|
||||
@ -52,5 +48,4 @@ export class DownloadsComponent implements OnInit {
|
||||
}
|
||||
return styles;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ export class ErrorComponent implements OnInit {
|
||||
await this.getError();
|
||||
}
|
||||
|
||||
async getError(): Promise<void> {
|
||||
async getError() {
|
||||
const id = this.route.snapshot.paramMap.get('id') || '-1';
|
||||
if (id === '19') { // 19 is MFA error, return to MFA
|
||||
this.returnUrl = '/mfa';
|
||||
|
@ -42,6 +42,9 @@ export interface UDSApiServiceType {
|
||||
/* Executes logout */
|
||||
logout(): void;
|
||||
|
||||
/* Download file/launches a custom uro */
|
||||
download(url: string): Promise<void>;
|
||||
|
||||
/* sleep milliseconds */
|
||||
sleep(ms: number): Promise<void>;
|
||||
/**
|
||||
|
@ -19,7 +19,6 @@ import { UDSApiServiceType } from './uds-api.service-type';
|
||||
|
||||
import { environment } from '../environments/environment';
|
||||
|
||||
|
||||
const DARK_THEME = 'dark-theme';
|
||||
const LIGHT_THEME = 'light-theme';
|
||||
const TIMEOUT = 10000;
|
||||
@ -32,14 +31,10 @@ const toPromise = <T>(observable: Observable<T>, wait?: number): Promise<T> => {
|
||||
@Injectable()
|
||||
export class UDSApiService implements UDSApiServiceType {
|
||||
readonly user: User;
|
||||
transportsWindow: Window|null = null;
|
||||
transportsWindow: Window | null = null;
|
||||
plugin: Plugin;
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
public gui: UDSGuiService,
|
||||
public router: Router
|
||||
) {
|
||||
constructor(private http: HttpClient, public gui: UDSGuiService, public router: Router) {
|
||||
this.user = new User(udsData.profile);
|
||||
this.plugin = new Plugin(this);
|
||||
}
|
||||
@ -91,32 +86,20 @@ export class UDSApiService implements UDSApiServiceType {
|
||||
}
|
||||
|
||||
/* Client enabler */
|
||||
async enabler(
|
||||
serviceId: string,
|
||||
transportId: string
|
||||
): Promise<JSONEnabledService> {
|
||||
const enabler = this.config.urls.enabler
|
||||
.replace('param1', serviceId)
|
||||
.replace('param2', transportId);
|
||||
async enabler(serviceId: string, transportId: string): Promise<JSONEnabledService> {
|
||||
const enabler = this.config.urls.enabler.replace('param1', serviceId).replace('param2', transportId);
|
||||
return toPromise(this.http.get<JSONEnabledService>(enabler));
|
||||
}
|
||||
|
||||
/* Check userService status */
|
||||
async status(
|
||||
serviceId: string,
|
||||
transportId: string
|
||||
): Promise<JSONStatusService> {
|
||||
const status = this.config.urls.status
|
||||
.replace('param1', serviceId)
|
||||
.replace('param2', transportId);
|
||||
async status(serviceId: string, transportId: string): Promise<JSONStatusService> {
|
||||
const status = this.config.urls.status.replace('param1', serviceId).replace('param2', transportId);
|
||||
return toPromise(this.http.get<JSONStatusService>(status));
|
||||
}
|
||||
|
||||
/* Services resetter */
|
||||
async action(action: string, serviceId: string): Promise<JSONService> {
|
||||
const actionURL = this.config.urls.action
|
||||
.replace('param1', serviceId)
|
||||
.replace('param2', action);
|
||||
const actionURL = this.config.urls.action.replace('param1', serviceId).replace('param2', action);
|
||||
return toPromise(this.http.get<JSONService>(actionURL));
|
||||
}
|
||||
|
||||
@ -131,9 +114,7 @@ export class UDSApiService implements UDSApiServiceType {
|
||||
password: string,
|
||||
domain: string
|
||||
): Promise<any> {
|
||||
const url = this.config.urls.updateTransportTicket
|
||||
.replace('param1', ticketId)
|
||||
.replace('param2', scrambler);
|
||||
const url = this.config.urls.updateTransportTicket.replace('param1', ticketId).replace('param2', scrambler);
|
||||
return toPromise(
|
||||
this.http.post<any>(url, {
|
||||
username,
|
||||
@ -164,20 +145,14 @@ export class UDSApiService implements UDSApiServiceType {
|
||||
* Gets services information
|
||||
*/
|
||||
async getServicesInformation(): Promise<JSONServicesInformation> {
|
||||
return toPromise(
|
||||
this.http.get<JSONServicesInformation>(this.config.urls.services)
|
||||
);
|
||||
return toPromise(this.http.get<JSONServicesInformation>(this.config.urls.services));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets error string from a code
|
||||
*/
|
||||
async getErrorInformation(errorCode: string): Promise<JSONErrorInformation> {
|
||||
return toPromise(
|
||||
this.http.get<JSONErrorInformation>(
|
||||
this.config.urls.error.replace('9999', errorCode)
|
||||
)
|
||||
);
|
||||
return toPromise(this.http.get<JSONErrorInformation>(this.config.urls.error.replace('9999', errorCode)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,6 +175,28 @@ export class UDSApiService implements UDSApiServiceType {
|
||||
window.location.href = this.config.urls.logout;
|
||||
}
|
||||
|
||||
async download(url: string): Promise<void> {
|
||||
// Launch the download
|
||||
// Create an iframe and set the src to the url
|
||||
// This will trigger the download
|
||||
// First, loof for an existing download iframe
|
||||
let iframe = document.getElementById('download') as HTMLIFrameElement;
|
||||
// If not found, create it
|
||||
if (!iframe) {
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.id = 'download';
|
||||
iframe.style.display = 'none';
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
// Set the src to the url
|
||||
iframe.src = url;
|
||||
// onload in iframe will only be triggered if an html page is downloaded. If it is loaded, it's not a download
|
||||
iframe.onload = () => {
|
||||
alert('Error downloading file. Please try again later.');
|
||||
};
|
||||
//window.location.href = url;
|
||||
}
|
||||
|
||||
sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
@ -215,9 +212,7 @@ export class UDSApiService implements UDSApiServiceType {
|
||||
* @returns Observable
|
||||
*/
|
||||
async getAuthCustomJavascript(authId: string): Promise<string> {
|
||||
return toPromise(
|
||||
this.http.get(this.config.urls.customAuth + authId, {responseType: 'text'})
|
||||
);
|
||||
return toPromise(this.http.get(this.config.urls.customAuth + authId, { responseType: 'text' }));
|
||||
}
|
||||
|
||||
// Switch dark/light theme
|
||||
|
Loading…
Reference in New Issue
Block a user