Unverified Commit ee0f3c22 authored by 老广's avatar 老广 Committed by GitHub

Merge pull request #104 from jumpserver/dev_beta

Dev beta
parents 77910c92 6bb66d4f
......@@ -8,6 +8,6 @@ RUN npm run-script build
FROM nginx:alpine
COPY --from=stage-build /data/dist /opt/luna/
COPY --from=stage-build /data/luan /opt/luna/
COPY ./src/assets/i18n /opt/luna/i18n
COPY nginx.conf /etc/nginx/conf.d/default.conf
......@@ -7,7 +7,9 @@ import {CookieService} from 'ngx-cookie-service';
import {MAT_LABEL_GLOBAL_OPTIONS} from '@angular/material';
// service
import {AppService, HttpService, LocalStorageService, NavService, LogService, UUIDService, TreeFilterService} from './app.service';
import {AppService, HttpService, LocalStorageService, NavService, LogService,
UUIDService, TreeFilterService, ViewService,
} from './app.service';
import {AppRouterModule} from './router/router.module';
import {Pipes} from './pipes/pipes';
......@@ -55,6 +57,7 @@ import {AssetTreeDialogComponent, ManualPasswordDialogComponent} from './element
LocalStorageService,
CookieService,
TreeFilterService,
ViewService,
NGXLogger,
{provide: MAT_LABEL_GLOBAL_OPTIONS, useValue: {float: 'always'}}
]
......
......@@ -2,11 +2,10 @@ import {EventEmitter, Injectable, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {CookieService} from 'ngx-cookie-service';
import {DataStore, User, Browser, i18n} from './globals';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {NGXLogger} from 'ngx-logger';
import {SystemUser, GuacObjAddResp, TreeNode, User as _User, NavEvt} from './model';
import {SystemUser, GuacObjAddResp, TreeNode, User as _User, NavEvt, View} from './model';
import {environment} from '../environments/environment';
import * as UUID from 'uuid-js/lib/uuid.js';
......@@ -66,6 +65,11 @@ export class HttpService {
return this.http.get<Array<TreeNode>>(url);
}
filterMyGrantedAssetsById(id: string) {
const url = `/api/perms/v1/users/assets/tree/?id=${id}`;
return this.http.get<Array<TreeNode>>(url);
}
getMyGrantedNodes(async: boolean, refresh?: boolean) {
const cachePolicy = refresh ? '2' : '1';
const syncUrl = `/api/perms/v1/users/nodes-with-assets/tree/?cache_policy=${cachePolicy}`;
......@@ -442,3 +446,34 @@ export class TreeFilterService {
this.onFilter.emit(q);
}
}
@Injectable()
export class ViewService {
viewList: Array<View> = [];
currentView: View;
num = 0;
addView(view: View) {
this.num += 1;
view.id = 'View_' + this.num;
this.viewList.push(view);
}
activeView(view: View) {
this.viewList.forEach((v, k) => {
v.active = v === view;
});
setTimeout(() => {
const viewEl = document.getElementById(view.id);
if (viewEl) {
viewEl.scrollIntoView();
}
}, 100);
this.currentView = view;
}
removeView(view: View) {
const index = this.viewList.indexOf(view);
this.viewList.splice(index, 1);
}
}
......@@ -141,20 +141,6 @@ export class ElementAssetTreeComponent implements OnInit, OnDestroy {
initTree() {
this.initAssetsTree();
this.initRemoteAppsTree();
// Todo: connect to some asset, direct
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.connectAsset(t);
return;
}
});
}
});
}
connectAsset(node: TreeNode) {
......@@ -289,12 +275,12 @@ export class ElementAssetTreeComponent implements OnInit, OnDestroy {
if (!this.assetsTree) {
return;
}
if (!keyword) {
const searchNode = this.assetsTree.getNodesByFilter((node) => node.id === 'search');
if (searchNode) {
this.assetsTree.removeChildNodes(searchNode[0]);
this.assetsTree.removeNode(searchNode[0]);
}
if (!keyword) {
const treeNodes = this.assetsTree.getNodes();
if (treeNodes.length !== 0) {
this.assetsTree.showNode(treeNodes[0]);
......
import {Component, Input, OnInit, Output, Inject, OnDestroy, EventEmitter} from '@angular/core';
import {Component, OnInit, Output, Inject, OnDestroy, EventEmitter} from '@angular/core';
import {connectEvt} from '@app/globals';
import {AppService, HttpService, LogService, NavService} from '@app/app.service';
import {AppService, HttpService, LogService} from '@app/app.service';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
import {FormControl, Validators} from '@angular/forms';
import {ActivatedRoute} from '@angular/router';
import {SystemUser, TreeNode, Asset} from '@app/model';
import {View} from '@app/model';
import * as jQuery from 'jquery/dist/jquery.min';
declare var $: any;
@Component({
selector: 'elements-connect',
......@@ -41,6 +38,20 @@ export class ElementConnectComponent implements OnInit, OnDestroy {
}
}
});
this.activatedRoute.queryParams.subscribe(params => {
const login_to = params['login_to'];
if (login_to && !this.hasLoginTo) {
this._http.filterMyGrantedAssetsById(login_to).subscribe(
nodes => {
if (nodes.length === 1) {
this.hasLoginTo = true;
const node = nodes[0];
this.Connect(node);
}
}
);
}
});
}
ngOnDestroy(): void {
connectEvt.unsubscribe();
......
......@@ -29,10 +29,6 @@ export class ElementContentViewComponent implements OnInit {
}
static DisconnectAll() {
// for (let i = 0; i < viewList.List.length; i++) {
// Todo:
// ContentComponent.TerminalDisconnect(i);
// }
}
constructor() {
......
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {View, ViewAction} from '@app/model';
import {ViewService} from '@app/app.service';
@Component({
selector: 'elements-content',
......@@ -8,7 +9,8 @@ import {View, ViewAction} from '@app/model';
})
export class ElementContentComponent implements OnInit {
@ViewChild('tabs') tabsRef: ElementRef;
viewList: Array<View> = [];
viewList: Array<View>;
hasLoginTo = false;
static DisconnectAll() {
}
......@@ -17,16 +19,17 @@ export class ElementContentComponent implements OnInit {
return (this.viewList.length + 1) * 151 + 10;
}
constructor() {
constructor(private viewSrv: ViewService) {
}
ngOnInit() {
this.viewList = this.viewSrv.viewList;
}
onNewView(view) {
this.scrollToEnd();
setTimeout(() => {
this.viewList.push(view);
this.viewSrv.addView(view);
this.setViewActive(view);
}, 100);
}
......@@ -45,9 +48,7 @@ export class ElementContentComponent implements OnInit {
}
setViewActive(view) {
this.viewList.forEach((v, k) => {
v.active = v === view;
});
this.viewSrv.activeView(view);
}
closeView(view) {
......@@ -61,7 +62,7 @@ export class ElementContentComponent implements OnInit {
nextActiveView = this.viewList[index + 1];
}
}
this.viewList.splice(index, 1);
this.viewSrv.removeView(view);
if (nextActiveView) {
this.setViewActive(nextActiveView);
}
......
......@@ -84,11 +84,6 @@ export class ElementGuacamoleComponent implements OnInit {
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
}
Disconnect() {
// TOdo:
return;
}
active() {
this.el.nativeElement.focus();
}
......
import {Component, Inject, OnInit, ViewChild, ElementRef} from '@angular/core';
import {AppService, HttpService, LogService} from '@app/app.service';
// import {ElementTreeFilterComponent} from '../tree-filter/tree-filter.component';
import {Component} from '@angular/core';
import {DataStore} from '@app/globals';
import {version} from '@src/environments/environment';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
export interface Node {
id: string;
name: string;
comment: string;
title: string;
isParent: boolean;
pId: string;
open: boolean;
iconSkin: string;
meta: object;
}
export class Host {
name: string;
id: string;
type: string;
}
@Component({
selector: 'elements-left-bar',
templateUrl: './left-bar.component.html',
styleUrls: ['./left-bar.component.scss'],
// providers: [ElementTreeFilterComponent]
})
export class ElementLeftBarComponent {
DataStore = DataStore;
version = version;
q: string;
event: MouseEvent;
clientX = 0;
clientY = 0;
TooltipPosition = 'above';
static Reload() {
}
static Hide() {
DataStore.showLeftBar = false;
DataStore.Nav.map(function (value, i) {
value['children'].forEach((v, key) => {
if (DataStore.Nav[i]['children'][key]['id'] === 'HideLeftManager') {
DataStore.Nav[i]['children'][key] = {
'id': 'ShowLeftManager',
'click': 'ShowLeft',
'name': 'Show left manager'
};
}
});
});
window.dispatchEvent(new Event('resize'));
}
static Show() {
DataStore.showLeftBar = true;
DataStore.Nav.map(function (value, i) {
value['children'].forEach((v, key) => {
if (DataStore.Nav[i]['children'][key]['id'] === 'ShowLeftManager') {
DataStore.Nav[i]['children'][key] = {
'id': 'HideLeftManager',
'click': 'HideLeft',
'name': 'Hide left manager'
};
}
});
});
window.dispatchEvent(new Event('resize'));
}
constructor(private _appService: AppService,
private _http: HttpService,
private _logger: LogService,
public _dialog: MatDialog,
) {
this._logger.log('nav.ts:NavComponent');
}
Search(q) {
// Todo:
// this._search.Search(q);
}
onRightClick(event: MouseEvent): void {
this.clientX = event.clientX;
this.clientY = event.clientY;
}
}
......@@ -71,7 +71,7 @@
display: flex;
}
.nav .dropdown-content li a {
.nav .dropdown-content a {
padding: 6px 14px 6px 25px;
white-space: nowrap;
font-family: 'Roboto', sans-serif;
......@@ -110,7 +110,14 @@
background-color: darkgray;
}
.nav ul li.active {
box-sizing: border-box;
border-bottom: 3px solid #19aa8d !important;
.flag {
display: none;
color: #19aa8d;
padding-right: 10px;
}
.active .flag {
display: inline;
}
......@@ -12,5 +12,17 @@
</li>
</ul>
</li>
<li [ngClass]="{'dropdown': true}">
<a>{{"Tab List"|trans}}</a>
<ul *ngIf="viewList.length > 0" [ngClass]="{'dropdown-content': true}">
<ng-container *ngFor="let v of viewList, let idx = index" >
<li *ngIf="v.nick!=null" [ngClass]="{'disconnected':!v.connected, 'hidden': v.closed != false}">
<span [class.active]="v.active">
<a id="{{ 'tab' + idx }}" (click)="_viewSrv.activeView(v)"><i class="fa fa-circle flag"></i> {{v.nick}} </a>
</span>
</li>
</ng-container>
</ul>
</li>
</ul>
</div>
......@@ -6,11 +6,12 @@
* @author liuzheng <liuzheng712@gmail.com>
*/
import {Component, Inject, OnInit} from '@angular/core';
import {HttpService, LocalStorageService, NavService, LogService} from '@app/app.service';
import {HttpService, LocalStorageService, NavService, LogService, ViewService} from '@app/app.service';
import {DataStore, i18n} from '@app/globals';
import * as jQuery from 'jquery/dist/jquery.min.js';
import {ElementLeftBarComponent} from '@app/elements/left-bar/left-bar.component';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
declare let layer: any;
import {View} from '@app/model';
@Component({
selector: 'elements-nav',
......@@ -21,6 +22,7 @@ export class ElementNavComponent implements OnInit {
DataStore = DataStore;
navs: Array<any>;
_asyncTree = false;
viewList: Array<View>;
static Hide() {
jQuery('elements-nav').hide();
......@@ -30,13 +32,13 @@ export class ElementNavComponent implements OnInit {
private _logger: LogService,
public _dialog: MatDialog,
public _navSvc: NavService,
public _viewSrv: ViewService,
private _localStorage: LocalStorageService) {
this._logger.log('nav.ts:NavComponent');
this.getNav();
}
ngOnInit() {
this.navs = this.getNav();
this.viewList = this._viewSrv.viewList;
}
get treeLoadAsync() {
......@@ -54,12 +56,12 @@ export class ElementNavComponent implements OnInit {
break;
}
case 'HideLeft': {
DataStore.showLeftBar = false;
ElementLeftBarComponent.Hide();
this.refreshNav();
break;
}
case 'ShowLeft': {
DataStore.showLeftBar = true;
ElementLeftBarComponent.Show();
this.refreshNav();
break;
}
......@@ -90,11 +92,6 @@ export class ElementNavComponent implements OnInit {
window.dispatchEvent(new Event('resize'));
break;
}
case'Disconnect': {
if (!confirm('断开当前连接?')) {
return
}
}
case 'Reconnect': {
break;
}
......
......@@ -21,7 +21,7 @@ export class ElementTermComponent implements OnInit, AfterViewInit {
@Output() winSizeChangeTrigger = new EventEmitter<Array<number>>();
winSizeChange$: Observable<any>;
constructor(private _logger: LogService){
constructor(private _logger: LogService) {
}
......@@ -33,6 +33,7 @@ export class ElementTermComponent implements OnInit, AfterViewInit {
this.winSizeChange$
.subscribe(() => {
this._logger.debug('Get win size change event');
this.resizeTerm();
});
}
......
......@@ -22,7 +22,7 @@
/*}*/
.left-side {
min-width: 100px;
}
.handle {
......@@ -31,7 +31,7 @@
user-select: none;
z-index: 9999;
height: 5px;
width: 1px;
width: 0;
display: block;
padding: 0;
margin: 0;
......
<elements-nav></elements-nav>
<div fxLayout="row" id="container" ngxSplit="row">
<div fxFlex="20%" fxFlexFill maxBasis="400px" minBasis="100px" ngxSplitArea *ngIf="DataStore.showLeftBar" class="left-side">
<div fxFlex="20%" fxFlexFill ngxSplitArea
[ngStyle]="{'display': store.showLeftBar ? '' : 'none', 'min-width': store.showLeftBar ? '100px': ''}"
class="left-side"
>
<elements-left-bar></elements-left-bar>
</div>
<div ngxSplitHandle (mouseup)="dragSplitBtn($event)" class="handle handle-row" *ngIf="DataStore.showLeftBar" >
<div ngxSplitHandle (mouseup)="dragSplitBtn($event)" class="handle handle-row" [ngStyle]="{'display': store.showLeftBar ? '' : 'none'}" >
<i class="fa fa-window-minimize" style="color: white"></i>
</div>
<div [fxFlex]="DataStore.showLeftBar ? '80%' : '100%'" fxFlexFill ngxSplitArea class="content">
<div [fxFlex]="store.showLeftBar ? '80%' : '100%'" fxFlexFill ngxSplitArea class="content">
<elements-content></elements-content>
</div>
</div>
......@@ -9,7 +9,7 @@ import {environment} from '@src/environments/environment';
})
export class PageMainComponent implements OnInit {
User = User;
DataStore = DataStore;
store = DataStore;
ngOnInit(): void {
}
......
......@@ -69,5 +69,6 @@
"load tree async": "异步加载树",
"load tree sync": "同步加载树",
"show manual password": "显示手动密码窗",
"skip manual password": "跳过手动密码窗"
"skip manual password": "跳过手动密码窗",
"tab list": "窗口列表"
}
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