Skip to content

Commit

Permalink
Merge pull request #987 from jumpserver/dev
Browse files Browse the repository at this point in the history
v3.8.0
  • Loading branch information
BaiJiangJie authored Oct 19, 2023
2 parents aad9fac + 601e455 commit 198fcdc
Show file tree
Hide file tree
Showing 25 changed files with 132 additions and 45 deletions.
5 changes: 3 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {MAT_LABEL_GLOBAL_OPTIONS} from '@angular/material';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import { DragDropModule } from '@angular/cdk/drag-drop';
import {DragDropModule} from '@angular/cdk/drag-drop';

// service
import {AllServices} from '@app/services';
Expand All @@ -35,9 +35,10 @@ import {ElementDialogAlertComponent} from '@app/services/dialog/dialog.service';
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 {version} from '../environments/environment';

export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, '/luna/assets/i18n/');
return new TranslateHttpLoader(http, '/luna/assets/i18n/', '.json?v=' + version);
}

@NgModule({
Expand Down
2 changes: 1 addition & 1 deletion src/app/elements/asset-tree/asset-tree.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ export class ElementAssetTreeComponent implements OnInit {
* @param splitConnect 是否分屏连接
*/
async onMenuConnect(splitConnect = false) {
if (splitConnect && this._viewSrv.currentView.subViews.length >= 3) {
if (splitConnect && this._viewSrv.currentView.subViews.length >= 4) {
const msg = await this._i18n.instant('Split connect number');
this.snackBar.open(msg, '', {
verticalPosition: 'top',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ <h3>{{"Connect" | translate}} - {{ asset.name | truncatechars:30 }}</h3>
<elements-connect-method
(onDownloadRDPFile)="onConfirm(true)"
[(connectMethod)]="connectMethod"
[manualAuthInfo]="manualAuthInfo"
[account]="accountSelected"
[connectOption]="connectOption"
[protocol]="protocol"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Account, ConnectMethod, Protocol} from '@app/model';
import {Account, ConnectMethod, AuthInfo, Protocol} from '@app/model';
import {AppService, I18nService, SettingService} from '@app/services';

@Component({
Expand All @@ -10,6 +10,7 @@ import {AppService, I18nService, SettingService} from '@app/services';
export class ElementConnectMethodComponent implements OnInit {
@Output() connectMethodChange = new EventEmitter<ConnectMethod>();
@Output() onDownloadRDPFile = new EventEmitter<ConnectMethod>();
@Input() manualAuthInfo: AuthInfo;
@Input() connectOption: Object;
@Input() account: Account;
public connectMethods = [];
Expand All @@ -22,7 +23,7 @@ export class ElementConnectMethodComponent implements OnInit {
}

get isAppletClientMethod() {
return this.connectOption['appletConnectMethod'] === 'client';
return this.connectOption && this.connectOption['appletConnectMethod'] === 'client';
}

private _protocol: Protocol;
Expand Down Expand Up @@ -94,8 +95,12 @@ export class ElementConnectMethodComponent implements OnInit {
if (!this._settingSvc.hasXPack()) {
return false;
}
if (!this.account.has_secret) {
return false;
if (this.account && !this.account.has_secret) {
const aliases = ['@USER', '@INPUT'];
// 同名账号、手动输入可以下载RDP文件
if (!aliases.includes(this.account.alias) || (!this.manualAuthInfo.secret || !this.manualAuthInfo.username)) {
return false;
}
}
if (method.component === 'razor') {
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="select-user form-field" style="width: 100%;">
<div *ngIf="accounts.length > 0; else empty" class="select-user form-field" style="width: 100%;">
<label class="zone-label" for="selectAccount">{{ "Select account" | translate }}</label>
<mat-form-field style="width: 100%; margin-top:-10px">
<mat-select
Expand Down Expand Up @@ -35,6 +35,10 @@
</mat-error>
</div>

<ng-template #empty>
<div class="not-account">{{'No account available'| translate }}</div>
</ng-template>

<div *ngIf="showManualUsernameInput" class="form-field">
<label class="zone-label" style="margin-bottom: 0">{{ "Username" | translate }}</label>
<mat-form-field class="input-field" floatLabel='never'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@
font-size: 15px;
padding-left: 10px;
}

.not-account {
margin-bottom: 10px;
}
6 changes: 5 additions & 1 deletion src/app/elements/connect/connect.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,16 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
if (connectMethod.value.endsWith('_guide')) {
return this.createWebView(asset, connectInfo, connToken);
}
let appletConnectMethod = connectOption ? connectOption['appletConnectMethod'] : 'web';
if (!this._settingSvc.hasXPack()) {
appletConnectMethod = 'web';
}

if (connectInfo.downloadRDP) {
return this._http.downloadRDPFile(connToken, this._settingSvc.setting);
} else if (connectMethod.type === 'native') {
this.callLocalClient(connToken).then();
} else if (connectMethod.type === 'applet' && connectOption['appletConnectMethod'] !== 'web') {
} else if (connectMethod.type === 'applet' && appletConnectMethod === 'client') {
this.callLocalClient(connToken).then();
} else {
this.createWebView(asset, connectInfo, connToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ <h1 mat-dialog-title>
<mat-form-field style="width: 100%;">
<input [(ngModel)]="name" matInput required placeholder='{{"Name"| translate}}' name="fontSize" max="60" >
</mat-form-field>
<mat-form-field style="width: 100%;">
<mat-select [(value)]="module"
placeholder="{{'Module'| translate }}">
<mat-option *ngFor="let type of commandModules" [value]="type.value">{{type.label}}</mat-option>
</mat-select>
</mat-form-field>
</div>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ import {MAT_DIALOG_DATA} from '@angular/material/dialog';
})
export class ElementCommandDialogComponent implements OnInit {
public name = '';
public module = 'shell';
public commandModules = [
{
label: 'Shell',
value: 'shell'
}
];

constructor(public dialogRef: MatDialogRef<ElementCommandDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
Expand All @@ -20,12 +27,11 @@ export class ElementCommandDialogComponent implements OnInit {
ngOnInit() {}

async onSubmit() {
console.log('this.name: ', this.name);
if (!this.name) { return; }
const data = {
name: this.name,
args: this.data.command,
module: 'shell',
module: this.module,
};
this._http.addQuickCommand(data).subscribe(
async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ div, elements-term, elements-guacamole {

.many-view {
flex: 0 0 50%;
}

.height-view {
height: 50%;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,15 @@
>
<div class="view">
<div
*ngIf="!loading"
*ngFor="let sub of subViews; let i = index"
class="sub-view"
[ngClass]="{'many-view': subViews.length > 1, 'three-view': subViews.length == 2}">
<elements-content-view
[view]="view"
[hasHead]="true"
[canClose]="false"
></elements-content-view>
</div>
<div
*ngFor="let sub of subViews"
class="sub-view"
[ngClass]="{'many-view': subViews.length > 1}"
[ngClass]="{'many-view': subViews.length > 1, 'height-view': subViews.length > 2, 'three-view': subViews.length == 3 && i == 2}"
>
<div *ngIf="sub.smartEndpoint">
<elements-content-view
[view]="sub"
[hasHead]="true"
[canClose]="true"
[hasHead]="subViews.length > 1"
[canClose]="i !== 0"
></elements-content-view>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {ActivatedRoute} from '@angular/router';
export class ElementContentWindowComponent implements OnInit, DoCheck {
@Input() view: View;
@ViewChild('contentWindow', {static: true}) windowRef: ElementRef;
loading = true;
public id: string;
private iterableDiffer: any;

Expand All @@ -33,24 +32,19 @@ export class ElementContentWindowComponent implements OnInit, DoCheck {
this.id = 'window-' + Math.random().toString(36).substr(2);
this.createWaterMark();
this.view.smartEndpoint = await this._appSvc.getSmartEndpoint(this.view);
setTimeout(() => {
this.loading = false;
}, 1000);
this.subViews.push(this.view);
}

async ngDoCheck() {
const iterableChanges = this.iterableDiffer.diff(this.view.subViews);

if (iterableChanges) {
if (iterableChanges && iterableChanges.collection.length > 1) {
// subViews 数组发生变化
iterableChanges.forEachAddedItem(async (item) => {
const smartEndpoint = await this._appSvc.getSmartEndpoint(item.item).then();
const index = this.view.subViews.findIndex(i => i.connectToken.id === item.item.connectToken.id);
this.view.subViews[index].smartEndpoint = smartEndpoint;
});
iterableChanges.forEachRemovedItem((item) => {
console.log('Removed item:', item);
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ export class ElementConnectorGuideComponent implements OnInit {
},
error => {
this.token.is_reusable = false;
if (error.status === 404) {
this._toastr.error(this._i18n.instant('Token expired'));
return;
}

this._toastr.error(error.error.msg || error.error.is_reusable || error.message);
}
);
Expand Down
3 changes: 2 additions & 1 deletion src/app/elements/content/content.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
></i>
<ul class="command-list" *ngIf="quickCommands.length > 0; else empty">
<li class="command-box" *ngFor="let command of quickCommands" (click)="sendQuickCommand(command)">
{{ command.name }}
<i [ngClass]="command.module.value + '_ico_docu'" class="view_icon"></i>
<span style="vertical-align: middle;">{{ command.name }}</span>
</li>
</ul>
<i
Expand Down
16 changes: 15 additions & 1 deletion src/app/elements/content/content.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ $-border-y: #1f1b1b;
color: #d6cbcb;
}
}

.view_icon {
width: 12px;
height: 12px;
margin: 0 !important;
margin-right: 3px !important;
vertical-align: middle;
display: inline-block;
}

.view_icon::before {
font-family: FontAwesome;
color: #ffffff;
display: inline-block;
}
}

#batchCommandDiv input {
Expand Down Expand Up @@ -329,7 +344,6 @@ tr:hover {
width: 15px;
}


.input-box {
display: flex;
width: 100%;
Expand Down
12 changes: 9 additions & 3 deletions src/app/elements/content/content.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class ElementContentComponent implements OnInit {
async ngOnInit() {
this.viewList = this.viewSrv.viewList;
this.viewIds = this.viewSrv.viewIds;
this.quickCommands = await this._http.getQuickCommand();
this.quickCommands = await this.quickCommandsFilter();
document.addEventListener('click', this.hideRMenu.bind(this), false);
}

Expand Down Expand Up @@ -141,7 +141,7 @@ export class ElementContentComponent implements OnInit {
const d = {'data': cmd};
this.viewList[i].termComp.sendCommand(d);
const subViews = this.viewList[i].subViews;
if (subViews.length > 0) {
if (subViews.length > 1) {
for (let j = 0; j < subViews.length; j++) {
if (subViews[j].protocol !== 'ssh' || subViews[j].connected !== true) {
continue;
Expand Down Expand Up @@ -277,11 +277,17 @@ export class ElementContentComponent implements OnInit {
moveItemInArray(this.viewIds, event.previousIndex, event.currentIndex);
}

async quickCommandsFilter() {
let list = await this._http.getQuickCommand();
list = list.filter(i => i.module.value === 'shell');
return list;
}

async switchCommand() {
this.batchCommand = '';
this.isShowInputCommand = !this.isShowInputCommand;
if (!this.isShowInputCommand) {
this.quickCommands = await this._http.getQuickCommand();
this.quickCommands = await this.quickCommandsFilter();
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/app/elements/nav/nav.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ export class ElementNavComponent implements OnInit {
}

get viewListSorted() {
return this.viewList.sort((a, b) => {
return this.viewIds.indexOf(a.id) - this.viewIds.indexOf(b.id);
const viewList = [];
this.viewIds.forEach((id, index) => {
const view = this.viewList.find(i => i.id === id);
viewList[index] = view;
});
return viewList;
}

ngOnInit() {
Expand Down
5 changes: 3 additions & 2 deletions src/app/pages/main/main.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ as-split ::ng-deep .as-split-gutter.as-dragged .as-split-gutter-icon, .ex-b as-s
}

as-split.as-horizontal ::ng-deep .as-split-gutter-icon {
width: 8px !important;
left: -6px;
width: 5px !important;
left: -1px;
z-index: 1;
}

as-split.as-vertical ::ng-deep .as-split-gutter-icon {
Expand Down
Loading

0 comments on commit 198fcdc

Please sign in to comment.