Commit 35e34bf2 authored by ibuler's avatar ibuler

[Update] 优化搜索

parent f0abd8f7
{
"reset": "重置",
"submit": "提交",
"email subject prefix": "邮件主题前缀",
"basic setting": "基本设置",
"email setting": "邮件设置",
"ldap setting": "LDAP设置",
"terminal setting": "终端设置",
"current site url": "当前站点URL",
"user guide url": "用户向导URL",
"user first login update profile done redirect to it": "用户第一次登录,修改profile后重定向到地址",
"server": "服务器",
"view": "视图",
"help": "帮助",
"hide left manager": "隐藏左边栏",
"show left manager": "显示左边栏",
"disconnect all": "断开所有链接",
"disconnect": "断开链接",
"website": "官网",
"search": "搜索",
"settings": "系统设置",
"job center": "作业中心",
"sessions": "会话管理",
"perms": "权限管理",
"assets": "资产管理",
"users": "用户管理",
"dashboard": "仪表盘",
"task": "任务",
"session online": "在线会话",
"session offline": "离线会话",
"commands": "命令记录",
"terminal": "终端管理",
"asset perminssion": "资产授权",
"asset": "资产",
"asset group": "资产组",
"cluster": "集群",
"admin user": "管理用户",
"system user": "系统用户",
"labels": "标签管理",
"user": "用户",
"user group": "用户组",
"login logs": "登陆日志",
"language": "语言选择",
"found": "发现",
"users ": "用户",
"choose a user": "选择一个用户",
"please choose a user": "请选择一个用户",
"cancel": "取消",
"confirm": "确认",
"document": "文档",
"support": "商业支持",
"speed": "速度",
"file manager": "文件管理",
"file": "文件管理",
"new connection": "连接",
"connect": "连接",
"rdp resolution": "RDP分辨率",
"set rdp solution": "设置分辨率",
"select a solution": "选择分辨率",
"set font": "设置字体",
"font": "字体",
"font size": "字体大小",
"full screen": "全屏显示",
"please input password": "请输入密码",
"username": "用户名",
"password": "密码",
"skip": "跳过",
"loading": "加载中"
}
{
"reset": "重置",
"submit": "提交",
"email subject prefix": "邮件主题前缀",
"basic setting": "基本设置",
"email setting": "邮件设置",
"ldap setting": "LDAP设置",
"terminal setting": "终端设置",
"current site url": "当前站点URL",
"user guide url": "用户向导URL",
"user first login update profile done redirect to it": "用户第一次登录,修改profile后重定向到地址",
"server": "服务器",
"view": "视图",
"help": "帮助",
"hide left manager": "隐藏左边栏",
"show left manager": "显示左边栏",
"disconnect all": "断开所有链接",
"disconnect": "断开链接",
"website": "官网",
"search": "搜索",
"settings": "系统设置",
"job center": "作业中心",
"sessions": "会话管理",
"perms": "权限管理",
"assets": "资产管理",
"users": "用户管理",
"dashboard": "仪表盘",
"task": "任务",
"session online": "在线会话",
"session offline": "离线会话",
"commands": "命令记录",
"terminal": "终端管理",
"asset perminssion": "资产授权",
"asset": "资产",
"asset group": "资产组",
"cluster": "集群",
"admin user": "管理用户",
"system user": "系统用户",
"labels": "标签管理",
"user": "用户",
"user group": "用户组",
"login logs": "登陆日志",
"language": "语言选择",
"found": "发现",
"users ": "用户",
"choose a user": "选择一个用户",
"please choose a user": "请选择一个用户",
"cancel": "取消",
"confirm": "确认",
"document": "文档",
"support": "商业支持",
"speed": "速度",
"file manager": "文件管理",
"file": "文件管理",
"new connection": "连接",
"connect": "连接",
"rdp resolution": "RDP分辨率",
"set rdp solution": "设置分辨率",
"select a solution": "选择分辨率",
"set font": "设置字体",
"font": "字体",
"font size": "字体大小",
"full screen": "全屏显示",
"please input password": "请输入密码",
"username": "用户名",
"password": "密码",
"skip": "跳过",
"loading": "加载中"
}
......@@ -13,17 +13,14 @@ import {HttpClientModule} from '@angular/common/http';
import {AppRouterModule} from './router/router.module';
import {AppComponent} from './pages/app.component';
// service
import {AppService, HttpService, LocalStorageService, NavService, LogService, UUIDService} from './app.service';
import {AppService, HttpService, LocalStorageService, NavService, LogService, UUIDService, TreeFilterService} from './app.service';
import {CookieService} from 'ngx-cookie-service';
import {MAT_LABEL_GLOBAL_OPTIONS} from '@angular/material';
import {Pipes} from './pipes/pipes';
import {AppComponent} from './pages/app.component';
import {PagesComponents} from './pages/pages.component';
import {ElementComponents} from './elements/elements.component';
import {ChangLanWarningDialogComponent, RDPSolutionDialogComponent, FontDialogComponent} from './elements/nav/nav.component';
......@@ -71,9 +68,9 @@ import {SftpComponent} from './elements/sftp/sftp.component';
LocalStorageService,
DialogService,
CookieService,
TreeFilterService,
NGXLogger,
{provide: MAT_LABEL_GLOBAL_OPTIONS, useValue: {float: 'always'}}
]
})
export class AppModule {
......
......@@ -5,7 +5,7 @@
* @date 2017-11-07
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Injectable, OnInit} from '@angular/core';
import {EventEmitter, Injectable, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {CookieService} from 'ngx-cookie-service';
import 'rxjs/add/operator/map';
......@@ -13,7 +13,8 @@ import 'rxjs/add/operator/catch';
import {DataStore, User, Browser, i18n} from './globals';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {NGXLogger} from 'ngx-logger';
import {SystemUser, GuacObjAddResp, TreeNode} from './model';
import {SystemUser, GuacObjAddResp, TreeNode, User as _User} from './model';
import {environment} from '../environments/environment';
import * as UUID from 'uuid-js/lib/uuid.js';
declare function unescape(s: string): string;
......@@ -64,7 +65,7 @@ export class HttpService {
}
getUserProfile() {
return this.http.get('/api/users/v1/profile/');
return this.http.get<_User>('/api/users/v1/profile/');
}
getMyGrantedNodes(async: boolean, refresh?: boolean) {
......@@ -111,7 +112,7 @@ export class HttpService {
.set('user_id', userId)
.set('asset_id', assetId)
.set('system_user_id', systemUserId)
.set('token', DataStore.guacamole_token);
.set('token', DataStore.guacamoleToken);
let body = new HttpParams();
if (systemUserUsername && systemUserPassword) {
systemUserUsername = btoa(systemUserUsername);
......@@ -139,7 +140,7 @@ export class HttpService {
let params = new HttpParams()
.set('user_id', userId)
.set('remote_app_id', remoteAppId)
.set('token', DataStore.guacamole_token);
.set('token', DataStore.guacamoleToken);
let body = new HttpParams();
if (systemUserUsername && systemUserPassword) {
systemUserUsername = btoa(systemUserUsername);
......@@ -280,46 +281,41 @@ export class AppService implements OnInit {
constructor(private _http: HttpService,
private _router: Router,
private _logger: LogService,
private _cookie: CookieService,
private _logger: LogService,
private _localStorage: LocalStorageService) {
if (this._cookie.get('loglevel')) {
// 0.- Level.OFF
// 1.- Level.ERROR
// 2.- Level.WARN
// 3.- Level.INFO
// 4.- Level.DEBUG
// 5.- Level.LOG
this._logger.level = parseInt(this._cookie.get('loglevel'), 10);
// this._logger.debug('Your debug stuff');
// this._logger.info('An info');
// this._logger.warn('Take care ');
// this._logger.error('Too late !');
// this._logger.log('log !');
} else {
this._cookie.set('loglevel', '0', 99, '/', document.domain);
// this._logger.level = parseInt(Cookie.getCookie('loglevel'));
this._logger.level = 0;
this.setLogLevel();
this.setLang();
this.checklogin();
}
// if (environment.production) {
this._logger.level = 2;
this.checklogin();
// }
ngOnInit() {
}
if (this._cookie.get('lang')) {
this.lang = this._cookie.get('lang');
} else {
this.lang = window.navigator.languages ? window.navigator.languages[0] : 'cn';
this._cookie.set('lang', this.lang);
setLogLevel() {
// 设置logger level
let logLevel = this._cookie.get('logLevel');
if (!logLevel) {
logLevel = environment.production ? '1' : '5';
}
this._logger.level = parseInt(logLevel, 10);
}
if (this.lang !== 'en') {
this._http.get('/luna/i18n/' + this.lang + '.json').subscribe(
setLang() {
let lang = this._cookie.get('lang');
if (!lang) {
lang = navigator.language;
}
lang = lang.substr(0, 2);
this.lang = lang;
if (lang !== 'en') {
this._http.get('/luna/i18n/' + 'zh' + '.json').subscribe(
data => {
this._localStorage.set('lang', JSON.stringify(data));
},
err => {
this._logger.error('Load i18n file error: ', err.error);
}
);
}
......@@ -332,42 +328,26 @@ export class AppService implements OnInit {
}
}
ngOnInit() {
}
checklogin() {
this._logger.log('service.ts:AppService,checklogin');
if (DataStore.Path) {
if (document.location.pathname === '/luna/connect') {
} else {
return;
}
if (User.logined) {
if (document.location.pathname === '/login') {
this._router.navigate(['']);
} else {
this._router.navigate([document.location.pathname]);
}
return;
// jQuery('angular2').show();
} else {
this._http.getUserProfile()
.subscribe(
data => {
User.id = data['id'];
User.name = data['name'];
User.username = data['username'];
User.email = data['email'];
User.is_active = data['is_active'];
User.is_superuser = data['is_superuser'];
User.role = data['role'];
// User.groups = data['groups'];
User.wechat = data['wechat'];
User.comment = data['comment'];
User.date_expired = data['date_expired'];
if (data['phone']) {
User.phone = data['phone'].toString();
}
User.logined = data['logined'];
this._logger.debug(User);
this._localStorage.set('user', data['id']);
}
this._http.getUserProfile().subscribe(
user => {
Object.assign(User, user);
User.logined = true;
this._localStorage.set('user', user.id);
},
err => {
// this._logger.error(err);
......@@ -377,8 +357,6 @@ export class AppService implements OnInit {
// this._router.navigate(['login']);
},
);
}
}
} else {
this._router.navigate(['FOF']);
// jQuery('angular2').show();
......@@ -435,3 +413,12 @@ export class NavService {
this.store.set('SkipAllManualPassword', value);
}
}
@Injectable()
export class TreeFilterService {
onFilter: EventEmitter<string> = new EventEmitter<string>();
filter(q: string) {
this.onFilter.emit(q);
}
}
import {Component, Input, OnInit, Inject, SimpleChanges, OnChanges, ElementRef, ViewChild} from '@angular/core';
import {NavList, View} from '../../pages/control/control/control.component';
import {AppService, HttpService, LogService, NavService} from '../../app.service';
import {connectEvt} from '../../globals';
import {Component, Input, OnInit, OnDestroy, ElementRef, ViewChild} from '@angular/core';
import {MatDialog} from '@angular/material';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {ActivatedRoute} from '@angular/router';
import {AppService, HttpService, LogService, NavService, TreeFilterService} from '../../app.service';
import {connectEvt} from '../../globals';
import {TreeNode, ConnectEvt} from '../../model';
import * as jQuery from 'jquery/dist/jquery.min';
import {View} from '../content/model';
declare var $: any;
@Component({
selector: 'elements-asset-tree',
templateUrl: './asset-tree.component.html',
styleUrls: ['./asset-tree.component.scss']
styleUrls: ['./asset-tree.component.scss'],
})
export class ElementAssetTreeComponent implements OnInit, OnChanges {
export class ElementAssetTreeComponent implements OnInit, OnDestroy {
@Input() query: string;
@Input() searchEvt$: BehaviorSubject<string>;
@ViewChild('rMenu') rMenu: ElementRef;
......@@ -43,47 +43,40 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
isShowRMenu = false;
rightClickSelectNode: any;
hasLoginTo = false;
loadTreeAsync = false;
onNodeClick(event, treeId, treeNode, clickFlag) {
if (treeNode.isParent) {
this.assetsTree.expandNode(treeNode);
} else {
this._http.getUserProfile().subscribe();
this.Connect(treeNode);
}
}
treeFilterSubscription: any;
constructor(private _appSvc: AppService,
private _treeFilterSvc: TreeFilterService,
public _dialog: MatDialog,
public _logger: LogService,
private activatedRoute: ActivatedRoute,
private _http: HttpService,
private _navSvc: NavService
) {
this.searchEvt$ = new BehaviorSubject<string>(this.query);
}
) {}
ngOnInit() {
this.initTree();
document.addEventListener('click', this.hideRMenu.bind(this), false);
this.loadTreeAsync = this._navSvc.treeLoadAsync;
// Todo: 搜索
this.searchEvt$.asObservable()
.debounceTime(300)
.distinctUntilChanged()
.subscribe((n) => {
this.filter();
});
this.treeFilterSubscription = this._treeFilterSvc.onFilter.subscribe(
keyword => {
this._logger.debug('Filter tree: ', keyword);
this.filterAssets(keyword);
this.filterRemoteApps(keyword);
}
);
}
ngOnChanges(changes: SimpleChanges) {
// if (changes['Data'] && this.Data) {
// this.draw();
// }
if (changes['query'] && !changes['query'].firstChange) {
this.searchEvt$.next(this.query);
ngOnDestroy(): void {
this.treeFilterSubscription.unsubscribe();
}
onNodeClick(event, treeId, treeNode, clickFlag) {
if (treeNode.isParent) {
this.assetsTree.expandNode(treeNode);
} else {
this._http.getUserProfile().subscribe();
this.ConnectAsset(treeNode);
}
}
......@@ -98,7 +91,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
onClick: this.onNodeClick.bind(this),
onRightClick: this.onRightClick.bind(this)
};
if (this.loadTreeAsync) {
if (this._navSvc.treeLoadAsync) {
setting['async'] = {
enable: true,
url: '/api/perms/v1/users/nodes/children-with-assets/tree/',
......@@ -107,7 +100,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
};
}
this._http.getMyGrantedNodes(this.loadTreeAsync, refresh).subscribe(resp => {
this._http.getMyGrantedNodes(this._navSvc.treeLoadAsync, refresh).subscribe(resp => {
const assetsTree = $.fn.zTree.init($('#assetsTree'), setting, resp);
this.assetsTree = assetsTree;
this.rootNodeAddDom(assetsTree, () => {
......@@ -144,7 +137,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
this.Data.forEach(t => {
if (login_to === t.id && t.isParent === false) {
this.hasLoginTo = true;
this.Connect(t);
this.ConnectAsset(t);
return;
}
});
......@@ -152,7 +145,7 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
});
}
Connect(node: TreeNode) {
ConnectAsset(node: TreeNode) {
const evt = new ConnectEvt(node, 'asset');
connectEvt.next(evt);
}
......@@ -215,24 +208,88 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
}
connectFileManager() {
const host = this.rightClickSelectNode.meta.asset;
const id = NavList.List.length - 1;
if (host) {
NavList.List[id].nick = '[FILE]' + host.hostname;
NavList.List[id].connected = true;
NavList.List[id].edit = false;
NavList.List[id].closed = false;
NavList.List[id].host = host;
NavList.List[id].type = 'sftp';
NavList.List.push(new View());
NavList.Active = id;
jQuery('.tabs').animate({'scrollLeft': 150 * id}, 400);
}
const node = this.rightClickSelectNode;
const evt = new ConnectEvt(node, 'sftp');
connectEvt.next(evt);
}
connectTerminal() {
const host = this.rightClickSelectNode;
this.Connect(host);
this.ConnectAsset(host);
}
filterAssets(keyword) {
if (this._navSvc.treeLoadAsync) {
this._logger.debug('Filter assets server');
this.filterAssetsServer(keyword);
} else {
this._logger.debug('Filter assets local');
this.filterAssetsLocal(keyword);
}
}
filterTree(keyword, tree, filterCallback) {
const nodes = tree.transformToArray(tree.getNodes());
if (!keyword) {
if (tree.hiddenNodes) {
tree.showNodes(tree.hiddenNodes);
tree.hiddenNodes = null;
}
if (tree.expandNodes) {
tree.expandNodes.forEach((node) => {
if (node.id !== nodes[0].id) {
tree.expandNode(node, false);
}
});
tree.expandNodes = null;
}
return null;
}
let shouldShow = [];
const matchedNodes = tree.getNodesByFilter(filterCallback);
matchedNodes.forEach((node) => {
const parents = this.recurseParent(node);
const children = this.recurseChildren(node);
shouldShow = [...shouldShow, ...parents, ...children, node];
});
tree.hiddenNodes = nodes;
tree.expandNodes = shouldShow;
tree.hideNodes(nodes);
tree.showNodes(shouldShow);
shouldShow.forEach((node) => {
if (node.isParent) {
tree.expandNode(node, true);
}
});
}
filterRemoteApps(keyword) {
if (!this.remoteAppsTree) {
return null;
}
function filterCallback(node: TreeNode) {
return node.name.toLowerCase().indexOf(keyword) !== -1;
}
return this.filterTree(keyword, this.remoteAppsTree, filterCallback);
}
filterAssetsServer(keyword) {
return;
}
filterAssetsLocal(keyword) {
if (!this.assetsTree) {
return null;
}
function filterAssetsCallback(node) {
if (node.isParent) {
return false;
}
const host = node.meta.asset;
return host.hostname.toLowerCase().indexOf(keyword) !== -1 || host.ip.indexOf(keyword) !== -1;
}
return this.filterTree(keyword, this.assetsTree, filterAssetsCallback);
// zTreeObj.expandAll(true);
}
recurseParent(node) {
......@@ -260,54 +317,5 @@ export class ElementAssetTreeComponent implements OnInit, OnChanges {
});
return all_children;
}
filter() {
const zTreeObj = $.fn.zTree.getZTreeObj('ztree');
if (!zTreeObj) {
return null;
}
let _keywords = this.query;
const nodes = zTreeObj.transformToArray(zTreeObj.getNodes());
if (!_keywords) {
if (this.hiddenNodes) {
zTreeObj.showNodes(this.hiddenNodes);
this.hiddenNodes = null;
}
if (this.expandNodes) {
this.expandNodes.forEach((node) => {
if (node.id !== nodes[0].id) {
zTreeObj.expandNode(node, false);
}
});
this.expandNodes = null;
}
return null;
}
_keywords = _keywords.toLowerCase();
let shouldShow = [];
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;
} else {
return node.name.toLowerCase().indexOf(_keywords) !== -1;
}
});
matchedNodes.forEach((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);
}
});
// zTreeObj.expandAll(true);
}
}
......@@ -8,15 +8,10 @@ elements-term, elements-guacamole, elements-settings {
.window {
display: none;
height: 100%;
/*padding: 15px;*/
}
.active {
display: block;
}
.right-side {
height: 100%;
width: 100%;
background-color: gray;
}
......@@ -7,6 +7,7 @@
>
</elements-ssh-term>
<elements-guacamole
[view]="view"
[host]="view.host"
[sysUser]="view.user"
[remoteAppId]="view.remoteApp"
......
<div id="content" fxLayout="column" ngxSplit="column" style="width: 100%;height: 100%;">
<div fxFlex="0 0 30px">
<div class="scroll-botton" style="padding: 0 5px">
<div class="scroll-button" style="padding: 0 5px">
<a class="left" (click)="scrollLeft()"><i class="fa fa-caret-left"></i></a>
<a class="right" (click)="scrollRight()"><i class="fa fa-caret-right"></i></a>
</div>
......@@ -15,9 +15,7 @@
</div>
</div>
<div fxFlex="0 0 calc(100%-35px)" id="winContainer">
<div class="window" *ngFor="let view of viewList; let i=index">
<elements-content-window [view]="view"></elements-content-window>
</div>
<elements-content-window *ngFor="let view of viewList" [view]="view" ></elements-content-window>
</div>
</div>
......
/*.right-side {*/
/*height: 100%;*/
/*width: 100%;*/
/*background-color: gray;*/
/*}*/
/*div {*/
/*height: 100%;*/
/*width: 100%;*/
/*padding: 0;*/
/*background-color: #1f1b1b;*/
/*margin: 0;*/
/*position: initial;*/
/*}*/
/*#content {*/
/*padding-top: 0;*/
/*}*/
/*.container-fluid {*/
/*padding-top: 30px;*/
/*}*/
.tabs {
height: 30px;
overflow-y: hidden;
......@@ -52,7 +29,7 @@
background-color: #F5F5F5;
}
.scroll-botton {
.scroll-button {
font-size: 20px;
float: left;
height: 30px;
......@@ -60,3 +37,7 @@
background-color: #3a3333;
color: white
}
.window {
height: 100%;
}
......@@ -15,7 +15,7 @@ import jQuery from 'jquery/dist/jquery.min';
@Component({
selector: 'elements-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.css']
styleUrls: ['./content.component.scss']
})
export class ElementContentComponent implements OnInit {
viewList: Array<View> = [];
......
......@@ -3,8 +3,7 @@ import {CookieService} from 'ngx-cookie-service';
import {HttpService, LogService} from '../../app.service';
import {DataStore, User} from '../../globals';
import {DomSanitizer} from '@angular/platform-browser';
import {environment} from '../../../environments/environment';
import {NavList} from '../../pages/control/control/control.component';
import {View} from '../content/model';
@Component({
selector: 'elements-guacamole',
......@@ -12,6 +11,7 @@ import {NavList} from '../../pages/control/control/control.component';
styleUrls: ['./guacamole.component.scss']
})
export class ElementGuacamoleComponent implements OnInit {
@Input() view: View;
@Input() host: any;
@Input() sysUser: any;
@Input() remoteAppId: string;
......@@ -36,10 +36,7 @@ export class ElementGuacamoleComponent implements OnInit {
action.subscribe(
data => {
const base = data.result;
this.target = document.location.origin + '/guacamole/#/client/' + base + '?token=' + DataStore.guacamole_token;
setTimeout(() => {
NavList.List[this.index].Rdp = this.el.nativeElement;
}, 500);
this.target = document.location.origin + '/guacamole/#/client/' + base + '?token=' + DataStore.guacamoleToken;
},
error => {
if (!this.registered) {
......@@ -57,8 +54,8 @@ export class ElementGuacamoleComponent implements OnInit {
this._http.getGuacamoleToken(User.id, '').subscribe(
data => {
// /guacamole/client will redirect to http://guacamole/#/client
DataStore.guacamole_token = data['authToken'];
DataStore.guacamole_token_time = nowTime;
DataStore.guacamoleToken = data['authToken'];
DataStore.guacamoleTokenTime = nowTime;
this.registerHost();
},
error => {
......@@ -70,8 +67,8 @@ export class ElementGuacamoleComponent implements OnInit {
ngOnInit() {
// /guacamole/api/tokens will redirect to http://guacamole/api/tokens
this.view.type = 'rdp';
if (this.target) {
NavList.List[this.index].Rdp = this.el.nativeElement;
return null;
}
......@@ -88,7 +85,8 @@ export class ElementGuacamoleComponent implements OnInit {
}
Disconnect() {
NavList.List[this.index].connected = false;
// TOdo:
return;
}
active() {
......
<div class="sidebar" fxLayout="column" ngxSplit="column">
<div fxflex="1 1 30px" class="tree-filter">
<elements-tree-filter></elements-tree-filter>
<elements-tree-filter ></elements-tree-filter>
</div>
<div class="overflow ngx-scroll-overlay" fxflex="1 1 calc(90%-60px)">
<elements-asset-tree [query]="q" ></elements-asset-tree>
<elements-asset-tree ></elements-asset-tree>
</div>
<div class="footer-version" fxflex="1 1 30px">
......
......@@ -43,7 +43,7 @@ export class ElementLeftBarComponent {
}
static Hide() {
DataStore.leftbarshow = false;
DataStore.showLeftBar = false;
DataStore.Nav.map(function (value, i) {
value['children'].forEach((v, key) => {
if (DataStore.Nav[i]['children'][key]['id'] === 'HideLeftManager') {
......@@ -59,7 +59,7 @@ export class ElementLeftBarComponent {
}
static Show() {
DataStore.leftbarshow = true;
DataStore.showLeftBar = true;
DataStore.Nav.map(function (value, i) {
value['children'].forEach((v, key) => {
if (DataStore.Nav[i]['children'][key]['id'] === 'ShowLeftManager') {
......
import {Injectable, EventEmitter} from '@angular/core';
@Injectable()
export class TreeFilterService {
onFilter: EventEmitter<string> = new EventEmitter<string>();
filter(q: string) {
if (q) {
console.log('Emit key to filter...: ', q);
this.onFilter.emit(q);
}
}
}
......@@ -6,7 +6,7 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, Inject, OnInit} from '@angular/core';
import {AppService, HttpService, LocalStorageService, NavService, LogService} from '../../app.service';
import {HttpService, LocalStorageService, NavService, LogService} from '../../app.service';
import {CleftbarComponent} from '../../pages/control/cleftbar/cleftbar.component';
import {ControlComponent, NavList, View} from '../../pages/control/control/control.component';
import {DataStore, i18n} from '../../globals';
......@@ -29,8 +29,7 @@ export class ElementNavComponent implements OnInit {
jQuery('elements-nav').hide();
}
constructor(private _appService: AppService,
private _http: HttpService,
constructor(private _http: HttpService,
private _logger: LogService,
public _dialog: MatDialog,
public _navSvc: NavService,
......
......@@ -12,7 +12,7 @@ import {getWsSocket} from '../../globals';
templateUrl: './ssh-term.component.html',
styleUrls: ['./ssh-term.component.scss']
})
export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy {
export class ElementSshTermComponent implements OnInit, OnDestroy {
@Input() host: any;
@Input() view: View;
@Input() sysUser: any;
......@@ -34,9 +34,7 @@ export class ElementSshTermComponent implements OnInit, AfterViewInit, OnDestroy
this.ws = sock;
this.connectHost();
});
}
ngAfterViewInit() {
this.view.type = 'ssh';
}
newTerm() {
......
<input #keyword id="search" class="search"
<input id="search" class="search"
[formControl]="searchControl"
placeholder=" {{'Search'| trans }} ..."
maxlength="2048"
name="q"
name="keyword"
autocomplete="off"
title="Search"
type="text" tabindex="1" spellcheck="false" [(ngModel)]="q"
type="text" tabindex="1" spellcheck="false"
>
import {Component, OnChanges, Input, Pipe, PipeTransform} from '@angular/core';
import {AppService, HttpService, LogService} from '../../app.service';
import {Component, OnInit, Output, Pipe, PipeTransform, EventEmitter} from '@angular/core';
import {FormControl} from '@angular/forms';
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
import {LogService, TreeFilterService} from '../../app.service';
@Component({
selector: 'elements-tree-filter',
templateUrl: './tree-filter.component.html',
styleUrls: ['./tree-filter.component.css']
styleUrls: ['./tree-filter.component.css'],
})
export class ElementTreeFilterComponent implements OnChanges {
q: string;
@Input() input;
searchRequest: any;
export class ElementTreeFilterComponent implements OnInit {
private searchControl: FormControl;
private debounce = 400;
constructor(private _appService: AppService,
private _http: HttpService,
constructor(private _treeFilterService: TreeFilterService,
private _logger: LogService) {
this._logger.log('LeftbarComponent.ts:SearchBar');
}
ngOnChanges(changes) {
this.q = changes.input.currentValue;
}
modelChange($event) {
this.Search(this.q);
}
public Search(q) {
if (this.searchRequest) {
this.searchRequest.unsubscribe();
}
this.searchRequest = this._http.search(q)
.subscribe(
data => {
this._logger.log(data);
},
err => {
this._logger.error(err);
},
() => {
}
);
this._logger.log(q);
ngOnInit(): void {
this.searchControl = new FormControl('');
this.searchControl.valueChanges
.pipe(debounceTime(this.debounce), distinctUntilChanged())
.subscribe(query => {
this._logger.debug('Tree filter: ', query);
this._treeFilterService.filter(query);
});
}
}
......
......@@ -25,11 +25,11 @@ export const DataStore: _DataStore = {
error: {},
msg: {},
loglevel: 0,
leftbarshow: true,
showLeftBar: true,
windowsize: [],
autologin: false,
guacamole_token: '',
guacamole_token_time: 0
guacamoleToken: '',
guacamoleTokenTime: 0
};
export let Browser = new _Browser();
......
......@@ -88,11 +88,11 @@ export class DataStore {
error: {};
msg: {};
loglevel: number;
leftbarshow = true;
showLeftBar = true;
windowsize: Array<number>;
autologin: boolean;
guacamole_token: string;
guacamole_token_time: number;
guacamoleToken: string;
guacamoleTokenTime: number;
}
......
<ng-progress></ng-progress>
<elements-nav *ngIf="DataStore.NavShow"></elements-nav>
<router-outlet></router-outlet>
<!--<elements-interactive></elements-interactive>-->
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});
/**
* 控制主页
*
*
* @date 2017-11-07
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, HostListener} from '@angular/core';
import {Component} from '@angular/core';
import {DataStore} from '../globals';
import { environment } from '../../environments/environment';
import {AppService} from '../app.service';
@Component({
selector: 'app-root',
......@@ -18,16 +11,7 @@ import { environment } from '../../environments/environment';
export class AppComponent {
DataStore = DataStore;
constructor() {}
@HostListener('window:beforeunload', ['$event'])
unloadNotification($event: any) {
const notInIframe = window.self === window.top;
const notInReplay = location.pathname.indexOf('/luna/replay') === -1;
if (environment.production && notInIframe && notInReplay) {
return false;
}
return true;
constructor(appSrv: AppService) {
}
}
......@@ -55,7 +55,7 @@ export class CleftbarComponent {
}
static Hide() {
DataStore.leftbarshow = false;
DataStore.showLeftBar = false;
DataStore.Nav.map(function (value, i) {
value['children'].forEach((v, key) => {
if (DataStore.Nav[i]['children'][key]['id'] === 'HideLeftManager') {
......@@ -71,7 +71,7 @@ export class CleftbarComponent {
}
static Show() {
DataStore.leftbarshow = true;
DataStore.showLeftBar = true;
DataStore.Nav.map(function (value, i) {
value['children'].forEach((v, key) => {
if (DataStore.Nav[i]['children'][key]['id'] === 'ShowLeftManager') {
......
<elements-nav></elements-nav>
<div id="container" class="container-fluid row" fxLayout="row" ngxSplit="row">
<div fxFlex="1 1 20%" minBasis="100px" maxBasis="800px" fxFlexFill ngxSplitArea *ngIf="DataStore.leftbarshow">
<div fxFlex="1 1 20%" minBasis="100px" maxBasis="800px" fxFlexFill ngxSplitArea *ngIf="DataStore.showLeftBar">
<elements-left-bar></elements-left-bar>
</div>
<div fxFlex="0" ngxSplitHandle [style.display]="activeViewIsRdp() ? 'none' : 'block'" (mouseup)="dragSplitBtn($event)"></div>
<div [fxFlex]="DataStore.leftbarshow ? '1 1 80%' : '1 1 100%'" ngxSplitArea class="content">
<div fxFlex="0" ngxSplitHandle (mouseup)="dragSplitBtn($event)"></div>
<div [fxFlex]="DataStore.showLeftBar ? '1 1 80%' : '1 1 100%'" ngxSplitArea class="content">
<elements-content></elements-content>
</div>
</div>
import {Component, OnInit} from '@angular/core';
import {Component, HostListener, OnInit} from '@angular/core';
import {DataStore, User} from '../../globals';
import {NavList} from '../control/control/control.component';
import {environment} from '../../../environments/environment';
@Component({
selector: 'pages-main',
......@@ -14,11 +14,14 @@ export class PageMainComponent implements OnInit {
ngOnInit(): void {
}
activeViewIsRdp() {
return NavList.List[NavList.Active].type === 'rdp';
}
dragSplitBtn(evt) {
window.dispatchEvent(new Event('resize'));
}
@HostListener('window:beforeunload', ['$event'])
unloadNotification($event: any) {
const notInIframe = window.self === window.top;
const notInReplay = location.pathname.indexOf('/luna/replay') === -1;
return !(environment.production && notInIframe && notInReplay);
}
}
import {PageMainComponent} from './main/main.component';
import {PagesBlankComponent} from './blank/blank.component';
import {PagesConnectComponent} from './connect/connect.component';
// import {PagesControlComponent} from './control/control.component';
import {PagesMonitorComponent} from './monitor/monitor.component';
import {PagesReplayComponent} from './replay/replay.component';
// import {PagesSettingComponent} from './setting/setting.component';
import {PagesNotFoundComponent} from './not-found/not-found.component';
import {PagesLoginComponent} from './login/login.component';
// import {CleftbarComponent} from './control/cleftbar/cleftbar.component';
import {JsonComponent} from './replay/json/json.component';
// import {ControlComponent} from './control/control/control.component';
// import {PagesControlNavComponent} from './control/control/controlnav/nav.component';
// import {SearchComponent, SearchFilter} from './control/search/search.component';
import {PagesMonitorLinuxComponent} from './monitor/linux/linux.component';
import {PagesMonitorWindowsComponent} from './monitor/windows/windows.component';
import {ReplayGuacamoleComponent} from './replay/guacamole/guacamole.component';
......@@ -20,15 +14,10 @@ export const PagesComponents = [
PageMainComponent,
PagesBlankComponent,
PagesConnectComponent,
// PagesControlComponent, ControlComponent, PagesControlNavComponent,
// CleftbarComponent,
PagesMonitorComponent,
PagesReplayComponent, JsonComponent,
// PagesSettingComponent,
PagesNotFoundComponent,
PagesLoginComponent,
// SearchComponent,
// SearchFilter,
PagesMonitorLinuxComponent,
PagesMonitorWindowsComponent,
ReplayGuacamoleComponent
......
......@@ -9,7 +9,7 @@ export const PluginModules = [
BrowserAnimationsModule,
NgProgressModule,
MaterialModule,
LoggerModule.forRoot({serverLoggingUrl: '/api/logs', level: NgxLoggerLevel.DEBUG, serverLogLevel: NgxLoggerLevel.ERROR}),
LoggerModule.forRoot({level: NgxLoggerLevel.DEBUG, serverLogLevel: NgxLoggerLevel.ERROR}),
NgxDatatableModule,
NgxUIModule,
SplitModule
......
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