Commit d13ece2b authored by zhouwenqing's avatar zhouwenqing Committed by 老广

菜单栏增加窗口列表菜单和增加重新连接功能菜单 (#92)

* [Update] 修改点击同步session

* support chrome firefox and ie explorer fullscreen

* 修改标签页的span为inline-block,增加展现title属性

* 1、增加窗口列表菜单,展现连接的窗口列表;2、服务器菜单下增加重新连接菜单,断开的连接可以重新连接;

* 修改标签文字内容高度
parent 95b667ce
......@@ -63,5 +63,8 @@
"full screen": "全屏显示",
"please input password": "请输入密码",
"username": "用户名",
"password": "密码"
"password": "密码",
"tab list": "窗口列表",
"reconnect": "重新连接",
"are you sure to reconnect it?(rdp not support)": "确定要重新连接吗? (RDP暂不支持)"
}
......@@ -63,5 +63,8 @@
"full screen": "全屏显示",
"please input password": "请输入密码",
"username": "用户名",
"password": "密码"
"password": "密码",
"tab list": "窗口列表",
"reconnect": "重新连接",
"are you sure to reconnect it?(rdp not support)": "确定要重新连接吗? (RDP暂不支持)"
}
......@@ -63,5 +63,8 @@
"full screen": "全屏显示",
"please input password": "请输入密码",
"username": "用户名",
"password": "密码"
"password": "密码",
"tab list": "窗口列表",
"reconnect": "重新连接",
"are you sure to reconnect it?(rdp not support)": "确定要重新连接吗? (RDP暂不支持)"
}
......@@ -5,6 +5,7 @@ import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
import {FormControl, Validators} from '@angular/forms';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {ActivatedRoute} from '@angular/router';
import * as jQuery from 'jquery/dist/jquery.min';
declare var $: any;
......@@ -60,16 +61,16 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
public _logger: LogService,
private activatedRoute: ActivatedRoute,
private _http: HttpService
) {
) {
this.searchEvt$ = new BehaviorSubject<string>(this.query);
}
getGrantedAssetsNodes() {
this._http.get_my_granted_nodes()
.subscribe(response => {
this.Data = [...response, ...this.Data];
this.draw();
});
.subscribe(response => {
this.Data = [...response, ...this.Data];
this.draw();
});
}
refreshGrantedAssetsNodes() {
......@@ -87,7 +88,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
this.Data = [...this.Data, ...response];
this.draw();
}
});
});
}
ngOnInit() {
......@@ -126,16 +127,16 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
});
this.activatedRoute.queryParams.subscribe(params => {
const login_to = params['login_to'];
if (login_to && !this.hasLoginTo) {
this.Data.forEach(t => {
if (login_to === t.id && t.isParent === false) {
this.hasLoginTo = true;
this.Connect(t);
return;
}
});
}
const login_to = params['login_to'];
if (login_to && !this.hasLoginTo) {
this.Data.forEach(t => {
if (login_to === t.id && t.isParent === false) {
this.hasLoginTo = true;
this.Connect(t);
return;
}
});
}
});
}
......@@ -146,7 +147,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
$rootNodeRef.after(refreshIcon);
const refreshIconRef = $('#tree-refresh');
refreshIconRef.bind('click', function () {
callback();
callback();
});
}
......@@ -165,7 +166,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
}
onRightClick(event, treeId, treeNode) {
if (!treeNode || treeNode.isParent ) {
if (!treeNode || treeNode.isParent) {
return null;
}
const host = treeNode.meta.asset;
......@@ -175,10 +176,10 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
protocols.push(host.protocol);
}
for (let i = 0; i < protocols.length; i++) {
const protocol = protocols[i];
if (protocol && protocol.startsWith('ssh')) {
findSSHProtocol = true;
}
const protocol = protocols[i];
if (protocol && protocol.startsWith('ssh')) {
findSSHProtocol = true;
}
}
if (!findSSHProtocol) {
alert('Windows 请使用Ctrl+Shift+Alt呼出侧边栏上传下载');
......@@ -193,7 +194,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
this.rightClickSelectNode = treeNode;
}
}
connectAsset(node) {
const system_users = node.meta.system_users;
const host = node.meta.asset;
......@@ -316,6 +317,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
}
NavList.List.push(new View());
NavList.Active = id;
jQuery('.tabs').animate({'scrollLeft': 150 * id}, 400);
}
this._logger.debug(NavList);
}
......@@ -384,7 +386,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
}
_keywords = _keywords.toLowerCase();
let shouldShow = [];
const matchedNodes = zTreeObj.getNodesByFilter(function(node) {
const matchedNodes = zTreeObj.getNodesByFilter(function (node) {
if (node.meta.type === 'asset') {
const host = node.meta.asset;
return host.hostname.toLowerCase().indexOf(_keywords) !== -1 || host.ip.indexOf(_keywords) !== -1;
......@@ -393,18 +395,18 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
}
});
matchedNodes.forEach((node) => {
const parents = this.recurseParent(node);
const children = this.recurseChildren(node);
shouldShow = [...shouldShow, ...parents, ...children, node];
const parents = this.recurseParent(node);
const children = this.recurseChildren(node);
shouldShow = [...shouldShow, ...parents, ...children, node];
});
this.hiddenNodes = nodes;
this.expandNodes = shouldShow;
zTreeObj.hideNodes(nodes);
zTreeObj.showNodes(shouldShow);
shouldShow.forEach((node) => {
if (node.isParent) {
zTreeObj.expandNode(node, true);
}
if (node.isParent) {
zTreeObj.expandNode(node, true);
}
});
// zTreeObj.expandAll(true);
}
......
......@@ -95,3 +95,12 @@
cursor: default;
color: #c5babc;
}
.nav ul li.disconnected {
background-color: darkgray;
}
.nav ul li.active {
box-sizing: border-box;
border-bottom: 3px solid #19aa8d !important;
}
......@@ -12,5 +12,15 @@
</li>
</ul>
</li>
<li [ngClass]="{'dropdown': true}">
<a>{{"Tab List"|trans}}</a>
<ul *ngIf="NavList.List.length>1" [ngClass]="{'dropdown-content': true}">
<ng-container *ngFor="let t of NavList.List, let idx= index" >
<li *ngIf="t.nick!=null" [ngClass]="{'active':idx==NavList.Active,'disconnected':!t.connected, 'hidden': t.closed != false}">
<a id="{{ 'tab' + idx }}" (click)="toTab(idx)">{{t.nick}}</a>
</li>
</ng-container>
</ul>
</li>
</ul>
</div>
......@@ -21,6 +21,7 @@ declare let layer: any;
})
export class ElementNavComponent implements OnInit {
DataStore = DataStore;
NavList = NavList;
ChangeLanWarningDialog: any;
static Hide() {
......@@ -39,6 +40,10 @@ export class ElementNavComponent implements OnInit {
ngOnInit() {
}
toTab(idx) {
ControlComponent.active(idx);
}
click(event) {
this._logger.debug('nav.ts:NavComponent,click', event);
switch (event) {
......@@ -67,11 +72,30 @@ export class ElementNavComponent implements OnInit {
break;
}
case 'FullScreen': {
document.getElementsByClassName('window active ')[0].requestFullscreen();
let ele:any = document.getElementsByClassName("window active ")[0];
if (ele.requestFullscreen) {
ele.requestFullscreen();
} else if (ele.mozRequestFullScreen) {
ele.mozRequestFullScreen();
} else if (ele.msRequestFullscreen) {
ele.msRequestFullscreen();
} else if (ele.webkitRequestFullscreen) {
ele.webkitRequestFullScreen();
} else {
throw new Error('不支持全屏api');
}
window.dispatchEvent(new Event('resize'));
break;
}
case'Disconnect': {
case 'Reconnect': {
if (NavList.List[NavList.Active].termComp) {
NavList.List[NavList.Active].termComp.reconnect();
}
break;
}
case 'Disconnect': {
if (!confirm('断开当前连接? (RDP暂不支持)')) {
break;
}
......@@ -221,6 +245,11 @@ export class ElementNavComponent implements OnInit {
'click': 'DisconnectAll',
'name': 'Disconnect all'
},
{
'id': 'Reconnect',
'click': 'Reconnect',
'name': 'Reconnect'
},
]
}, {
'id': 'FileManager',
......
import {AfterViewInit, Component, Input, OnInit, OnDestroy } from '@angular/core';
import {AfterViewInit, Component, Input, OnInit, OnDestroy} from '@angular/core';
import {Terminal} from 'xterm';
import {NavList, View} from '../../pages/control/control/control.component';
import {UUIDService} from '../../app.service';
import {CookieService} from 'ngx-cookie-service';
import {Socket} from '../../utils/socket';
import {getWsSocket} from '../../globals';
import {TransPipe} from '../../pipes/trans.pipe';
@Component({
......@@ -23,6 +24,7 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
ws: Socket;
roomID: string;
view: View;
transPipe: TransPipe;
constructor(private _uuid: UUIDService, private _cookie: CookieService) {
}
......@@ -31,6 +33,7 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
this.view = NavList.List[this.index];
this.secret = this._uuid.gen();
this.newTerm();
this.transPipe = new TransPipe();
getWsSocket().then(sock => {
this.ws = sock;
this.connectHost();
......@@ -51,6 +54,7 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
}
});
this.view.Term = this.term;
this.view.termComp = this;
}
changeWinSize(size: Array<number>) {
......@@ -59,7 +63,19 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
}
}
connectHost() {
reconnect() {
if (NavList.List[this.index].connected === true) {
if (!confirm(this.transPipe.transform('Are you sure to reconnect it?(RDP not support)'))) {
return;
}
this.close();
}
this.secret = this._uuid.gen();
this.emitHostAndTokenData();
}
emitHostAndTokenData() {
if (this.host) {
const data = {
uuid: this.host.id,
......@@ -77,6 +93,10 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
console.log('On token event trigger');
this.ws.emit('token', data);
}
}
connectHost() {
this.emitHostAndTokenData();
this.term.on('data', data => {
const d = {'data': data, 'room': this.roomID};
......@@ -107,6 +127,7 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
console.log('On room', data);
this.roomID = data.room;
this.view.room = data.room;
this.view.connected = true;
}
});
}
......
......@@ -9,6 +9,7 @@
import {Component, OnInit} from '@angular/core';
import {TermWS} from '../../../globals';
import * as jQuery from 'jquery/dist/jquery.min';
export class View {
nick: string;
......@@ -23,6 +24,7 @@ export class View {
room: string;
Rdp: any;
Term: any;
termComp: any;
}
export let NavList: {
......@@ -46,6 +48,7 @@ export class ControlComponent implements OnInit {
v.hide = id.toString() !== k;
});
NavList.Active = id;
jQuery('.tabs').animate({'scrollLeft': 150 * id}, 400);
}
static TerminalDisconnect(id) {
......
......@@ -48,8 +48,9 @@
padding-right: 14px;
line-height: 26px;
cursor: default;
width: 115px;
height: 21px;
/*width: 145px;*/
height: 26px;
display: block;
}
.tabs ul li a.close {
......@@ -72,18 +73,18 @@
padding-left: 12px;
line-height: 26px;
color: white;
height: 18px;
height: 26px;
}
.tabs ul li input {
font-family: 'Roboto', sans-serif;
font-size: 13px;
width: 115px;
width: 120px;
border: none;
background-color: inherit;
color: white;
padding: 5px 20px 4px 15px;
height: 18px;
height: 26px;
}
/*
......
......@@ -7,7 +7,7 @@
<li *ngFor="let m of NavList.List;let i = index"
[ngClass]="{'active':i==NavList.Active,'disconnected':!m.connected, 'hidden': m.closed != false}"
id="termnav-{{i}}" (click)="setActive(i)" (dblclick)="m.edit=true;setActive(i)">
<span *ngIf="!m.edit">{{m.nick | truncatechars:25 }}</span>
<span *ngIf="!m.edit" [attr.title]="m.nick">{{m.nick | truncatechars:17 }}</span>
<input *ngIf="m.edit" [(ngModel)]="m.nick" (blur)="m.edit=false" (keyup.enter)="m.edit=false" autofocus="true"/>
<a class="close" (click)="close(m,i)">&times;</a>
</li>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment