Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
L
luna
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
luna
Commits
bc92f254
Commit
bc92f254
authored
Sep 10, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 支持新窗口打开
parent
989b0fd8
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
139 additions
and
106 deletions
+139
-106
app.service.ts
src/app/app.service.ts
+10
-6
asset-tree.component.html
src/app/elements/asset-tree/asset-tree.component.html
+4
-6
asset-tree.component.scss
src/app/elements/asset-tree/asset-tree.component.scss
+7
-1
asset-tree.component.ts
src/app/elements/asset-tree/asset-tree.component.ts
+50
-9
connect.component.ts
src/app/elements/connect/connect.component.ts
+0
-1
content-window.component.html
...app/elements/content-window/content-window.component.html
+2
-2
content.component.ts
src/app/elements/content/content.component.ts
+0
-1
guacamole.component.ts
src/app/elements/guacamole/guacamole.component.ts
+2
-1
nav.component.html
src/app/elements/nav/nav.component.html
+1
-1
ssh-term.component.ts
src/app/elements/ssh-term/ssh-term.component.ts
+1
-1
term.component.ts
src/app/elements/term/term.component.ts
+4
-2
connect.component.html
src/app/pages/connect/connect.component.html
+4
-10
connect.component.scss
src/app/pages/connect/connect.component.scss
+7
-0
connect.component.ts
src/app/pages/connect/connect.component.ts
+28
-61
main.component.html
src/app/pages/main/main.component.html
+2
-1
main.component.ts
src/app/pages/main/main.component.ts
+14
-0
zh.json
src/assets/i18n/zh.json
+2
-1
build.sh
tools/build.sh
+1
-2
No files found.
src/app/app.service.ts
View file @
bc92f254
...
...
@@ -78,8 +78,12 @@ export class HttpService {
return
this
.
http
.
get
<
Array
<
TreeNode
>>
(
url
);
}
getMyGrantedRemoteApps
()
{
return
this
.
http
.
get
<
Array
<
TreeNode
>>
(
'/api/perms/v1/user/remote-apps/tree/'
);
getMyGrantedRemoteApps
(
id
?:
string
)
{
let
url
=
'/api/perms/v1/user/remote-apps/tree/'
;
if
(
id
)
{
url
+=
`?id=
${
id
}
&only=1`
;
}
return
this
.
http
.
get
<
Array
<
TreeNode
>>
(
url
);
}
getMyAssetSystemUsers
(
assetId
:
string
)
{
...
...
@@ -339,13 +343,11 @@ export class AppService implements OnInit {
}
checklogin
()
{
this
.
_logger
.
log
(
'service.ts:AppService,checklogin
'
);
this
.
_logger
.
debug
(
'Check user auth
'
);
if
(
!
DataStore
.
Path
)
{
this
.
_router
.
navigate
([
'FOF'
]);
}
if
(
document
.
location
.
pathname
===
'/luna/connect'
)
{
return
;
}
if
(
User
.
logined
)
{
if
(
document
.
location
.
pathname
===
'/login'
)
{
this
.
_router
.
navigate
([
''
]);
...
...
@@ -363,8 +365,10 @@ export class AppService implements OnInit {
err
=>
{
// this._logger.error(err);
User
.
logined
=
false
;
if
(
document
.
location
.
pathname
!==
'/luna/connect'
)
{
window
.
location
.
href
=
document
.
location
.
origin
+
'/users/login?next='
+
document
.
location
.
pathname
+
document
.
location
.
search
;
}
// this._router.navigate(['login']);
},
);
...
...
src/app/elements/asset-tree/asset-tree.component.html
View file @
bc92f254
...
...
@@ -12,12 +12,10 @@
<div
#
rMenu
*
ngIf=
"isShowRMenu"
class=
"basicContext"
[
style
.
top
]="
pos
.
top
"
[
style
.
left
]="
pos
.
left
"
>
<table>
<tbody>
<tr
class=
"basicContext__item "
>
<td
class=
"basicContext__data"
data-num=
"0"
(
click
)="
connectTerminal
()"
>
<span
class=
"basicContext__icon fa fa-terminal new-connection"
></span>
{{ "New Connection"|trans }}
</td>
</tr>
<tr
class=
"basicContext__item basicContext__item--separator"
></tr>
<tr
class=
"basicContext__item "
>
<td
class=
"basicContext__data"
data-num=
"2"
(
click
)="
connectFileManager
()"
><span
class=
"basicContext__icon fa fa-file refresh"
></span>
{{ "File Manager"|trans }}
</td>
<tr
*
ngFor=
"let menu of RMenuList; let i = index"
class=
"basicContext__item "
>
<td
class=
"basicContext__data"
[
attr
.
data-num
]="
i
"
(
click
)="
menu
.
click
()"
[
ngStyle
]="{'
display
'
:
menu
.
hide
?
'
none
'
:
''}"
>
<span
class=
"basicContext__icon fa"
[
ngClass
]="
menu
.
fa
"
></span>
{{ menu.name|trans }}
</td>
</tr>
</tbody>
</table>
...
...
src/app/elements/asset-tree/asset-tree.component.scss
View file @
bc92f254
...
...
@@ -57,8 +57,9 @@
.basicContext
td
{
display
:
block
;
padding
:
0
3
5px
;
padding
:
0
1
5px
;
text-decoration
:
none
;
min-width
:
150px
;
width
:
auto
;
opacity
:
1
;
white-space
:
nowrap
;
...
...
@@ -69,6 +70,11 @@
border-radius
:
0
;
cursor
:
pointer
;
}
.basicContext__icon
{
padding-right
:
5px
;
}
.basicContext__item.basicContext__item--separator
{
background
:
#181414
;
border
:
0
;
...
...
src/app/elements/asset-tree/asset-tree.component.ts
View file @
bc92f254
...
...
@@ -126,9 +126,13 @@ export class ElementAssetTreeComponent implements OnInit, OnDestroy {
const
setting
=
Object
.
assign
({},
this
.
setting
);
setting
[
'callback'
]
=
{
onClick
:
this
.
onRemoteAppsNodeClick
.
bind
(
this
),
onRightClick
:
this
.
onRightClick
.
bind
(
this
)
};
this
.
_http
.
getMyGrantedRemoteApps
().
subscribe
(
resp
=>
{
if
(
!
resp
)
{
return
;
}
const
tree
=
$
.
fn
.
zTree
.
init
(
$
(
'#remoteAppsTree'
),
setting
,
resp
);
this
.
remoteAppsTree
=
tree
;
this
.
rootNodeAddDom
(
tree
,
()
=>
{
...
...
@@ -175,11 +179,11 @@ export class ElementAssetTreeComponent implements OnInit, OnDestroy {
this
.
isShowRMenu
=
false
;
}
onRightClick
(
event
,
treeId
,
treeNode
)
{
if
(
!
treeNode
||
treeNode
.
isParent
)
{
return
null
;
nodeSupportSSH
()
{
const
host
=
this
.
rightClickSelectNode
.
meta
.
asset
;
if
(
!
host
)
{
return
false
;
}
const
host
=
treeNode
.
meta
.
asset
;
let
findSSHProtocol
=
false
;
const
protocols
=
host
.
protocols
||
[];
if
(
host
.
protocol
)
{
...
...
@@ -191,9 +195,34 @@ export class ElementAssetTreeComponent implements OnInit, OnDestroy {
findSSHProtocol
=
true
;
}
}
if
(
!
findSSHProtocol
)
{
alert
(
'Windows 请使用Ctrl+Shift+Alt呼出侧边栏上传下载'
);
return
findSSHProtocol
;
}
get
RMenuList
()
{
const
menuList
=
[{
'id'
:
'new-connection'
,
'name'
:
'Open in new window'
,
'fa'
:
'fa-terminal'
,
'hide'
:
false
,
'click'
:
this
.
connectInNewWindow
.
bind
(
this
)
},
{
'id'
:
'file-manager'
,
'name'
:
'File Manager'
,
'fa'
:
'fa-file'
,
'hide'
:
!
this
.
nodeSupportSSH
(),
'click'
:
this
.
connectFileManager
.
bind
(
this
)
}];
if
(
!
this
.
rightClickSelectNode
)
{
return
[];
}
return
menuList
;
}
onRightClick
(
event
,
treeId
,
treeNode
)
{
if
(
!
treeNode
||
treeNode
.
isParent
)
{
return
null
;
}
this
.
rightClickSelectNode
=
treeNode
;
if
(
!
treeNode
&&
event
.
target
.
tagName
.
toLowerCase
()
!==
'button'
&&
$
(
event
.
target
).
parents
(
'a'
).
length
===
0
)
{
this
.
assetsTree
.
cancelSelectedNode
();
...
...
@@ -211,9 +240,21 @@ export class ElementAssetTreeComponent implements OnInit, OnDestroy {
connectEvt
.
next
(
evt
);
}
connectTerminal
()
{
const
host
=
this
.
rightClickSelectNode
;
this
.
connectAsset
(
host
);
connectInNewWindow
()
{
const
node
=
this
.
rightClickSelectNode
;
let
url
=
'/luna/connect?'
;
switch
(
node
.
meta
.
type
)
{
case
'asset'
:
url
+=
'asset='
+
node
.
meta
.
asset
.
id
;
break
;
case
'remote_app'
:
url
+=
'remote_app='
+
node
.
id
;
break
;
default
:
alert
(
'Unknown type: '
+
node
.
meta
.
type
);
return
;
}
window
.
open
(
url
,
'_blank'
);
}
filterAssets
(
keyword
)
{
...
...
src/app/elements/connect/connect.component.ts
View file @
bc92f254
...
...
@@ -14,7 +14,6 @@ import {View} from '@app/model';
export
class
ElementConnectComponent
implements
OnInit
,
OnDestroy
{
@
Output
()
onNewView
:
EventEmitter
<
View
>
=
new
EventEmitter
<
View
>
();
pos
=
{
left
:
'100px'
,
top
:
'200px'
};
hasLoginTo
=
false
;
constructor
(
private
_appSvc
:
AppService
,
...
...
src/app/elements/content-window/content-window.component.html
View file @
bc92f254
<div
class=
"window"
[
ngClass
]="{'
active
'
:view
.
active
}"
style=
"height: 100%"
>
<div
class=
"window"
[
ngClass
]="{'
active
'
:view
.
active
}"
style=
"height: 100%"
>
<elements-ssh-term
[
view
]="
view
"
[
host
]="
view
.
host
"
...
...
@@ -15,4 +15,4 @@
>
</elements-guacamole>
<app-sftp
*
ngIf=
"view.type=='sftp'"
[
host
]="
view
.
host
"
></app-sftp>
</div>
</div>
src/app/elements/content/content.component.ts
View file @
bc92f254
...
...
@@ -10,7 +10,6 @@ import {ViewService} from '@app/app.service';
export
class
ElementContentComponent
implements
OnInit
{
@
ViewChild
(
'tabs'
)
tabsRef
:
ElementRef
;
viewList
:
Array
<
View
>
;
hasLoginTo
=
false
;
static
DisconnectAll
()
{
}
...
...
src/app/elements/guacamole/guacamole.component.ts
View file @
bc92f254
...
...
@@ -40,7 +40,7 @@ export class ElementGuacamoleComponent implements OnInit {
},
error
=>
{
if
(
!
this
.
registered
)
{
console
.
lo
g
(
'Register host error, register token then connect'
);
this
.
_logger
.
debu
g
(
'Register host error, register token then connect'
);
this
.
registerToken
();
}
}
...
...
@@ -51,6 +51,7 @@ export class ElementGuacamoleComponent implements OnInit {
const
now
=
new
Date
();
const
nowTime
=
now
.
getTime
()
/
1000
;
this
.
registered
=
true
;
this
.
_logger
.
debug
(
'Userid is'
,
User
.
id
);
this
.
_http
.
getGuacamoleToken
(
User
.
id
,
''
).
subscribe
(
data
=>
{
// /guacamole/client will redirect to http://guacamole/#/client
...
...
src/app/elements/nav/nav.component.html
View file @
bc92f254
<div
class=
"nav"
>
<ul
class=
"nav-main"
>
<li>
<li
style=
"padding-right: 10px"
>
<a
href=
"/"
><img
src=
"static/imgs/logo.png"
height=
"26px"
/></a>
</li>
<li
*
ngFor=
"let v of navs"
[
ngClass
]="{'
dropdown
'
:
v
.
children
}"
>
...
...
src/app/elements/ssh-term/ssh-term.component.ts
View file @
bc92f254
...
...
@@ -56,7 +56,7 @@ export class ElementSshTermComponent implements OnInit, OnDestroy {
}
reconnect
()
{
if
(
this
.
view
.
connected
=
==
true
)
{
if
(
this
.
view
.
connected
!
==
true
)
{
if
(
!
confirm
(
translate
(
'Are you sure to reconnect it?(RDP not support)'
)))
{
return
;
}
...
...
src/app/elements/term/term.component.ts
View file @
bc92f254
...
...
@@ -46,11 +46,11 @@ export class ElementTermComponent implements OnInit, AfterViewInit {
getWinSize
()
{
let
availableHeight
=
0
;
let
availableWidth
=
0
;
const
activeEle
=
$
(
'#winContainer'
);
if
(
document
[
'fullscreenElement'
])
{
availableWidth
=
document
.
body
.
clientWidth
-
10
;
availableHeight
=
document
.
body
.
clientHeight
;
}
else
{
const
activeEle
=
$
(
'#winContainer'
);
}
else
if
(
activeEle
)
{
const
elementStyle
=
window
.
getComputedStyle
(
this
.
term
.
element
);
const
elementPadding
=
{
top
:
parseInt
(
elementStyle
.
getPropertyValue
(
'padding-top'
),
10
),
...
...
@@ -63,6 +63,7 @@ export class ElementTermComponent implements OnInit, AfterViewInit {
availableHeight
=
activeEle
.
height
()
-
elementPaddingVer
;
availableWidth
=
activeEle
.
width
()
-
elementPaddingHor
-
(
<
any
>
this
.
term
).
viewport
.
scrollBarWidth
;
}
this
.
_logger
.
debug
(
'Winsize: '
,
availableWidth
,
availableHeight
);
const
dimensions
=
(
<
any
>
this
.
term
).
renderer
.
dimensions
;
const
geometry
=
[
...
...
@@ -76,6 +77,7 @@ export class ElementTermComponent implements OnInit, AfterViewInit {
if
(
!
isFinite
(
geometry
[
1
]))
{
geometry
[
1
]
=
24
;
}
this
.
_logger
.
debug
(
'size: '
,
geometry
);
return
geometry
;
}
...
...
src/app/pages/connect/connect.component.html
View file @
bc92f254
<elements-ssh-term
[
token
]="
token
"
[
index
]="
0
"
*
ngIf=
"system =='linux'"
>
</elements-ssh-term>
<elements-guacamole
[
target
]="
target
"
[
index
]="
0
"
*
ngIf=
"system=='windows' && target"
>
</elements-guacamole>
<div
class=
"windows"
id=
"winContainer"
>
<elements-content-window
[
view
]="
view
"
*
ngIf=
"view"
></elements-content-window>
<elements-connect
[
ngStyle
]="{'
display
'
:
'
none
'}"
(
onNewView
)="
onNewView
($
event
)"
></elements-connect>
</div>
src/app/pages/connect/connect.component.scss
View file @
bc92f254
.windows
{
height
:
100%
;
width
:
100%
;
padding
:
0
;
margin
:
0
;
background-color
:
#1f1b1b
;
}
src/app/pages/connect/connect.component.ts
View file @
bc92f254
import
{
Component
,
OnInit
}
from
'@angular/core'
;
import
{
AppService
,
HttpService
,
LocalStorageService
}
from
'@app/app.service'
;
import
{
DataStore
}
from
'@app/globals'
;
import
*
as
jQuery
from
'jquery/dist/jquery.min.js'
;
import
{
connectEvt
}
from
'@app/globals'
;
import
{
ConnectEvt
}
from
'@app/model'
;
// import {DataStore} from '@app/globals';
// import * as jQuery from 'jquery/dist/jquery.min.js';
import
{
View
,
ViewAction
}
from
'@app/model'
;
@
Component
({
selector
:
'pages-connect'
,
...
...
@@ -11,80 +14,44 @@ import * as jQuery from 'jquery/dist/jquery.min.js';
export
class
PagesConnectComponent
implements
OnInit
{
token
:
string
;
system
:
string
;
authToken
:
string
;
userid
:
string
;
target
:
string
;
base
:
string
;
view
:
View
;
constructor
(
private
_appService
:
AppService
,
private
_http
:
HttpService
,
private
_localStorage
:
LocalStorageService
)
{
DataStore
.
NavShow
=
false
;
}
onNewView
(
view
)
{
view
.
active
=
true
;
this
.
view
=
view
;
}
ngOnInit
()
{
this
.
system
=
this
.
_appService
.
getQueryString
(
'system'
);
this
.
token
=
this
.
_appService
.
getQueryString
(
'token'
);
this
.
userid
=
this
.
_localStorage
.
get
(
'user-'
+
this
.
token
);
this
.
authToken
=
this
.
_localStorage
.
get
(
'authToken-'
+
this
.
token
);
this
.
base
=
this
.
_localStorage
.
get
(
'base-'
+
this
.
token
);
jQuery
(
'body'
).
css
(
'background-color'
,
'#1f1b1b'
);
if
(
this
.
system
===
'windows'
)
{
if
(
!
this
.
userid
)
{
this
.
_http
.
getUserIdFromToken
(
this
.
token
)
.
subscribe
(
data
=>
{
this
.
_localStorage
.
set
(
'user-'
+
this
.
token
,
data
[
'user'
]);
this
.
userid
=
data
[
'user'
];
this
.
getAuthToken
();
}
);
}
else
{
this
.
getAuthToken
();
}
}
}
getAuthToken
()
{
if
(
!
this
.
authToken
)
{
this
.
_http
.
getGuacamoleToken
(
this
.
userid
,
this
.
token
).
subscribe
(
data
=>
{
if
(
data
[
'authToken'
])
{
this
.
_localStorage
.
set
(
'authToken-'
+
this
.
token
,
data
[
'authToken'
]);
this
.
authToken
=
data
[
'authToken'
];
this
.
getBase
();
const
assetId
=
this
.
_appService
.
getQueryString
(
'asset'
);
const
remoteAppId
=
this
.
_appService
.
getQueryString
(
'remote_app'
);
if
(
assetId
)
{
this
.
_http
.
filterMyGrantedAssetsById
(
assetId
).
subscribe
(
nodes
=>
{
if
(
!
nodes
)
{
return
;
}
const
evt
=
new
ConnectEvt
(
nodes
[
0
],
'asset'
);
connectEvt
.
next
(
evt
);
}
);
}
else
{
this
.
getBase
();
}
}
getBase
()
{
if
(
!
this
.
base
)
{
this
.
_http
.
guacamoleTokenAddAsset
(
this
.
token
,
this
.
authToken
).
subscribe
(
data
=>
{
if
(
data
[
'result'
])
{
this
.
_localStorage
.
set
(
'base-'
+
this
.
token
,
data
[
'result'
]);
this
.
base
=
data
[
'result'
];
this
.
setWinTarget
();
}
});
}
else
{
this
.
setWinTarget
();
if
(
remoteAppId
)
{
this
.
_http
.
getMyGrantedRemoteApps
(
remoteAppId
).
subscribe
(
nodes
=>
{
if
(
!
nodes
)
{
return
;
}
const
evt
=
new
ConnectEvt
(
nodes
[
0
],
'asset'
);
connectEvt
.
next
(
evt
);
}
setWinTarget
()
{
if
(
this
.
base
&&
this
.
authToken
)
{
this
.
target
=
document
.
location
.
origin
+
'/guacamole/#/client/'
+
this
.
base
+
'?asset_token=jumpserver&token='
+
this
.
authToken
;
}
else
{
window
.
location
.
reload
();
);
}
}
}
src/app/pages/main/main.component.html
View file @
bc92f254
...
...
@@ -6,7 +6,8 @@
>
<elements-left-bar></elements-left-bar>
</div>
<div
ngxSplitHandle
(
mouseup
)="
dragSplitBtn
($
event
)"
class=
"handle handle-row"
[
ngStyle
]="{'
display
'
:
store
.
showLeftBar
?
''
:
'
none
'}"
>
<div
ngxSplitHandle
(
mouseup
)="
dragSplitBtn
($
event
)"
class=
"handle handle-row"
[
ngStyle
]="{'
display
'
:
showSplitter
?
''
:
'
none
'}"
>
<i
class=
"fa fa-window-minimize"
style=
"color: white"
></i>
</div>
<div
[
fxFlex
]="
store
.
showLeftBar
?
'
80
%'
:
'
100
%'"
fxFlexFill
ngxSplitArea
class=
"content"
>
...
...
src/app/pages/main/main.component.ts
View file @
bc92f254
import
{
Component
,
HostListener
,
OnInit
}
from
'@angular/core'
;
import
{
DataStore
,
User
}
from
'@app/globals'
;
import
{
environment
}
from
'@src/environments/environment'
;
import
{
ViewService
}
from
'@app/app.service'
;
@
Component
({
selector
:
'pages-main'
,
...
...
@@ -11,6 +12,19 @@ export class PageMainComponent implements OnInit {
User
=
User
;
store
=
DataStore
;
constructor
(
public
viewSrv
:
ViewService
)
{}
get
currentView
()
{
return
this
.
viewSrv
.
currentView
;
}
get
showSplitter
()
{
if
(
this
.
currentView
&&
this
.
currentView
.
type
!==
'ssh'
)
{
return
false
;
}
return
this
.
store
.
showLeftBar
;
}
ngOnInit
():
void
{
}
...
...
src/assets/i18n/zh.json
View file @
bc92f254
...
...
@@ -70,5 +70,6 @@
"load tree sync"
:
"同步加载树"
,
"show manual password"
:
"显示手动密码窗"
,
"skip manual password"
:
"跳过手动密码窗"
,
"tab list"
:
"窗口列表"
"tab list"
:
"窗口列表"
,
"open in new window"
:
"新窗口打开"
}
tools/build.sh
View file @
bc92f254
...
...
@@ -2,10 +2,9 @@
set
-ex
rm
-fr
luna
npm run-script build
rm
-fr
luna
*
mv
dist luna
cp
-R
src/assets/i18n luna/
tar
czf luna.tar.gz luna
md5 luna.tar.gz
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment