Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
atlas
Project
Overview
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
dataplatform
atlas
Commits
27916dd4
Commit
27916dd4
authored
6 years ago
by
gutkaBinit
Committed by
Sarath Subramanian
6 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ATLAS-3031: UI : Allow user to export the lineage in PNG formatt
Signed-off-by:
Sarath Subramanian
<
ssubramanian@hortonworks.com
>
parent
f92e06cd
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
160 additions
and
14 deletions
+160
-14
graph.scss
dashboardv2/public/css/scss/graph.scss
+5
-0
LineageLayoutView_tmpl.html
...dv2/public/js/templates/graph/LineageLayoutView_tmpl.html
+8
-4
LineageLayoutView.js
dashboardv2/public/js/views/graph/LineageLayoutView.js
+147
-10
No files found.
dashboardv2/public/css/scss/graph.scss
View file @
27916dd4
...
@@ -421,4 +421,8 @@ span#zoom_in {
...
@@ -421,4 +421,8 @@ span#zoom_in {
word-break
:
break-all
;
word-break
:
break-all
;
}
}
}
.hidden-svg
{
visibility
:
hidden
;
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
View file @
27916dd4
...
@@ -90,6 +90,11 @@
...
@@ -90,6 +90,11 @@
</div>
</div>
<div
class=
"graph-button-group pull-right"
>
<div
class=
"graph-button-group pull-right"
>
<div>
<div>
<button
data-id=
"saveSvg"
class=
"disabled btn btn-action btn-gray btn-sm"
title=
"Export to PNG"
>
<i
class=
"fa fa-camera"
></i>
</button>
</div>
<div>
<button
type=
"button"
data-id=
"setting-toggler"
class=
"btn btn-action btn-gray btn-sm"
><i
class=
"fa fa-gear"
></i></button>
<button
type=
"button"
data-id=
"setting-toggler"
class=
"btn btn-action btn-gray btn-sm"
><i
class=
"fa fa-gear"
></i></button>
</div>
</div>
<div>
<div>
...
@@ -127,12 +132,11 @@
...
@@ -127,12 +132,11 @@
<div
class=
"fontLoader"
>
<div
class=
"fontLoader"
>
<i
class=
"fa fa-refresh fa-spin-custom"
></i>
<i
class=
"fa fa-refresh fa-spin-custom"
></i>
</div>
</div>
<canvas
width=
"960"
height=
"500"
style=
"display:none; position: absolute;"
></canvas>
<div
class=
"legends pull-left"
style=
"height: 25px; padding: 2px;"
>
<div
class=
"legends pull-left"
style=
"height: 25px; padding: 2px;"
>
<span
style=
"margin-right: 8px; color:#fb4200;"
><i
class=
"fa fa-circle-o fa-fw"
aria-hidden=
"true"
></i>
Current Entity
</span>
<span
style=
"margin-right: 8px; color:#fb4200;"
><i
class=
"fa fa-circle-o fa-fw"
aria-hidden=
"true"
></i>
Current Entity
</span>
<span
style=
"margin-right: 8px; color:#df9b00;"
><i
class=
"fa fa-long-arrow-right fa-fw"
aria-hidden=
"true"
></i>
Lineage
</span>
<span
style=
"margin-right: 8px; color:#df9b00;"
><i
class=
"fa fa-long-arrow-right fa-fw"
aria-hidden=
"true"
></i>
Lineage
</span>
<span
style=
"margin-right: 8px; color:#fb4200;"
><i
class=
"fa fa-long-arrow-right fa-fw"
aria-hidden=
"true"
></i>
Impact
</span>
<span
style=
"margin-right: 8px; color:#fb4200;"
><i
class=
"fa fa-long-arrow-right fa-fw"
aria-hidden=
"true"
></i>
Impact
</span>
</div>
</div>
<!-- <svg width="100%" height="calc(100% - 28px)" preserveAspectRatio="xMidYMid meet" viewBox="0 0 854 330" enable-background="new 0 0 854 330" xml:space="preserve"></svg> -->
<svg
width=
"{{width}}"
height=
"{{height}}"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
version=
"1.1"
></svg>
<svg
width=
"{{width}}"
height=
"{{height}}"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
version=
"1.1"
></svg>
</div>
</div>
\ No newline at end of file
<div
class=
"hidden-svg"
></div>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
dashboardv2/public/js/views/graph/LineageLayoutView.js
View file @
27916dd4
...
@@ -63,7 +63,8 @@ define(['require',
...
@@ -63,7 +63,8 @@ define(['require',
searchNode
:
'[data-id="searchNode"]'
,
searchNode
:
'[data-id="searchNode"]'
,
nodeDetailTable
:
'[data-id="nodeDetailTable"]'
,
nodeDetailTable
:
'[data-id="nodeDetailTable"]'
,
showOnlyHoverPath
:
'[data-id="showOnlyHoverPath"]'
,
showOnlyHoverPath
:
'[data-id="showOnlyHoverPath"]'
,
showTooltip
:
'[data-id="showTooltip"]'
showTooltip
:
'[data-id="showTooltip"]'
,
saveSvg
:
'[data-id="saveSvg"]'
,
},
},
templateHelpers
:
function
()
{
templateHelpers
:
function
()
{
return
{
return
{
...
@@ -82,6 +83,7 @@ define(['require',
...
@@ -82,6 +83,7 @@ define(['require',
events
[
"click "
+
this
.
ui
.
settingToggler
]
=
'onClickSettingToggler'
;
events
[
"click "
+
this
.
ui
.
settingToggler
]
=
'onClickSettingToggler'
;
events
[
"click "
+
this
.
ui
.
lineageFullscreenToggler
]
=
'onClickLineageFullscreenToggler'
;
events
[
"click "
+
this
.
ui
.
lineageFullscreenToggler
]
=
'onClickLineageFullscreenToggler'
;
events
[
"click "
+
this
.
ui
.
searchToggler
]
=
'onClickSearchToggler'
;
events
[
"click "
+
this
.
ui
.
searchToggler
]
=
'onClickSearchToggler'
;
events
[
"click "
+
this
.
ui
.
saveSvg
]
=
'onClickSaveSvg'
;
return
events
;
return
events
;
},
},
...
@@ -488,7 +490,8 @@ define(['require',
...
@@ -488,7 +490,8 @@ define(['require',
createGraph
:
function
()
{
createGraph
:
function
()
{
var
that
=
this
,
var
that
=
this
,
width
=
this
.
$
(
'svg'
).
width
(),
width
=
this
.
$
(
'svg'
).
width
(),
height
=
this
.
$
(
'svg'
).
height
();
height
=
this
.
$
(
'svg'
).
height
(),
imageObject
=
{};
this
.
g
.
nodes
().
forEach
(
function
(
v
)
{
this
.
g
.
nodes
().
forEach
(
function
(
v
)
{
var
node
=
that
.
g
.
node
(
v
);
var
node
=
that
.
g
.
node
(
v
);
// Round the corners of the nodes
// Round the corners of the nodes
...
@@ -500,6 +503,8 @@ define(['require',
...
@@ -500,6 +503,8 @@ define(['require',
var
render
=
new
dagreD3
.
render
();
var
render
=
new
dagreD3
.
render
();
// Add our custom arrow (a hollow-point)
// Add our custom arrow (a hollow-point)
render
.
arrows
().
arrowPoint
=
function
normal
(
parent
,
id
,
edge
,
type
)
{
render
.
arrows
().
arrowPoint
=
function
normal
(
parent
,
id
,
edge
,
type
)
{
var
parentNode
=
parent
&&
parent
[
0
]
&&
parent
[
0
][
0
]
&&
parent
[
0
][
0
].
parentNode
?
parent
[
0
][
0
].
parentNode
:
parent
;
d3
.
select
(
parentNode
).
select
(
'path.path'
).
attr
(
'marker-end'
,
"url(#"
+
id
+
")"
);
var
marker
=
parent
.
append
(
"marker"
)
var
marker
=
parent
.
append
(
"marker"
)
.
attr
(
"id"
,
id
)
.
attr
(
"id"
,
id
)
.
attr
(
"viewBox"
,
"0 0 10 10"
)
.
attr
(
"viewBox"
,
"0 0 10 10"
)
...
@@ -536,17 +541,49 @@ define(['require',
...
@@ -536,17 +541,49 @@ define(['require',
.
attr
(
"height"
,
"100%"
)
.
attr
(
"height"
,
"100%"
)
.
append
(
'image'
)
.
append
(
'image'
)
.
attr
(
"xlink:href"
,
function
(
d
)
{
.
attr
(
"xlink:href"
,
function
(
d
)
{
var
that
=
this
;
if
(
node
)
{
if
(
node
)
{
return
Utils
.
getEntityIconPath
({
entityData
:
node
});
var
imageIconPath
=
Utils
.
getEntityIconPath
({
entityData
:
node
}),
imagePath
=
((
window
.
location
.
origin
+
Utils
.
getBaseUrl
(
window
.
location
.
pathname
))
+
imageIconPath
);
var
xhr
=
new
XMLHttpRequest
();
xhr
.
responseType
=
'blob'
;
xhr
.
onload
=
function
()
{
var
reader
=
new
FileReader
();
reader
.
onloadend
=
function
()
{
_
.
each
(
imageObject
[
imageIconPath
],
function
(
obj
)
{
obj
.
attr
(
"xlink:href"
,
reader
.
result
);
});
imageObject
[
imageIconPath
]
=
reader
.
result
;
}
if
(
xhr
.
status
!=
404
)
{
reader
.
readAsDataURL
(
xhr
.
response
);
}
else
{
xhr
.
open
(
'GET'
,
Utils
.
getEntityIconPath
({
entityData
:
node
,
errorUrl
:
this
.
responseURL
}),
true
);
xhr
.
send
();
}
}
if
(
_
.
isUndefined
(
imageObject
[
imageIconPath
]))
{
// before img success
imageObject
[
imageIconPath
]
=
[
d3
.
select
(
that
)];
xhr
.
open
(
'GET'
,
imagePath
,
true
);
xhr
.
send
();
}
else
if
(
_
.
isArray
(
imageObject
[
imageIconPath
]))
{
// before img success
imageObject
[
imageIconPath
].
push
(
d3
.
select
(
that
));
}
else
{
d3
.
select
(
that
).
attr
(
"xlink:href"
,
imageObject
[
imageIconPath
]);
return
imageObject
[
imageIconPath
];
}
}
}
})
})
.
attr
(
"x"
,
"4"
)
.
attr
(
"x"
,
"4"
)
.
attr
(
"y"
,
currentNode
?
"3"
:
"4"
)
.
attr
(
"y"
,
currentNode
?
"3"
:
"4"
).
attr
(
"width"
,
"40"
)
.
attr
(
"width"
,
"40"
)
.
attr
(
"height"
,
"40"
);
.
attr
(
"height"
,
"40"
)
.
on
(
"error"
,
function
()
{
this
.
setAttributeNS
(
'http://www.w3.org/1999/xlink'
,
'xlink:href'
,
Utils
.
getEntityIconPath
({
entityData
:
node
,
errorUrl
:
this
.
href
.
baseVal
}));
});
node
.
intersect
=
function
(
point
)
{
node
.
intersect
=
function
(
point
)
{
return
dagreD3
.
intersect
.
circle
(
node
,
currentNode
?
24
:
21
,
point
);
return
dagreD3
.
intersect
.
circle
(
node
,
currentNode
?
24
:
21
,
point
);
...
@@ -770,6 +807,7 @@ define(['require',
...
@@ -770,6 +807,7 @@ define(['require',
g
:
this
.
g
,
g
:
this
.
g
,
guid
:
this
.
guid
guid
:
this
.
guid
}).
init
();
}).
init
();
this
.
$el
.
find
(
'[data-id="saveSvg"]'
).
removeClass
(
'disabled'
)
},
},
renderLineageTypeSearch
:
function
()
{
renderLineageTypeSearch
:
function
()
{
var
that
=
this
;
var
that
=
this
;
...
@@ -870,7 +908,105 @@ define(['require',
...
@@ -870,7 +908,105 @@ define(['require',
"attributeDefs"
:
attributeDefs
,
"attributeDefs"
:
attributeDefs
,
"sortBy"
:
false
"sortBy"
:
false
}));
}));
}
},
onClickSaveSvg
:
function
(
e
,
a
)
{
var
that
=
this
;
var
loaderTargetDiv
=
$
(
e
.
currentTarget
).
find
(
'>i'
);
if
(
$
(
e
.
currentTarget
).
hasClass
(
'disabled'
))
{
Utils
.
notifyWarn
({
content
:
"Lineage can be downloaded once it is rendered."
});
return
false
;
// return if the lineage is not loaded.
}
if
(
loaderTargetDiv
.
hasClass
(
'fa-refresh'
))
{
Utils
.
notifyWarn
({
content
:
"Please wait while the lineage gets downloaded"
});
return
false
;
// return if the lineage is not loaded.
}
that
.
toggleLoader
(
loaderTargetDiv
);
Utils
.
notifyInfo
({
content
:
"Lineage will be downloaded in a moment."
});
setTimeout
(
function
()
{
var
svg
=
that
.
$
(
'svg'
)[
0
],
svgClone
=
svg
.
cloneNode
(
true
),
scaleFactor
=
1
;
$
(
'.hidden-svg'
).
html
(
svgClone
);
$
(
svgClone
).
find
(
'>g'
).
attr
(
"transform"
,
"scale("
+
scaleFactor
+
")"
);
var
canvasOffset
=
{
x
:
150
,
y
:
150
},
setWidth
=
(
svgClone
.
getBBox
().
width
+
(
canvasOffset
.
x
)),
setHeight
=
(
svgClone
.
getBBox
().
height
+
(
canvasOffset
.
y
));
svgClone
.
attributes
.
viewBox
.
value
=
"-10,-10,"
+
setWidth
+
","
+
setHeight
;
var
createCanvas
=
document
.
createElement
(
'canvas'
);
createCanvas
.
id
=
"canvas"
;
createCanvas
.
style
.
display
=
'none'
;
var
body
=
$
(
'body'
).
append
(
createCanvas
),
canvas
=
$
(
'canvas'
)[
0
];
canvas
.
width
=
(
svgClone
.
getBBox
().
width
*
scaleFactor
)
+
canvasOffset
.
x
;
canvas
.
height
=
(
svgClone
.
getBBox
().
height
*
scaleFactor
)
+
canvasOffset
.
y
;
var
ctx
=
canvas
.
getContext
(
'2d'
),
data
=
(
new
XMLSerializer
()).
serializeToString
(
svgClone
),
DOMURL
=
window
.
URL
||
window
.
webkitURL
||
window
;
ctx
.
fillStyle
=
"#FFFFFF"
;
ctx
.
fillRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
);
ctx
.
strokeRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
);
ctx
.
restore
();
var
img
=
new
Image
(
canvas
.
width
,
canvas
.
height
);
var
svgBlob
=
new
Blob
([
data
],
{
type
:
'image/svg+xml;base64'
});
var
url
=
DOMURL
.
createObjectURL
(
svgBlob
);
img
.
onload
=
function
()
{
try
{
var
a
=
document
.
createElement
(
"a"
);
a
.
download
=
"download.png"
;
ctx
.
drawImage
(
img
,
50
,
50
,
canvas
.
width
,
canvas
.
height
);
canvas
.
toBlob
(
function
(
blob
)
{
if
(
!
blob
)
{
Utils
.
notifyError
({
content
:
"There was an error in downloading Lineage!"
});
return
;
}
a
.
href
=
DOMURL
.
createObjectURL
(
blob
);
if
(
blob
.
size
>
10000000
)
{
Utils
.
notifyWarn
({
content
:
"The Image size is huge, please open the image in a browser!"
});
}
a
.
click
();
that
.
toggleLoader
(
loaderTargetDiv
);
},
'image/png'
);
$
(
'.hidden-svg'
).
html
(
''
);
createCanvas
.
remove
();
}
catch
(
err
)
{
Utils
.
notifyError
({
content
:
"There was an error in downloading Lineage!"
});
that
.
toggleLoader
(
loaderTargetDiv
);
}
};
img
.
src
=
url
;
},
0
)
},
toggleLoader
:
function
(
element
)
{
if
((
element
).
hasClass
(
'fa-camera'
))
{
(
element
).
removeClass
(
'fa-camera'
).
addClass
(
"fa-spin-custom fa-refresh"
);
}
else
{
(
element
).
removeClass
(
"fa-spin-custom fa-refresh"
).
addClass
(
'fa-camera'
);
}
},
});
});
return
LineageLayoutView
;
return
LineageLayoutView
;
});
});
\ No newline at end of file
This diff is collapsed.
Click to expand it.
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