Commit 2735f96f by kevalbhatt Committed by Madhan Neethiraj

ATLAS-2487: UI updates to render entity relationships

parent 0120003a
......@@ -4,14 +4,15 @@
* Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE)
*/
/* Toggle Styles */
#wrapper {
padding-left: 0;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
#wrapper.toggled {
......@@ -27,14 +28,15 @@
margin-left: -350px;
overflow-y: auto;
background: #323544;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
-moz-transition: left 0.3s;
-o-transition: left 0.3s;
-webkit-transition: left 0.3s;
transition: left 0.3s;
}
#wrapper.toggled #sidebar-wrapper {
width: 350px;}
width: 350px;
}
#page-content-wrapper {
width: 100%;
......@@ -46,67 +48,76 @@
margin-right: -350px;
}
/* Sidebar Styles */
.sidebar-nav {
margin: 0;
padding: 0;
list-style: none;
}
.sidebar-nav > li {
.sidebar-nav>li {
line-height: 50px;
padding: 0 20px;
border-bottom: 1px #1c1e2a solid;
}
.sidebar-nav > li a {
.sidebar-nav>li a {
display: block;
text-decoration: none;
color: #fff;
}
.sidebar-nav > li a:hover {
.sidebar-nav>li a:hover {
text-decoration: none;
color: #fff;
}
.sidebar-nav > li a:active,
.sidebar-nav > li a:focus {
.sidebar-nav>li a:active,
.sidebar-nav>li a:focus {
text-decoration: none;
}
.sidebar-nav > .sidebar-brand {
.sidebar-nav>.sidebar-brand {
font-size: 18px;
line-height: 60px;
line-height: 50px;
}
.sidebar-nav > .sidebar-brand a {
.sidebar-nav>.sidebar-brand a {
color: #ddd;
letter-spacing: 1px;
}
.sidebar-nav > .sidebar-brand a:hover {
.sidebar-nav>.sidebar-brand a:hover {
color: #fff;
background: none;
}
/* Extended Elements */
.sidebar-input .input-group {
margin: 10px 0px;
}
.sidebar-input .form-control,
.sidebar-input .input-group-addon {
background-color: transparent;
border-radius: 0px;
}
.sidebar-input .form-control {
border-right: none;
color: #eee;
}
.sidebar-input .input-group-addon {
border-left: none;
color: #ccc;
}
.sidebar-input .form-control:focus + .input-group-addon {
.sidebar-input .form-control:focus+.input-group-addon {
border-color: #66afe9;
}
......@@ -120,7 +131,8 @@
}
#sidebar-wrapper {
width: 350px; }
width: 350px;
}
#wrapper.toggled #sidebar-wrapper {
width: 0;
......
......@@ -54,3 +54,22 @@
}
}
}
.details-backbutton {
display: none !important;
}
.full-screen {
#sidebar-wrapper {
left: 0;
}
#wrapper {
padding-left: 0px;
}
}
.detail-page {
.details-backbutton {
display: block !important;
}
}
\ No newline at end of file
......@@ -208,7 +208,7 @@ button:focus {
padding: 2px 6px;
}
&.btn-md {
padding: 5px 10px;
padding: 6px 10px;
}
}
......
......@@ -65,3 +65,7 @@
box-shadow: 0 2px $white;
}
}
.navbar-nav>li>a{
padding: 15px 10px;
}
\ No newline at end of file
......@@ -417,3 +417,6 @@ div.columnmanager-dropdown-container {
.text-center {
text-align: center !important;
}
.margin-15{
margin: 15px 0px;
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.relationship-box {
.relatioship-link {
fill: none;
stroke-width: 1.5px;
}
.relationship-details {
position: absolute;
left: 0;
overflow: auto;
top: 0px;
max-height: 100%;
box-shadow: 4px 13px 14px -12px;
background: #e7e7e7;
transform: scaleX(0);
width: 200px;
transition: transform 0.3s ease-in;
&.open {
transform: scaleX(1);
}
.title {
background: black;
color: white;
padding: 10px;
margin-top: 0;
}
.close-details {
position: absolute;
top: 0;
color: white;
left: 0;
height: 21px;
width: 21px;
cursor: pointer;
font-size: 16px;
}
.entity-list {
overflow: auto;
list-style-type: disc;
list-style-position: outside;
padding-left: 18px;
}
ul>li {
word-wrap: break-word;
margin-bottom: 5px;
text-align: left;
}
}
}
\ No newline at end of file
......@@ -25,6 +25,7 @@
@import "panel.scss";
@import "loader.scss";
@import "graph.scss";
@import "relationship.scss";
@import "old-style.scss";
@import "theme.scss";
@import "tag.scss";
......
......@@ -162,3 +162,18 @@ ul.tabs li.tab {
border-top: none;
}
}
.default-tab {
.nav-tabs {
>li {
&.active {
>a {
color: $color_jungle_green_approx;
}
}
>a {
color: $black;
}
}
}
}
\ No newline at end of file
......@@ -43,7 +43,7 @@ header {
>a {
display: inline-block;
color: $color_ironside_gray_approx;
padding: 16px 14px;
padding: 15px 14px;
&:hover {
border-bottom: 2px solid $color_jungle_green_approx;
padding: 14px 14px;
......@@ -53,7 +53,6 @@ header {
padding: 5px;
}
i {
margin-top: 7px;
font-size: 18px;
}
}
......@@ -95,7 +94,11 @@ header {
.page-title {
background-color: $white;
padding: 25px;
padding: 10px 15px;
.title {
padding-top: 0;
margin-top: 0;
}
h1 {
// margin-top: 50px;
margin-bottom: 10px;
......@@ -206,8 +209,7 @@ hr[size="10"] {
}
.gray-bg {
background-color: #f6f7fb;
padding-bottom: 4%;
background-color: $color_white_lilac_approx
}
......
......@@ -42,7 +42,7 @@
<div data-id="r_pagination" class="inline"></div>
{{#if includePageSize}}
<div class="inline">
<div class="form-group inline-content">
<div class="inline-content">
<span class="control-label-sm inline ">Page Limit :</span>
<div class="select inline" style="width: 80px;">
<select data-id="pageSize" class="form-control"></select>
......
......@@ -19,10 +19,7 @@
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<div class="entityDetail form-horizontal col-sm-12">
<div class="row">
<a href="javascript:void(0);" data-id="backButton"><i class="fa fa-chevron-left"></i> Back To Results</a>
</div>
<h1 class="form-group"><span data-id="title"></span></h1> {{#if entityUpdate}}
<h1 class="title row"><span data-id="title"></span></h1> {{#if entityUpdate}}
<div data-id="editButtonContainer" class="pull-right"></div>
{{/if}}
<div class="form-group">
......@@ -39,84 +36,69 @@
</div>
</div>
</div>
</div>
<div class="container-fluid gray-bg">
<div class="row">
<div class="col-sm-custom">
<div class="">
<!-- <h4 class="lineageLabel"></h4> -->
<div class="lineageLayout">
<div class="panel panel-default" id="panel">
<div class="panel-heading clearfix">
<h4 class="panel-title pull-left"> LINEAGE & IMPACT</h4>
<div class="btn-group pull-right">
<button type="button" class="fullscreen_panel" id="fullscreen_panel" title="Fullscreen"><i class="fa fa-expand" aria-hidden="true"></i></button>
<button type="button" id="expand_collapse_panel" class="expand_collapse_panel" title="Collapse"><i class="fa fa-chevron-up" aria-hidden="true"></i></button>
</div>
</div>
<div id="panel_body" class="panel-body graph-bg resize-graph animated" align="center" style="height:375px;">
<div id="r_lineageLayoutView">
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
</div>
<div class="col-sm-12 default-tab">
<ul class="nav nav-tabs" data-id="tab-list">
<li role="properties" class="tab active"><a href="#tab-details" aria-controls="tab-details" role="tab" data-toggle="tab">Properties</a></li>
<li role="lineage" class="tab"><a href="#tab-lineage" aria-controls="tab-lineage" role="tab" data-toggle="tab">Lineage</a></li>
<li role="relationship" class="tab"><a href="#tab-relationship" aria-controls="tab-relationship" role="tab" data-toggle="tab">Relationships</a></li>
<li role="classification"><a href="#tab-tagTable" aria-controls="tab-tagTable" role="tab" data-toggle="tab">Classifications</a></li>
<li role="audit" class="tab"><a href="#tab-audit" aria-controls="tab-audit" role="tab" data-toggle="tab">Audits</a></li>
<li role="schema" class="tab schemaTable" style="display:none"><a href="#tab-schema" aria-controls="tab-schema" role="tab" data-toggle="tab">Schema</a></li>
<li role="profile" class="tab profileTab" style="display:none"><a href="#tab-profile" aria-controls="tab-profile" role="tab" data-toggle="tab">Profile</a></li>
</ul>
</div>
</div>
</div>
<div class="gray-bg">
<div class="tab-content">
<div id="tab-details" role="properties" class="tab-pane active animated fadeIn">
<div id="r_entityDetailTableLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-custom">
<div class="panel with-nav-tabs panel-default">
<div class="panel-heading clearfix">
<h4 class="panel-title pull-left">DETAILS</h4>
<div class="btn-group pull-right">
<button type="button" class="expand_collapse_panel" title="Collapse"><i class="fa fa-chevron-up" aria-hidden="true"></i></button>
<div id="tab-lineage" role="lineage" class="tab-pane animated fadeIn">
<div class="resize-graph animated" align="center" style="height:64vh;">
<div id="r_lineageLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-12">
<ul class="nav nav-tabs ">
<li role="properties" class="tab active"><a href="#tab-details" aria-controls="tab-details" role="tab" data-toggle="tab">Properties</a></li>
<li role="tags"><a href="#tab-tagTable" aria-controls="tab-tagTable" role="tab" data-toggle="tab">Classifications</a></li>
<li role="audits" class="tab"><a href="#tab-audit" aria-controls="tab-audit" role="tab" data-toggle="tab">Audits</a></li>
<li role="schema" class="tab schemaTable" style="display:none"><a href="#tab-schema" aria-controls="tab-schema" role="tab" data-toggle="tab">Schema</a></li>
<li role="profile" class="tab profileTab" style="display:none"><a href="#tab-profile" aria-controls="tab-profile" role="tab" data-toggle="tab">Profile</a></li>
</ul>
</div>
</div>
<div class="tab-content">
<div id="tab-details" role="properties" class="tab-pane active">
<div id="r_entityDetailTableLayoutView">
<div id="tab-relationship" role="relationship" class="tab-pane animated fadeIn">
<div class="resize-graph animated" align="center" style="height:64vh;">
<div id="r_relationshipLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
</div>
<div id="tab-tagTable" role="tags" class="tab-pane fade">
</div>
<div id="tab-tagTable" role="classification" class="tab-pane animated fadeIn">
<div id="r_tagTableLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
</div>
<div id="tab-audit" role="audits" class="tab-pane">
<div id="tab-audit" role="audit" class="tab-pane animated fadeIn">
<div id="r_auditTableLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
</div>
<div id="tab-schema" role="schema" class="tab-pane">
<div id="tab-schema" role="schema" class="tab-pane animated fadeIn">
<div id="r_schemaTableLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
</div>
<div id="tab-profile" role="profile" class="tab-pane">
<div id="tab-profile" role="profile" class="tab-pane animated fadeIn">
<div id="r_profileLayoutView">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
......@@ -124,9 +106,5 @@
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
......@@ -14,11 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<div style="position: absolute;height: calc(100% - 45px);width: calc(100% - 30px);">
<!-- <div class="graph-toolbar clearfix"></div> -->
<div style="position: absolute;height:100%;width:100%;" class="white-bg no-padding">
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<svg width="100%" height="100%" " viewBox="0 0 854 330" enable-background="new 0 0 854 330" xml:space="preserve"></svg>
<svg width="100%" height="calc(100% - 30px)" viewBox="0 0 854 330" enable-background="new 0 0 854 330" xml:space="preserve"></svg>
<div class="legends" style="height: 20px">
<i class="fa fa-long-arrow-right" aria-hidden="true" style="margin-right: 12px; color:#8bc152;">&nbsp<span>Lineage</span></i>
<i class="fa fa-long-arrow-right" aria-hidden="true" style="color:#fb4200;">&nbsp<span>Impact</span></i>
......
<!--
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<!-- <div class="graph-toolbar clearfix"></div> -->
<div style="position: absolute;height:100%;width:100%;" class="white-bg no-padding relationship-box">
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<div style="position: absolute;height:100%;width:100%;">
<svg width="100%" height="100%" viewBox="0 0 854 330" enable-background="new 0 0 854 330" xml:space="preserve"></svg>
</div>
<div class="relationship-details">
<div data-id="close" class="close-details"><i class="fa fa-times"></i></div>
<h4 class="title"><span data-id="typeName"></span></h4>
<div class="col-md-12">
<input data-id="searchNode" class="form-control form-group" placeholder="Search Entities" />
<ul data-id="entityList" class="entity-list"></ul>
</div>
</div>
</div>
\ No newline at end of file
......@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<div>
<div class="position-relative">
<div class="tableOverlay"></div>
<div class="inline-content-fr table-action-btn">
<div class="inline" data-id="checkDeletedEntity">
......
......@@ -23,12 +23,12 @@
<div class="ellipsis" style="display: none;"><span class="searchResult" style=" font-size: 16px;"></span>
</div>
<div class="searchTable">
<div class="row well">
<div class="row well" style="padding-top: 0px;">
<div class="row form-group pagination-box filter-box" style="display: none;">
<div class="col-sm-3">
<div class="col-sm-4">
<span class="labelShowRecord pull-left" data-id="pageRecordText"> </span>
</div>
<div class="col-sm-9 inline-content-fr no-padding-left">
<div class="col-sm-8 inline-content-fr no-padding-left">
<div class="inline" data-id="colManager"></div>
<div class="inline" data-id="containerCheckBox" style="display: none;">
<label class="checkbox-inline btn" for="inputLabel">
......@@ -84,12 +84,12 @@
<div class="input-group" data-id="goToPageDiv">
<input type="text" class="form-control number-input" data-id="gotoPage" placeholder="Goto Page" />
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" data-id="gotoPagebtn" title="Goto Page" disabled="disabled">Go!</button>
<button class="btn btn-atlas btn-md no-margin" type="button" data-id="gotoPagebtn" title="Goto Page" disabled="disabled">Go!</button>
</span>
</div>
</div>
<div class="inline">
<div class="form-group inline-content">
<div class="inline-content">
<span class="control-label-sm inline ">Page Limit :</span>
<div class="inline" style="width: 80px;">
<select data-id="showPage" multiple="multiple" class="form-control">
......
......@@ -15,6 +15,12 @@
* limitations under the License.
-->
<header class="clearfix">
<ul class="nav navbar-nav">
<li>
<a href="javascript:void(0);" data-id="menuHamburger"><i class="fa fa-bars"></i></a>
</li>
<li class="details-backbutton"><a href="javascript:void(0);" data-id="backButton"><i class="fa fa-chevron-left"></i> Back To Results</a></li>
</ul>
<div class="btn-group pull-right header-menu ">
<a target="_blank" href="http://atlas.apache.org/"><i class="fa fa-question-circle"></i></a>
<a href="javascript:void(0);" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="user-dropdown"><i class="fa fa-user user-circle "></i><span class="userName"></span></a>
......
......@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<div>
<div class="position-relative">
<div class="tableOverlay"></div>
<div class="inline-content-fr table-action-btn">
<div class="inline" >
......
......@@ -100,5 +100,10 @@ define(['require'], function(require) {
}
}
}
Enums.graphIcon = {
// hive_db: { icon: "fa-database", textContent: '\uf1c0' },
// hive_column: { icon: "fa-columns", textContent: '\uf0db' },
// hive_table: { icon: "fa-table", textContent: '\uf0ce' }
}
return Enums;
});
\ No newline at end of file
......@@ -44,8 +44,8 @@ define(['require',
RTagTableLayoutView: "#r_tagTableLayoutView",
RLineageLayoutView: "#r_lineageLayoutView",
RAuditTableLayoutView: "#r_auditTableLayoutView",
RProfileLayoutView: "#r_profileLayoutView"
RProfileLayoutView: "#r_profileLayoutView",
RRelationshipLayoutView: "#r_relationshipLayoutView"
},
/** ui selector cache */
ui: {
......@@ -57,11 +57,11 @@ define(['require',
description: '[data-id="description"]',
editBox: '[data-id="editBox"]',
deleteTag: '[data-id="deleteTag"]',
backButton: "[data-id='backButton']",
addTag: '[data-id="addTag"]',
tagList: '[data-id="tagList"]',
propagatedTagList: '[data-id="propagatedTagList"]',
fullscreenPanel: "#fullscreen_panel"
fullscreenPanel: "#fullscreen_panel",
tablist: '[data-id="tab-list"] li'
},
templateHelpers: function() {
return {
......@@ -83,8 +83,16 @@ define(['require',
};
events["click " + this.ui.deleteTag] = 'onClickTagCross';
events["click " + this.ui.addTag] = 'onClickAddTagBtn';
events['click ' + this.ui.backButton] = function() {
Backbone.history.history.back();
events["click " + this.ui.tablist] = function(e) {
var tabValue = $(e.currentTarget).attr('role');
Utils.setUrl({
url: Utils.getUrlState.getQueryUrl().queyParams[0],
urlParams: { tabActive: tabValue || 'properties' },
mergeBrowserUrl: false,
trigger: false,
updateTabState: true
});
};
return events;
},
......@@ -95,6 +103,7 @@ define(['require',
initialize: function(options) {
_.extend(this, _.pick(options, 'value', 'collection', 'id', 'entityDefCollection', 'typeHeaders', 'enumDefCollection', 'classificationDefCollection'));
this.bindEvents();
$('body').addClass("detail-page");
},
bindEvents: function() {
var that = this;
......@@ -176,6 +185,7 @@ define(['require',
})()
}
this.renderEntityDetailTableLayoutView(obj);
this.renderRelationshipLayoutView(obj);
this.renderAuditTableLayoutView(obj);
this.renderTagTableLayoutView(obj);
if (collectionJSON && (!_.isUndefined(collectionJSON.attributes['profileData']) || collectionJSON.typeName === "hive_db" || collectionJSON.typeName === "hbase_namespace")) {
......@@ -201,7 +211,7 @@ define(['require',
}
}, this);
this.listenTo(this.collection, 'error', function(model, response) {
this.$('.fontLoader').hide();
this.$('.fontLoader-relative').removeClass('show');
if (response.responseJSON) {
Utils.notifyError({
content: response.responseJSON.errorMessage || response.responseJSON.error
......@@ -212,7 +222,7 @@ define(['require',
onRender: function() {
var that = this;
Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.$('.entityDetail'));
this.$('.fontLoader').show(); // to show tab loader
this.$('.fontLoader-relative').addClass('show'); // to show tab loader
this.renderLineageLayoutView({
guid: this.id,
entityDefCollection: this.entityDefCollection,
......@@ -253,12 +263,17 @@ define(['require',
},
onShow: function() {
var params = Utils.getUrlState.getQueryParams();
if (params && params.profile) {
this.$('.nav.nav-tabs').find('.profileTab').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('#tab-profile').addClass('active').siblings().removeClass('active');
if (params && params.tabActive) {
this.$('.nav.nav-tabs').find('[role="' + params.tabActive + '"]').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('[role="' + params.tabActive + '"]').addClass('active').siblings().removeClass('active');
$("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000);
}
},
onDestroy: function() {
if (!Utils.getUrlState.isDetailPage()) {
$('body').removeClass("detail-page");
}
},
fetchCollection: function() {
this.collection.fetch({ reset: true });
},
......@@ -375,6 +390,12 @@ define(['require',
that.RLineageLayoutView.show(new LineageLayoutView(obj));
});
},
renderRelationshipLayoutView: function(obj) {
var that = this;
require(['views/graph/RelationshipLayoutView'], function(RelationshipLayoutView) {
that.RRelationshipLayoutView.show(new RelationshipLayoutView(obj));
});
},
renderSchemaLayoutView: function(obj) {
var that = this;
require(['views/schema/SchemaLayoutView'], function(SchemaLayoutView) {
......
......@@ -201,7 +201,9 @@ define(['require',
);
},
createGraph: function() {
var that = this;
var that = this,
width = this.$('svg').width(),
height = this.$('svg').height();
this.g.nodes().forEach(function(v) {
var node = that.g.node(v);
// Round the corners of the nodes
......@@ -283,7 +285,9 @@ define(['require',
return shapeSvg;
};
// Set up an SVG group so that we can translate the final graph.
var svg = this.svg = d3.select(this.$("svg")[0]),
var svg = this.svg = d3.select(this.$("svg")[0])
.attr("viewBox", "0 0 " + width + " " + height)
.attr("enable-background", "new 0 0 " + width + " " + height),
svgGroup = svg.append("g");
var zoom = this.zoom = d3.behavior.zoom()
.scaleExtent([0.5, 6])
......@@ -392,7 +396,7 @@ define(['require',
.on('dblclick', function(d) {
tooltip.hide(d);
Utils.setUrl({
url: '#!/detailPage/' + d,
url: '#!/detailPage/' + d + '?tabActive=lineage',
mergeBrowserUrl: false,
trigger: true
});
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
define(['require',
'backbone',
'hbs!tmpl/graph/RelationshipLayoutView_tmpl',
'collection/VLineageList',
'models/VEntity',
'utils/Utils',
'd3-tip',
'utils/Enums',
'utils/UrlLinks',
'platform'
], function(require, Backbone, RelationshipLayoutViewtmpl, VLineageList, VEntity, Utils, d3Tip, Enums, UrlLinks, platform) {
'use strict';
var RelationshipLayoutView = Backbone.Marionette.LayoutView.extend(
/** @lends RelationshipLayoutView */
{
_viewName: 'RelationshipLayoutView',
template: RelationshipLayoutViewtmpl,
/** Layout sub regions */
regions: {},
/** ui selector cache */
ui: {
relationshipDetailClose: '[data-id="close"]',
searchNode: '[data-id="searchNode"]'
},
/** ui events hash */
events: function() {
var events = {};
events["click " + this.ui.relationshipDetailClose] = function() {
this.toggleInformationSlider({ close: true });
};
events["keyup " + this.ui.searchNode] = 'searchNode';
return events;
},
/**
* intialize a new RelationshipLayoutView Layout
* @constructs
*/
initialize: function(options) {
_.extend(this, _.pick(options, 'entity', 'entityName', 'guid', 'actionCallBack'));
this.graphData = this.createData(this.entity);
},
createData: function(entity) {
var that = this,
links = [],
nodes = {};
if (entity && entity.relationshipAttributes) {
_.each(entity.relationshipAttributes, function(obj, key) {
if (!_.isEmpty(obj)) {
links.push({
"source": nodes[that.entity.typeName] ||
(nodes[that.entity.typeName] = _.extend({ "name": that.entity.typeName }, { value: entity })),
"target": nodes[key] ||
(nodes[key] = _.extend({
"name": key
}, { value: obj })),
"value": obj
})
}
});
}
return { nodes: nodes, links: links };
},
onRender: function() {
},
onShow: function(argument) {
if (this.graphData && _.isEmpty(this.graphData.links)) {
this.noRelationship();
} else {
this.createGraph(this.graphData);
}
},
noRelationship: function() {
this.$('svg').html('<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">No relationship data found</text>');
},
toggleInformationSlider: function(options) {
if (options.open && !this.$('.relationship-details').hasClass("open")) {
this.$('.relationship-details').addClass('open');
} else if (options.close && this.$('.relationship-details').hasClass("open")) {
d3.selectAll('circle').attr("stroke", "none");
this.$('.relationship-details').removeClass('open');
}
},
searchNode: function(e) {
var $el = $(e.currentTarget);
this.updateRelationshipDetails(_.extend({}, $el.data(), { searchString: $el.val() }))
},
updateRelationshipDetails: function(options) {
var data = options.obj.value,
typeName = data.typeName || options.obj.name,
searchString = options.searchString,
listString = "";
this.$("[data-id='typeName']").text(typeName);
var getElement = function(options) {
var name = options.entityName ? options.entityName : Utils.getName(options, "displayText");
return "<li><a href=#!/detailPage/" + options.guid + "?tabActive=relationship>" + _.escape(name) + " (" + options.typeName + ")</a></li>";
}
if (_.isArray(data)) {
_.each(_.sortBy(data, "displayText"), function(val) {
var name = Utils.getName(val, "displayText"),
valObj = _.extend({}, val, { entityName: name });
if (searchString) {
if (name.search(new RegExp(searchString, "i")) != -1) {
listString += getElement(valObj);
} else {
return;
}
} else {
listString += getElement(valObj);
}
});
} else {
listString += getElement(data);
}
this.$("[data-id='entityList']").html(listString);
},
createGraph: function(data) {
var that = this,
width = this.$('svg').width(),
height = this.$('svg').height();
var scale = 1.0,
activeEntityColor = "#00b98b";
var force = d3.layout.force()
.nodes(d3.values(data.nodes))
.links(data.links)
.size([width, height])
.linkDistance(200)
.charge(function(d) {
var charge = -500;
if (d.index === 0) charge = 100
return charge;
})
.on("tick", tick)
.start();
var zoom = d3.behavior.zoom()
.scale(scale)
.scaleExtent([1, 5])
.on("zoom", zoomed);
function zoomed() {
var translateX = d3.event.translate[0];
var translateY = d3.event.translate[1];
var xScale = d3.event.scale;
container.attr("transform", "translate(" + translateX + "," + translateY + ")scale(" + xScale + ")");
}
var svg = d3.select(this.$("svg")[0])
.attr("viewBox", "0 0 " + width + " " + height)
.attr("enable-background", "new 0 0 " + width + " " + height)
.call(zoom)
.on("dblclick.zoom", null),
drag = force.drag()
.on("dragstart", dragstart);
var container = svg.append("g")
.attr("id", "container")
.attr("transform", "translate(0,0)scale(1,1)");
// build the arrow.
container.append("svg:defs").selectAll("marker")
.data(["output"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 10)
.attr("refY", -0.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5")
.attr("fill", activeEntityColor);
// add the links and the arrows
var path = container.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
// .attr("class", function(d) { return "link " + d.type; })
.attr("class", "relatioship-link")
.attr("stroke", activeEntityColor)
.attr("marker-end", "url(#output)");
// define the nodes
var node = container.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.on('click', function(d) {
if (d3.event.defaultPrevented) return; // ignore drag
that.toggleInformationSlider({ open: true, obj: d });
that.ui.searchNode.data({ obj: d });
d3.selectAll('circle').attr("stroke", "none");
d3.select('circle[typename="' + d.name + '"]').attr("stroke", function(d) {
if (d && d.value && d.value.guid == that.guid) {
return "#316132";
} else {
return activeEntityColor;
}
});
that.updateRelationshipDetails({ obj: d });
}).call(force.drag);
// add the nodes
var circleContainer = node.append("g");
circleContainer.on("dblclick", function(d) {
if ((_.isArray(d.value) && d.value.length == 1) || d.value.guid) {
var guid = _.isArray(d.value) ? _.first(d.value).guid : d.value.guid;
Utils.setUrl({
url: '#!/detailPage/' + guid,
mergeBrowserUrl: false,
urlParams: { tabActive: 'relationship' },
trigger: true
});
}
})
circleContainer.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", function(d) {
d.radius = 25;
return d.radius;
})
.attr("fill", function(d) {
if (d && d.value && d.value.guid == that.guid) {
return activeEntityColor;
} else {
return "#e0e0e0";
}
})
.attr("typename", function(d) {
return d.name;
})
circleContainer.append("text")
.attr('x', 0)
.attr('y', 0)
.attr('dy', (25 - 17))
.attr("text-anchor", "middle")
.style("font-family", "FontAwesome")
.style('font-size', function(d) { return '25px'; })
.text(function(d) {
var iconObj = Enums.graphIcon[d.name];
if (iconObj && iconObj.textContent) {
return iconObj.textContent;
} else {
if (d && _.isArray(d.value) && d.value.length > 1) {
return '\uf0c5';
} else {
return '\uf016';
}
}
})
.attr("fill", function(d) {
if (d && d.value && d.value.guid == that.guid) {
return "#fff";
} else {
return "#000";
}
});
var countBox = circleContainer.append('g')
countBox.append("circle")
.attr("cx", 18)
.attr("cy", -20)
.attr("r", function(d) {
if (_.isArray(d.value) && d.value.length > 1) {
return 10;
}
});
countBox.append("text")
.attr('dx', 18)
.attr('dy', -16)
.attr("text-anchor", "middle")
.attr("fill", "#e0e0e0")
.text(function(d) {
if (_.isArray(d.value)) {
return d.value.length;
}
});
// add the text
node.append("text")
.attr("x", -15)
.attr("y", "35")
.text(function(d) { return d.name; });
// add the curvy lines
function tick() {
path.attr("d", function(d) {
var diffX = d.target.x - d.source.x,
diffY = d.target.y - d.source.y,
// Length of path from center of source node to center of target node
pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY)),
// x and y distances from center to outside edge of target node
offsetX = (diffX * d.target.radius) / pathLength,
offsetY = (diffY * d.target.radius) / pathLength;
return "M" + d.source.x + "," + d.source.y + "A" + pathLength + "," + pathLength + " 0 0,1 " + (d.target.x - offsetX) + "," + (d.target.y - offsetY)
});
node.attr("transform", function(d) {
// if (d && d.value && d.value.guid == that.guid) {
// Center fixed node
// var damper = 0.1;
// d.x = (width / 2)
// d.y = (height / 2)
// }
return "translate(" + d.x + "," + d.y + ")";
});
}
function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
}
});
return RelationshipLayoutView;
});
\ No newline at end of file
......@@ -154,7 +154,7 @@ define(['require',
mergeBrowserUrl: false,
trigger: true,
urlParams: {
'profile': true
tabActive: 'profile'
}
});
});
......
......@@ -19,15 +19,37 @@
define(['require',
'hbs!tmpl/site/Header',
'utils/CommonViewFunction',
'utils/Globals'
], function(require, tmpl, CommonViewFunction, Globals) {
'utils/Globals',
'utils/Utils'
], function(require, tmpl, CommonViewFunction, Globals, Utils) {
'use strict';
var Header = Marionette.LayoutView.extend({
template: tmpl,
regions: {},
events: {},
ui: {
backButton: "[data-id='backButton']",
menuHamburger: "[data-id='menuHamburger']",
},
events: function() {
var events = {};
events['click ' + this.ui.backButton] = function() {
Utils.setUrl({
url: Globals.saveApplicationState.tabState.searchUrl,
mergeBrowserUrl: false,
trigger: true,
updateTabState: true
});
};
events['click ' + this.ui.menuHamburger] = function() {
$('body').toggleClass("full-screen");
};
return events;
},
initialize: function(options) {},
onRender: function() {
var that = this;
if (Globals.userLogedIn.status) {
......
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