From 20415d2e7b0e14ac9d3d33d51ac599e7955e8a89 Mon Sep 17 00:00:00 2001 From: zhaojisen <1301338853@qq.com> Date: Tue, 5 Nov 2024 16:33:59 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fixed=EF=BC=9AFixed=20an=20issue=20where=20?= =?UTF-8?q?anonymous=20accounts=20could=20not=20download=20rdp=20files=20u?= =?UTF-8?q?nder=20Web=20assets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../connect-dialog/connect-method/connect-method.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/elements/connect/connect-dialog/connect-method/connect-method.component.ts b/src/app/elements/connect/connect-dialog/connect-method/connect-method.component.ts index b5494d3f..6a22000a 100644 --- a/src/app/elements/connect/connect-dialog/connect-method/connect-method.component.ts +++ b/src/app/elements/connect/connect-dialog/connect-method/connect-method.component.ts @@ -97,7 +97,7 @@ export class ElementConnectMethodComponent implements OnInit { return false; } if (this.account && !this.account.has_secret) { - const aliases = ['@USER', '@INPUT']; + const aliases = ['@USER', '@INPUT', '@ANON']; // 同名账号、手动输入可以下载RDP文件 if (!aliases.includes(this.account.alias) || (!this.manualAuthInfo.username)) { return false; From 08ffb72155aae05b84aaef60f06431a70a771b75 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:41:38 +0800 Subject: [PATCH 2/9] feat: Add dynamic form and variable command dialog (#1176) * feat: Add dynamic form and variable command dialog * perf: Translate --------- Co-authored-by: wangruidong <940853815@qq.com> --- src/app/app.module.ts | 4 ++ .../elements/content/content.component.html | 1 + .../elements/content/content.component.scss | 5 +- src/app/elements/content/content.component.ts | 22 +++++++- ...ommand-with-variable-dialog.component.html | 7 +++ ...-command-with-variable-dialog.component.ts | 34 +++++++++++++ .../dynamic-form.service.ts | 21 ++++++++ .../variable-dynamic-form.component.html | 27 ++++++++++ .../variable-dynamic-form.component.scss | 11 ++++ .../variable-dynamic-form.component.ts | 50 +++++++++++++++++++ src/app/elements/elements.component.ts | 4 ++ 11 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.html create mode 100644 src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.ts create mode 100644 src/app/elements/content/variable-dynamic-form/dynamic-form.service.ts create mode 100644 src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html create mode 100644 src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss create mode 100644 src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 5cfd13db..971805b2 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -36,6 +36,8 @@ import {ClipboardService} from 'ngx-clipboard'; import {ElementsReplayMp4Component} from './elements/replay/mp4/mp4.component'; import {ElementCommandDialogComponent} from '@app/elements/content/command-dialog/command-dialog.component'; import {ElementSendCommandDialogComponent} from '@app/elements/content/send-command-dialog/send-command-dialog.component'; +import {ElementSendCommandWithVariableDialogComponent} from '@app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component'; +import {DynamicFormComponent} from '@app/elements/content/variable-dynamic-form/variable-dynamic-form.component'; import {version} from '../environments/environment'; import {BehaviorSubject, forkJoin, Observable, of} from 'rxjs'; import {catchError, mergeMap} from 'rxjs/operators'; @@ -115,6 +117,8 @@ export class CustomLoader implements TranslateLoader { ElementDialogAlertComponent, ElementCommandDialogComponent, ElementSendCommandDialogComponent, + DynamicFormComponent, + ElementSendCommandWithVariableDialogComponent ], bootstrap: [AppComponent], providers: [ diff --git a/src/app/elements/content/content.component.html b/src/app/elements/content/content.component.html index be887b82..f2db3ad6 100644 --- a/src/app/elements/content/content.component.html +++ b/src/app/elements/content/content.component.html @@ -88,6 +88,7 @@ *ngFor="let command of quickCommands" [matTooltip]="command.args" class="command-box" + [ngClass]="{'command-box-variable': command.variable.length !== 0}" matTooltipPosition="above" > diff --git a/src/app/elements/content/content.component.scss b/src/app/elements/content/content.component.scss index 9d903d5d..4e114deb 100644 --- a/src/app/elements/content/content.component.scss +++ b/src/app/elements/content/content.component.scss @@ -217,7 +217,6 @@ $-border-y: var(--el-main-bg-color); user-select: none; color: #d6cbcb; background-color: #463e3e; - &:hover { color: #ffffff; } @@ -226,6 +225,10 @@ $-border-y: var(--el-main-bg-color); color: #ccc8c8; } } + .command-box-variable { + @extend .command-box; + background-color: #6f4f3a; + } } .not-command { diff --git a/src/app/elements/content/content.component.ts b/src/app/elements/content/content.component.ts index 554999bf..69908d42 100644 --- a/src/app/elements/content/content.component.ts +++ b/src/app/elements/content/content.component.ts @@ -4,6 +4,7 @@ import {ConnectTokenService, HttpService, I18nService, LogService, SettingServic import {CdkDragDrop, moveItemInArray} from '@angular/cdk/drag-drop'; import {MatDialog} from '@angular/material'; import {ElementCommandDialogComponent} from '@app/elements/content/command-dialog/command-dialog.component'; +import {ElementSendCommandWithVariableDialogComponent} from '@app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component'; import {fromEvent, Subscription} from 'rxjs'; import * as jQuery from 'jquery/dist/jquery.min.js'; @@ -197,7 +198,26 @@ export class ElementContentComponent implements OnInit, OnDestroy { sendQuickCommand(command) { this.batchCommand = command.args; - this.sendBatchCommand(); + if(command.variable.length>0){ + const dialogRef=this._dialog.open( + ElementSendCommandWithVariableDialogComponent, + { + height: 'auto', + width: '500px', + data: {command:command} + } + ) + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.batchCommand = result + this.sendBatchCommand(); + } + }) + } + else{ + this.sendBatchCommand(); + } + } rMenuItems() { diff --git a/src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.html b/src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.html new file mode 100644 index 00000000..28a9fa44 --- /dev/null +++ b/src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.html @@ -0,0 +1,7 @@ +

+ {{"Send command"| translate}} +

+ +
+ +
diff --git a/src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.ts b/src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.ts new file mode 100644 index 00000000..91754a55 --- /dev/null +++ b/src/app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component.ts @@ -0,0 +1,34 @@ +import {Component, Inject, OnInit} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {HttpService} from '@app/services'; + +@Component({ + selector: 'elements-send-with-variable-command-dialog', + templateUrl: './send-command-with-variable-dialog.component.html', +}) +export class ElementSendCommandWithVariableDialogComponent implements OnInit { + public formConfig = []; + public command = {}; + constructor(public dialogRef: MatDialogRef, + private _http: HttpService, + @Inject(MAT_DIALOG_DATA) public data: any + ) {} + + ngOnInit() { + this.getVariableFormMeta() + } + async getVariableFormMeta() { + const adhoc = this.data.command.id + const url=`/api/v1/ops/variable/form_data/?t=${new Date().getTime()}&adhoc=${adhoc}` + const res: any = await this._http.options(url).toPromise(); + this.formConfig = res.actions.GET; + this.command = this.data.command; + } + onFormSubmitted(data: any) { + setTimeout(() => { + this.dialogRef.close(data.sendCommand); + }); + } + + protected readonly Component = Component; +} diff --git a/src/app/elements/content/variable-dynamic-form/dynamic-form.service.ts b/src/app/elements/content/variable-dynamic-form/dynamic-form.service.ts new file mode 100644 index 00000000..88e678e1 --- /dev/null +++ b/src/app/elements/content/variable-dynamic-form/dynamic-form.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; + +@Injectable({ + providedIn: 'root' +}) +export class DynamicFormService { + createFormGroup(fields: any): FormGroup { + const group: any = {}; + for (const field in fields) { + const fieldDefinition = fields[field]; + const validators = []; + if (fieldDefinition.required) { + validators.push(Validators.required); + } + group['jms_'+field] = new FormControl(fieldDefinition.default || '', validators) + } + group["sendCommand"] = new FormControl("") + return new FormGroup(group); + } +} diff --git a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html new file mode 100644 index 00000000..19a63035 --- /dev/null +++ b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html @@ -0,0 +1,27 @@ +
+
+ + + + {{ formConfig[fieldKey].help_text }} + +
+ + + + {{ choice.label }} + + + {{ formConfig[fieldKey].help_text }} +
+
+ + {{ 'Command'| translate }} + + + +
+ +
+
diff --git a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss new file mode 100644 index 00000000..c69421fc --- /dev/null +++ b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss @@ -0,0 +1,11 @@ +.full-width { + width: 100%; + margin-bottom: 20px; +} + +.radio-group { + margin-bottom: 20px; +} +mat-hint { + font-size: 10px; +} diff --git a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.ts b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.ts new file mode 100644 index 00000000..227764c5 --- /dev/null +++ b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.ts @@ -0,0 +1,50 @@ +import {Component, Input, Output, OnInit, SimpleChanges,EventEmitter} from '@angular/core'; +import {FormGroup} from '@angular/forms'; +import {DynamicFormService} from './dynamic-form.service'; +import * as _ from 'lodash'; + +@Component({ + selector: 'variable-dynamic-form', + templateUrl: './variable-dynamic-form.component.html', + styleUrls: ['./variable-dynamic-form.component.scss'], +}) +export class DynamicFormComponent implements OnInit { + @Input() formConfig: any; + @Input() command: any; + @Output() formSubmitted = new EventEmitter(); + dynamicForm: FormGroup; + fieldKeys: string[]; + constructor(private dynamicFormService: DynamicFormService) {} + ngOnInit(): void { + } + ngOnChanges(changes: SimpleChanges): void { + if (changes['formConfig'] && this.formConfig) { + this.dynamicForm = this.dynamicFormService.createFormGroup(this.formConfig); + this.fieldKeys = Object.keys(this.formConfig); + this.fieldKeys.forEach(fieldKey => { + const control = this.dynamicForm.get(`jms_${fieldKey}`); + if (control) { + control.valueChanges.subscribe(value => { + this.updateTextarea(); + }); + } + }); + } + } + updateTextarea(): void { + _.templateSettings.interpolate = /{{\s*([a-zA-Z0-9_]+)\s*}}/g; + let compiled = _.template(this.command.args); + let context= {} + this.fieldKeys.forEach(fieldKey => { + context[`jms_${fieldKey}`] = this.dynamicForm.get(`jms_${fieldKey}`).value; + }); + const commandText = compiled(context); + this.dynamicForm.get('sendCommand').setValue(commandText); + } + + onSubmit() { + if (this.dynamicForm.valid) { + this.formSubmitted.emit(this.dynamicForm.value); + } + } +} diff --git a/src/app/elements/elements.component.ts b/src/app/elements/elements.component.ts index 17c42fea..6bf554c9 100644 --- a/src/app/elements/elements.component.ts +++ b/src/app/elements/elements.component.ts @@ -30,6 +30,8 @@ import {ElementsReplayMp4Component} from './replay/mp4/mp4.component'; import {ElementConnectorGuideComponent} from '@app/elements/content/content-window/guide/guide.component'; import {ElementCommandDialogComponent} from '@app/elements/content/command-dialog/command-dialog.component'; import {ElementSendCommandDialogComponent} from '@app/elements/content/send-command-dialog/send-command-dialog.component'; +import {ElementSendCommandWithVariableDialogComponent} from '@app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component'; +import {DynamicFormComponent} from '@app/elements/content/variable-dynamic-form/variable-dynamic-form.component'; import {ElementChatComponent} from '@app/elements/chat/chat.component'; import {ElementsPartsComponent} from './replay/parts/parts.component'; @@ -70,5 +72,7 @@ export const ElementComponents = [ ElementConnectorGuideComponent, ElementCommandDialogComponent, ElementSendCommandDialogComponent, + ElementSendCommandWithVariableDialogComponent, + DynamicFormComponent, ElementsPartsComponent, ]; From c39fb532fc2d441e7a39f5015e409f3a35cb0918 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 11 Nov 2024 18:12:08 +0800 Subject: [PATCH 3/9] perf: add nec vnc component --- .../content-view/content-view.component.html | 7 +- .../content-window/nec/nec.component.html | 7 + .../content-window/nec/nec.component.scss | 0 .../content-window/nec/nec.component.ts | 133 ++++++++++++++++++ src/app/elements/elements.component.ts | 3 + 5 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/app/elements/content/content-window/nec/nec.component.html create mode 100644 src/app/elements/content/content-window/nec/nec.component.scss create mode 100644 src/app/elements/content/content-window/nec/nec.component.ts diff --git a/src/app/elements/content/content-window/content-view/content-view.component.html b/src/app/elements/content/content-window/content-view/content-view.component.html index 47f298a3..149cb790 100644 --- a/src/app/elements/content/content-window/content-view/content-view.component.html +++ b/src/app/elements/content/content-window/content-view/content-view.component.html @@ -16,6 +16,11 @@ [view]="view" > + + - \ No newline at end of file + diff --git a/src/app/elements/content/content-window/nec/nec.component.html b/src/app/elements/content/content-window/nec/nec.component.html new file mode 100644 index 00000000..e0412bf1 --- /dev/null +++ b/src/app/elements/content/content-window/nec/nec.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/elements/content/content-window/nec/nec.component.scss b/src/app/elements/content/content-window/nec/nec.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/elements/content/content-window/nec/nec.component.ts b/src/app/elements/content/content-window/nec/nec.component.ts new file mode 100644 index 00000000..f1d698ee --- /dev/null +++ b/src/app/elements/content/content-window/nec/nec.component.ts @@ -0,0 +1,133 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {Account, Asset, ConnectionToken, Endpoint, View} from '@app/model'; +import {ConnectTokenService, HttpService, I18nService, SettingService} from '@app/services'; +import {ToastrService} from 'ngx-toastr'; + +import {Command, InfoItem} from '../guide/model'; +import {User} from '@app/globals'; + +@Component({ + selector: 'elements-connector-nec', + templateUrl: './nec.component.html', + styleUrls: ['./nec.component.scss'] +}) + +export class ElementConnectorNecComponent implements OnInit { + @Input() view: View; + + asset: Asset; + account: Account; + protocol: string; + endpoint: Endpoint; + name: string; + cli: string; + infoItems: Array = []; + info: any; + globalSetting: any; + loading = true; + passwordMask = '******'; + passwordShow = '******'; + token: ConnectionToken; + showSetReusable: boolean; + commands: Array = []; + + constructor(private _http: HttpService, + private _i18n: I18nService, + private _toastr: ToastrService, + private _connectTokenSvc: ConnectTokenService, + private _settingSvc: SettingService + ) { + this.globalSetting = this._settingSvc.globalSetting; + this.showSetReusable = this.globalSetting.CONNECTION_TOKEN_REUSABLE; + } + + async ngOnInit() { + const {asset, account, protocol, smartEndpoint, connectToken} = this.view; + this.token = connectToken; + this.asset = asset; + this.account = account; + this.protocol = protocol; + this.endpoint = smartEndpoint; + + const oriHost = this.asset.address; + this.name = `${this.asset.name}(${oriHost})`; + this.setDBInfo(); + this.genConnCli(); + this.loading = false; + this.view.termComp = this; + } + + setDBInfo() { + const database = this.asset['spec_info']['db_name']; + this.infoItems = [ + {name: 'name', value: this.name, label: this._i18n.t('Name')}, + {name: 'host', value: this.endpoint.getHost(), label: this._i18n.t('Host')}, + {name: 'port', value: this.endpoint.getPort(this.protocol), label: this._i18n.t('Port')}, + {name: 'username', value: this.token.id, label: this._i18n.t('Username')}, + {name: 'password', value: this.token.value, label: this._i18n.t('Password')}, + {name: 'protocol', value: this.protocol, label: this._i18n.t('Protocol')}, + {name: 'date_expired', value: `${this.token.date_expired}`, label: this._i18n.t('Expire time')}, + ]; + if (this.showSetReusable) { + this.infoItems.push({name: 'set_reusable', value: '', label: this._i18n.t('Set reusable')}); + } + + this.info = this.infoItems.reduce((pre, current) => { + pre[current.name] = current.value; + return pre; + }, {}); + } + + genConnCli() { + const {password, host, port, database, protocol} = this.info; + // Password placeholders. Because there is a safe cli, the secret needs to be hidden, so the placeholders are replaced + const passwordHolder = `@${password}@`; + let cli = ''; + + switch (this.protocol) { + case 'vnc': + cli = `vncviewer` + + ` -UserName=${this.token.id}` + + ` ${host}:${port || '5900'}`; + break; + + default: + cli = `Protocol '${protocol}' Not support now`; + } + const cliSafe = cli.replace(passwordHolder, this.passwordMask); + const cliValue = cli.replace(passwordHolder, password); + this.cli = cliValue; + const vncPort = port || '5900'; + const cliDirect = `vncviewer -UserName=${User.username}#${this.account.username}#${this.asset.id} ${this.endpoint.host}:${vncPort}`; + + this.commands = [ + { + title: this._i18n.instant('Connect command line') + ' (' + this._i18n.instant('Using token') + ')', + value: cliValue, + safeValue: cliSafe, + helpText: this._i18n.instant('Password is token password on the table'), + callClient: false + }, + { + title: this._i18n.instant('Connect command line') + ' (' + this._i18n.instant('Directly') + ')', + value: cliDirect, + safeValue: cliDirect, + helpText: this._i18n.instant('Password is your password login to system'), + callClient: false + } + ]; + } + + async reconnect() { + const oldConnectToken = this.view.connectToken; + const newConnectToken = await this._connectTokenSvc.exchange(oldConnectToken); + if (!newConnectToken) { + return; + } + // 更新当前 view 的 connectToken + this.view.connectToken = newConnectToken; + await this.ngOnInit(); + // 刷新完成隐藏密码 + this.passwordShow = this.passwordMask; + } +} diff --git a/src/app/elements/elements.component.ts b/src/app/elements/elements.component.ts index 6bf554c9..7a16e911 100644 --- a/src/app/elements/elements.component.ts +++ b/src/app/elements/elements.component.ts @@ -30,10 +30,12 @@ import {ElementsReplayMp4Component} from './replay/mp4/mp4.component'; import {ElementConnectorGuideComponent} from '@app/elements/content/content-window/guide/guide.component'; import {ElementCommandDialogComponent} from '@app/elements/content/command-dialog/command-dialog.component'; import {ElementSendCommandDialogComponent} from '@app/elements/content/send-command-dialog/send-command-dialog.component'; +// tslint:disable-next-line:max-line-length import {ElementSendCommandWithVariableDialogComponent} from '@app/elements/content/send-command-with-variable-dialog/send-command-with-variable-dialog.component'; import {DynamicFormComponent} from '@app/elements/content/variable-dynamic-form/variable-dynamic-form.component'; import {ElementChatComponent} from '@app/elements/chat/chat.component'; import {ElementsPartsComponent} from './replay/parts/parts.component'; +import {ElementConnectorNecComponent} from '@app/elements/content/content-window/nec/nec.component'; export const ElementComponents = [ @@ -53,6 +55,7 @@ export const ElementComponents = [ ElementAssetTreeComponent, ElementConnectorKokoComponent, ElementConnectorMagnusComponent, + ElementConnectorNecComponent, ElementConnectComponent, ElementDownloadDialogComponent, ElementACLDialogComponent, From baebec87bacaeec999e8ca8e340a26bd1036b706 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 11 Nov 2024 18:44:26 +0800 Subject: [PATCH 4/9] perf: update nec code --- src/app/elements/content/content-window/nec/nec.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/elements/content/content-window/nec/nec.component.ts b/src/app/elements/content/content-window/nec/nec.component.ts index f1d698ee..5ec0923a 100644 --- a/src/app/elements/content/content-window/nec/nec.component.ts +++ b/src/app/elements/content/content-window/nec/nec.component.ts @@ -58,7 +58,6 @@ export class ElementConnectorNecComponent implements OnInit { } setDBInfo() { - const database = this.asset['spec_info']['db_name']; this.infoItems = [ {name: 'name', value: this.name, label: this._i18n.t('Name')}, {name: 'host', value: this.endpoint.getHost(), label: this._i18n.t('Host')}, @@ -79,7 +78,7 @@ export class ElementConnectorNecComponent implements OnInit { } genConnCli() { - const {password, host, port, database, protocol} = this.info; + const {password, host, port, protocol} = this.info; // Password placeholders. Because there is a safe cli, the secret needs to be hidden, so the placeholders are replaced const passwordHolder = `@${password}@`; let cli = ''; From 86d570ee57dfb36324b154dd3be4dec56ca52071 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 11 Nov 2024 18:56:51 +0800 Subject: [PATCH 5/9] perf: update nec info name --- src/app/elements/content/content-window/nec/nec.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/elements/content/content-window/nec/nec.component.ts b/src/app/elements/content/content-window/nec/nec.component.ts index 5ec0923a..98ba4a72 100644 --- a/src/app/elements/content/content-window/nec/nec.component.ts +++ b/src/app/elements/content/content-window/nec/nec.component.ts @@ -51,13 +51,13 @@ export class ElementConnectorNecComponent implements OnInit { const oriHost = this.asset.address; this.name = `${this.asset.name}(${oriHost})`; - this.setDBInfo(); + this.setConnectionInfo(); this.genConnCli(); this.loading = false; this.view.termComp = this; } - setDBInfo() { + setConnectionInfo() { this.infoItems = [ {name: 'name', value: this.name, label: this._i18n.t('Name')}, {name: 'host', value: this.endpoint.getHost(), label: this._i18n.t('Host')}, From eb301b6beafd3a8543ea43a38158b4302fb1a562 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 12 Nov 2024 14:35:05 +0800 Subject: [PATCH 6/9] fix: Set the default language to en --- src/app/services/i18n.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/app/services/i18n.ts b/src/app/services/i18n.ts index 2a60d586..ceb9e366 100644 --- a/src/app/services/i18n.ts +++ b/src/app/services/i18n.ts @@ -20,16 +20,17 @@ export class I18nService { getLangCode() { let langCode = this._cookie.get(this.LANG_COOKIE_NAME); if (!langCode) { - langCode = navigator.language; + langCode = navigator.language.toLowerCase(); } - if (langCode.indexOf('en') > -1) { - return 'en'; + if (['zh', 'zh-cn'].includes(langCode)) { + return 'zh'; + } else if (langCode.indexOf('zh-') > -1) { + // zh-hant zh-tw zh-hk + return 'zh-hant'; } else if (langCode.indexOf('ja') > -1) { return 'ja'; - } else if (langCode.indexOf('zh-hant') > -1) { - return 'zh-hant'; } else { - return 'zh'; + return 'en'; } } From c702ed7922bce6b94d8731744bccb0cbe8798438 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:24:16 +0000 Subject: [PATCH 7/9] chore(deps): bump elliptic from 6.5.4 to 6.6.0 Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.4 to 6.6.0. - [Commits](https://github.com/indutny/elliptic/compare/v6.5.4...v6.6.0) --- updated-dependencies: - dependency-name: elliptic dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ab2ace6d..6734bc2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3252,9 +3252,9 @@ electron-to-chromium@^1.3.378, electron-to-chromium@^1.4.251: integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== elliptic@^6.5.3, elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.npmmirror.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + version "6.6.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210" + integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA== dependencies: bn.js "^4.11.9" brorand "^1.1.0" From ba361570e70c9c1c0e7c4b73bafe559b0923b16b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:49:43 +0800 Subject: [PATCH 8/9] perf: Update dynamic form layout and styles (#1184) Co-authored-by: wangruidong <940853815@qq.com> --- .../variable-dynamic-form.component.html | 7 +++---- .../variable-dynamic-form.component.scss | 10 +++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html index 19a63035..afcef13d 100644 --- a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html +++ b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.html @@ -5,9 +5,9 @@ {{ formConfig[fieldKey].help_text }} -
+
- + {{ choice.label }} @@ -17,10 +17,9 @@
- {{ 'Command'| translate }} + -
diff --git a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss index c69421fc..140b443f 100644 --- a/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss +++ b/src/app/elements/content/variable-dynamic-form/variable-dynamic-form.component.scss @@ -1,11 +1,11 @@ .full-width { width: 100%; - margin-bottom: 20px; -} - -.radio-group { - margin-bottom: 20px; } mat-hint { font-size: 10px; } +.zone-label { + color: rgba(0, 0, 0, 0.54); + font-size:10px; + cursor: pointer; +} From f7cf3c2284607dfeecf532a431fc3363f34bd15b Mon Sep 17 00:00:00 2001 From: zhaojisen <1301338853@qq.com> Date: Thu, 21 Nov 2024 16:22:14 +0800 Subject: [PATCH 9/9] fixed: Fixed an issue when switching languages --- src/app/elements/nav/nav.component.ts | 2 +- .../replay/guacamole/guacamole.component.ts | 3 +++ src/app/services/i18n.ts | 17 ++++++++++++----- src/assets/i18n/{zh-hant.json => zh_hant.json} | 0 4 files changed, 16 insertions(+), 6 deletions(-) rename src/assets/i18n/{zh-hant.json => zh_hant.json} (100%) diff --git a/src/app/elements/nav/nav.component.ts b/src/app/elements/nav/nav.component.ts index 7b4f1981..e638bb22 100644 --- a/src/app/elements/nav/nav.component.ts +++ b/src/app/elements/nav/nav.component.ts @@ -115,7 +115,7 @@ export class ElementNavComponent implements OnInit { { id: 'Chinese-hant', click: () => { - this._i18n.use('zh-hant'); + this._i18n.use('zh_hant'); }, name: '中文(繁體)' }, diff --git a/src/app/elements/replay/guacamole/guacamole.component.ts b/src/app/elements/replay/guacamole/guacamole.component.ts index f3850a5d..07e50770 100644 --- a/src/app/elements/replay/guacamole/guacamole.component.ts +++ b/src/app/elements/replay/guacamole/guacamole.component.ts @@ -124,7 +124,10 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges { } this.recordingDisplay.scale(this.getPropScale()); }; + clearInterval(this.interval); + + // @ts-ignore this.interval = setInterval(() => { if (this.lastDuration === this.max) { clearInterval(this.interval); diff --git a/src/app/services/i18n.ts b/src/app/services/i18n.ts index ceb9e366..e3a32281 100644 --- a/src/app/services/i18n.ts +++ b/src/app/services/i18n.ts @@ -19,14 +19,18 @@ export class I18nService { getLangCode() { let langCode = this._cookie.get(this.LANG_COOKIE_NAME); + if (!langCode) { langCode = navigator.language.toLowerCase(); } + if (['zh', 'zh-cn'].includes(langCode)) { - return 'zh'; - } else if (langCode.indexOf('zh-') > -1) { + return 'zh-hans'; + } else if (langCode.indexOf('zh_hant') > -1) { // zh-hant zh-tw zh-hk - return 'zh-hant'; + return 'zh_hant'; + } else if (langCode.indexOf('zh-hans') > -1) { + return 'zh'; } else if (langCode.indexOf('ja') > -1) { return 'ja'; } else { @@ -58,16 +62,19 @@ export class I18nService { use(lang) { let useLang; + this._translate.use(lang); + if (lang.indexOf('en') > -1) { useLang = 'en'; } else if (lang.indexOf('ja') > -1) { useLang = 'ja'; - } else if (lang.indexOf('zh-hant') > -1) { - useLang = 'zh-hant'; + } else if (lang.indexOf('zh_hant') > -1) { + useLang = 'zh_hant'; } else { useLang = 'zh-hans'; } + this._cookie.set('django_language', useLang, 365, '/'); } } diff --git a/src/assets/i18n/zh-hant.json b/src/assets/i18n/zh_hant.json similarity index 100% rename from src/assets/i18n/zh-hant.json rename to src/assets/i18n/zh_hant.json