@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
212 lines (207 loc) • 18.3 kB
JavaScript
import * as i0 from '@angular/core';
import { Input, Component } from '@angular/core';
import * as i3 from '@c8y/ngx-components';
import { CoreModule, gettext as gettext$1, C8yTranslatePipe, TitleComponent, ActionBarItemComponent, C8yTranslateDirective, IconDirective, LoadingComponent } from '@c8y/ngx-components';
import * as i1$1 from '@c8y/ngx-components/remote-access/data';
import * as i2$1 from '@angular/router';
import * as i4 from '@angular/common';
import { NgIf, NgClass } from '@angular/common';
import { saveAs } from 'file-saver';
import * as i2 from 'ngx-bootstrap/modal';
import * as i1 from '@angular/forms';
import { Validators } from '@angular/forms';
import { gettext } from '@c8y/ngx-components/gettext';
import { BehaviorSubject, combineLatest, defer } from 'rxjs';
import { filter, map, distinctUntilChanged } from 'rxjs/operators';
class VncCredentialsPromptComponent {
constructor(formBuilder, modalRef) {
this.formBuilder = formBuilder;
this.modalRef = modalRef;
this.title = gettext('VNC credentials');
this.types = [];
this.result = new Promise((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
});
this.showUsername = false;
this.form = this.initForm();
}
ngOnInit() {
this.showUsername = this.types.includes('username');
this.form = this.initForm();
}
initForm() {
return this.formBuilder.group({
username: [undefined, this.showUsername ? [Validators.required] : []],
password: [undefined, [Validators.required]]
});
}
cancel() {
this._reject();
}
save() {
this._resolve(this.form.value);
}
submit() {
if (!this.form.valid) {
return;
}
this.modalRef.hide();
this.save();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncCredentialsPromptComponent, deps: [{ token: i1.FormBuilder }, { token: i2.BsModalRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: VncCredentialsPromptComponent, isStandalone: true, selector: "c8y-vnc-credentials-prompt", inputs: { types: "types" }, ngImport: i0, template: "<c8y-modal\n [title]=\"title\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [disabled]=\"form.invalid\"\n [labels]=\"{ cancel: 'Cancel', ok: 'Save' }\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'key'\"></span>\n </ng-container>\n <form\n class=\"p-24\"\n [formGroup]=\"form\"\n (submit)=\"submit()\"\n >\n <c8y-form-group *ngIf=\"showUsername\">\n <label\n for=\"username\"\n translate\n >\n Username\n </label>\n <input\n class=\"form-control\"\n id=\"username\"\n name=\"username\"\n type=\"text\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 'admin' }\"\n formControlName=\"username\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label\n for=\"password\"\n translate\n >\n Password\n </label>\n <input\n class=\"form-control\"\n id=\"password\"\n name=\"password\"\n type=\"password\"\n formControlName=\"password\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n\n <button type=\"submit\" class=\"hidden\">hidden submit</button>\n </form>\n</c8y-modal>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i3.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i3.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: i3.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i3.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncCredentialsPromptComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-vnc-credentials-prompt', standalone: true, imports: [CoreModule, NgIf], template: "<c8y-modal\n [title]=\"title\"\n [headerClasses]=\"'dialog-header'\"\n (onDismiss)=\"cancel()\"\n (onClose)=\"save()\"\n [disabled]=\"form.invalid\"\n [labels]=\"{ cancel: 'Cancel', ok: 'Save' }\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'key'\"></span>\n </ng-container>\n <form\n class=\"p-24\"\n [formGroup]=\"form\"\n (submit)=\"submit()\"\n >\n <c8y-form-group *ngIf=\"showUsername\">\n <label\n for=\"username\"\n translate\n >\n Username\n </label>\n <input\n class=\"form-control\"\n id=\"username\"\n name=\"username\"\n type=\"text\"\n [placeholder]=\"'e.g. {{ example }}' | translate: { example: 'admin' }\"\n formControlName=\"username\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n\n <c8y-form-group>\n <label\n for=\"password\"\n translate\n >\n Password\n </label>\n <input\n class=\"form-control\"\n id=\"password\"\n name=\"password\"\n type=\"password\"\n formControlName=\"password\"\n />\n <c8y-messages></c8y-messages>\n </c8y-form-group>\n\n <button type=\"submit\" class=\"hidden\">hidden submit</button>\n </form>\n</c8y-modal>\n" }]
}], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i2.BsModalRef }], propDecorators: { types: [{
type: Input
}] } });
class VncViewerComponent {
constructor(remoteAccess, activatedRoute, modalService) {
this.remoteAccess = remoteAccess;
this.activatedRoute = activatedRoute;
this.modalService = modalService;
this.titlePrefix = gettext$1('VNC viewer');
this.title = '';
this.container = null;
this.powerCapability = false;
this.status = 'connecting';
this.container$ = new BehaviorSubject(null);
const container$ = this.container$.pipe(filter(Boolean));
const configurationId$ = this.activatedRoute.params.pipe(map(params => params.configurationId), filter(Boolean), distinctUntilChanged());
const deviceId$ = this.activatedRoute.parent.params.pipe(map(params => params.id), filter(Boolean), distinctUntilChanged());
this.connectionSubscription = combineLatest([
container$,
deviceId$,
configurationId$,
defer(() => this.getNoVNCClient())
]).subscribe(([container, deviceId, configurationId, noVNC]) => {
this.disconnectFromOldSession();
this.connect(container, deviceId, configurationId, noVNC);
});
}
ngOnDestroy() {
this.connectionSubscription?.unsubscribe();
this.disconnectFromOldSession();
}
ngAfterViewInit() {
this.container$.next(document.getElementById('vnc-screen'));
}
disconnectFromOldSession() {
this.powerCapability = false;
this.title = '';
if (!this.noVNCClient) {
return;
}
this.noVNCClient.disconnect();
delete this.noVNCClient;
}
connect(container, deviceId, configId, noVNC) {
this.container = container;
this.changeStatus('connecting');
const options = {
wsProtocols: ['binary']
};
const uri = this.remoteAccess.getWebSocketUri(deviceId, configId);
this.noVNCClient = new noVNC(container, uri, options);
this.noVNCClient.resizeSession = true;
this.noVNCClient.scaleViewport = true;
this.noVNCClient.showDotCursor = true;
this.noVNCClient.viewOnly = false;
this.noVNCClient.qualityLevel = 6;
// need to set compressionLevel to something different than the default 2 as 2 seems to be causing issues..
this.noVNCClient.compressionLevel = 9;
this.noVNCClient.addEventListener('connect', _e => {
this.changeStatus('connected');
this.noVNCClient.focus();
});
this.noVNCClient.addEventListener('credentialsrequired', e => {
this.requestCredentials(e.detail.types);
});
this.noVNCClient.addEventListener('desktopname', e => {
this.title = e.detail.name;
});
this.noVNCClient.addEventListener('disconnect', () => {
this.changeStatus('disconnected');
});
this.noVNCClient.addEventListener('capabilities', e => {
this.powerCapability = e.detail.capabilities.power;
});
}
downloadScreenshot() {
this.noVNCClient.toBlob(blob => {
const date = new Date().toISOString();
saveAs(blob, `screenshot-${this.title}-${date}.png`);
}, 'image/png', 1);
}
changeStatus(status) {
this.status = status;
}
toggleFullscreen() {
if (document.fullscreenElement) {
document.exitFullscreen();
}
else {
this.container.requestFullscreen();
}
}
sendCtrlAltDel() {
this.noVNCClient.sendCtrlAltDel();
}
sendShutDown() {
this.noVNCClient.machineShutdown();
}
sendReset() {
this.noVNCClient.machineReset();
}
sendReboot() {
this.noVNCClient.machineReboot();
}
async getNoVNCClient() {
const lib = await import('@novnc/novnc/lib/rfb');
if (typeof lib.default === 'function') {
return lib.default;
}
const libDefault = lib.default;
if (typeof libDefault.default === 'function') {
return libDefault.default;
}
throw new Error('NoVNC library not found');
}
async requestCredentials(types) {
const modalRef = this.modalService.show(VncCredentialsPromptComponent, {
ignoreBackdropClick: true,
keyboard: false,
initialState: { types: types }
});
try {
const { username, password } = await modalRef.content.result;
this.noVNCClient.sendCredentials({ username, password, target: undefined });
}
catch (e) {
this.noVNCClient.disconnect();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncViewerComponent, deps: [{ token: i1$1.RemoteAccessService }, { token: i2$1.ActivatedRoute }, { token: i2.BsModalService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: VncViewerComponent, isStandalone: true, selector: "c8y-vnc-viewer", ngImport: i0, template: "<c8y-title>{{ titlePrefix | translate }}: {{ title | translate }}</c8y-title>\n\n<ng-container *ngIf=\"status === 'connected'\">\n <c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n (click)=\"toggleFullscreen()\"\n >\n <i [c8yIcon]=\"'expand'\"></i>\n <span translate>Fullscreen</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n (click)=\"downloadScreenshot()\"\n >\n <i [c8yIcon]=\"'download'\"></i>\n <span translate>Screenshot</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendCtrlAltDel()\"\n >\n <i [c8yIcon]=\"'keyboard'\"></i>\n <span translate>Send Ctrl+Alt+Del</span>\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<ng-container *ngIf=\"powerCapability && status === 'connected'\">\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendShutDown()\"\n >\n <i [c8yIcon]=\"'shutdown'\"></i>\n <span translate>Shutdown</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendReboot()\"\n >\n <i [c8yIcon]=\"'reset'\"></i>\n <span translate>Reboot</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendReset()\"\n >\n <i [c8yIcon]=\"'reset'\"></i>\n <span translate>Reset</span>\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<c8y-loading *ngIf=\"status === 'connecting'\"></c8y-loading>\n\n<div\n class=\"content-fullpage\"\n [ngClass]=\"{ hidden: status !== 'connected' }\"\n>\n <div\n class=\"inner-scroll\"\n id=\"vnc-screen\"\n ></div>\n</div>\n", dependencies: [{ kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: VncViewerComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-vnc-viewer', standalone: true, imports: [
C8yTranslatePipe,
TitleComponent,
ActionBarItemComponent,
C8yTranslateDirective,
IconDirective,
NgIf,
NgClass,
LoadingComponent
], template: "<c8y-title>{{ titlePrefix | translate }}: {{ title | translate }}</c8y-title>\n\n<ng-container *ngIf=\"status === 'connected'\">\n <c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n (click)=\"toggleFullscreen()\"\n >\n <i [c8yIcon]=\"'expand'\"></i>\n <span translate>Fullscreen</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n (click)=\"downloadScreenshot()\"\n >\n <i [c8yIcon]=\"'download'\"></i>\n <span translate>Screenshot</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendCtrlAltDel()\"\n >\n <i [c8yIcon]=\"'keyboard'\"></i>\n <span translate>Send Ctrl+Alt+Del</span>\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<ng-container *ngIf=\"powerCapability && status === 'connected'\">\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendShutDown()\"\n >\n <i [c8yIcon]=\"'shutdown'\"></i>\n <span translate>Shutdown</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendReboot()\"\n >\n <i [c8yIcon]=\"'reset'\"></i>\n <span translate>Reboot</span>\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item [placement]=\"'more'\">\n <button\n class=\"btn btn-link\"\n (click)=\"sendReset()\"\n >\n <i [c8yIcon]=\"'reset'\"></i>\n <span translate>Reset</span>\n </button>\n </c8y-action-bar-item>\n</ng-container>\n\n<c8y-loading *ngIf=\"status === 'connecting'\"></c8y-loading>\n\n<div\n class=\"content-fullpage\"\n [ngClass]=\"{ hidden: status !== 'connected' }\"\n>\n <div\n class=\"inner-scroll\"\n id=\"vnc-screen\"\n ></div>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1$1.RemoteAccessService }, { type: i2$1.ActivatedRoute }, { type: i2.BsModalService }] });
/**
* Generated bundle index. Do not edit.
*/
export { VncViewerComponent };
//# sourceMappingURL=c8y-ngx-components-remote-access-vnc-vnc-viewer.mjs.map