Commit 079ce35e by Shwetha GS

ATLAS-1004 Option to enable taxonomy feature (kevalbhatt18 via shwethags)

parent 80051c9e
......@@ -45,17 +45,6 @@
}
}
.loader {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
text-align: center;
z-index: 9;
background: $white_80 $url_0 no-repeat center center;
}
.fontLoader {
top: 50%;
left: 50%;
......
......@@ -132,3 +132,6 @@
color: $color_jungle_green_approx;
}
}
.position-relative{
position:relative;
}
\ No newline at end of file
......@@ -155,8 +155,10 @@ require(['App',
Globals.userLogedIn.status = true;
Globals.userLogedIn.response = response;
}
if (response && response['atlas.feature.taxonomy.enable'] !== undefined) {
Globals.taxonomy = response['atlas.feature.taxonomy.enable']
}
App.start();
}
});
});
......@@ -104,22 +104,26 @@ define([
'views/business_catalog/SideNavLayoutView',
'collection/VCatalogList'
], function(BusinessCatalogHeader, BusinessCatalogDetailLayoutView, SideNavLayoutView, VCatalogList) {
var paramObj = Utils.getUrlState.getQueryParams();
this.collection = new VCatalogList();
this.collection.url = url;
App.rNHeader.show(new BusinessCatalogHeader({ 'globalVent': that.globalVent, 'url': url, 'collection': this.collection }));
if (!App.rSideNav.currentView) {
App.rSideNav.show(new SideNavLayoutView({ 'globalVent': that.globalVent, 'url': url }));
if (Globals.taxonomy) {
var paramObj = Utils.getUrlState.getQueryParams();
this.collection = new VCatalogList();
this.collection.url = url;
App.rNHeader.show(new BusinessCatalogHeader({ 'globalVent': that.globalVent, 'url': url, 'collection': this.collection }));
if (!App.rSideNav.currentView) {
App.rSideNav.show(new SideNavLayoutView({ 'globalVent': that.globalVent, 'url': url }));
} else {
App.rSideNav.currentView.RBusinessCatalogLayoutView.currentView.manualRender("/" + url);
App.rSideNav.currentView.selectTab();
}
App.rNContent.show(new BusinessCatalogDetailLayoutView({
'globalVent': that.globalVent,
'url': url,
'collection': this.collection
}));
this.collection.fetch({ reset: true });
} else {
App.rSideNav.currentView.RBusinessCatalogLayoutView.currentView.manualRender("/" + url);
App.rSideNav.currentView.selectTab();
that.defaultAction()
}
App.rNContent.show(new BusinessCatalogDetailLayoutView({
'globalVent': that.globalVent,
'url': url,
'collection': this.collection
}));
this.collection.fetch({ reset: true });
});
},
detailPage: function(id) {
......@@ -228,14 +232,26 @@ define([
},
defaultAction: function(actions) {
// We have no matching route, lets just log what the URL was
Utils.setUrl({
url: '#!/taxonomy',
mergeBrowserUrl: false,
updateTabState: function() {
return { taxonomyUrl: this.url, stateChanged: false };
},
trigger: true
});
if (Globals.taxonomy) {
Utils.setUrl({
url: '#!/taxonomy',
mergeBrowserUrl: false,
updateTabState: function() {
return { taxonomyUrl: this.url, stateChanged: false };
},
trigger: true
});
} else {
Utils.setUrl({
url: '#!/tag',
mergeBrowserUrl: false,
updateTabState: function() {
return { tagUrl: this.url, stateChanged: false };
},
trigger: true
});
}
console.log('No route:', actions);
}
});
......
......@@ -19,16 +19,18 @@
<a href="index.html"><i class="fa fa-globe"></i> Apache Atlas</a>
</li>
<ul class="tabs" style="width: 100%;" role="tablist">
<li role="presentation" class="tab col-sm-4"><a href="#tab-tag" aria-controls="tab-tag" data-name="tab-tag" role="tab" data-toggle="tab">Tags</a></li>
<li role="presentation" class="tab col-sm-4 active"><a href="#tab-taxonomy" aria-controls="tab-taxonomy" data-name="tab-taxonomy" role="tab" data-toggle="tab" class="">Taxonomy</a></li>
<li role="presentation" class="tab col-sm-4"><a href="#tab-search" aria-controls="tab-search" data-name="tab-search" role="tab" data-toggle="tab" class=""><i class="fa fa-search"></i> Search</a></li>
<li role="presentation" class="{{tabClass}}"><a href="#tab-tag" aria-controls="tab-tag" data-name="tab-tag" role="tab" data-toggle="tab">Tags</a></li>
{{#if taxonomy}}
<li role="presentation" class="tab col-sm-4"><a href="#tab-taxonomy" aria-controls="tab-taxonomy" data-name="tab-taxonomy" role="tab" data-toggle="tab" class="">Taxonomy</a></li>
{{/if}}
<li role="presentation" class="{{tabClass}}"><a href="#tab-search" aria-controls="tab-search" data-name="tab-search" role="tab" data-toggle="tab" class=""><i class="fa fa-search"></i> Search</a></li>
</ul>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane" id="tab-tag">
<div id="r_tagLayoutView"></div>
</div>
<div role="tabpanel" class="tab-pane active" id="tab-taxonomy">
<div role="tabpanel" class="tab-pane" id="tab-taxonomy">
<div id="r_businessCatalogLayoutView"></div>
</div>
<div role="tabpanel" class="tab-pane" id="tab-search">
......
......@@ -29,7 +29,9 @@
</div>
<div class="position-relative thick-border">
<div data-id="r_tableList" class="table-responsive tableBorder"> </div>
<div data-id="r_tableSpinner"></div>
<div data-id="r_tableSpinner" class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
</div>
<div class="row banded">
<div data-id="r_footerRecords" class="col-sm-6 margin-top-10"></div>
......
......@@ -33,13 +33,14 @@
<div class="addTagBase tagBox" data-id="addTagPlus"><i class="fa fa-plus"></i></div>
</div>
</div>
<hr class="termTagLine">
<hr class="termTagLine"> {{#if taxonomy}}
<span class="termSpan">Terms:</span>
<div class="" data-id="termList">
<div class="addTag-dropdown" data-id="addTerm">
<div class="addTagBase termBox" data-id="addTermPlus"><i class="fa fa-plus"></i></div>
</div>
</div>
{{/if}}
</div>
</div>
<div class="container-fluid gray-bg">
......@@ -61,7 +62,9 @@
<li role="presentation" class="tab active"><a href="#tab-details" aria-controls="tab-details" role="tab" data-toggle="tab">Properties</a></li>
<!-- <li role="presentation"><a href="#profile" aria-controls="profile" role="tab" data-toggle="tab">Acceptable Use</a></li> -->
<li role="presentation"><a href="#tab-tagTable" aria-controls="tab-tagTable" role="tab" data-toggle="tab">Tags</a></li>
{{#if taxonomy}}
<li role="presentation"><a href="#tab-termTable" aria-controls="tab-termTable" role="tab" data-toggle="tab">Terms</a></li>
{{/if}}
<li role="presentation" class="tab"><a href="#tab-audit" aria-controls="tab-audit" role="tab" data-toggle="tab">Audits</a></li>
<li role="presentation" class="tab schemaTable" style="display:none"><a href="#tab-schema" aria-controls="tab-schema" role="tab" data-toggle="tab">Schema</a></li>
</ul>
......
......@@ -17,13 +17,13 @@
<!-- <div class="panel-heading">
<h3 class="panel-title">Lineage</h3>
</div> -->
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<div class="panel-body graph-bg" align="center">
<div class="graph" id="tree-container">
</div>
<div style="position:relative">
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<svg width=100% height=350></svg>
<div class="zoomButtonGroup">
<button class="zoomButton" id="zoom_in">+</button>
......
......@@ -14,8 +14,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<a href="javascript:void(0)" class="inputAssignTag multiSelect" style="display:none" data-id="addTerm"><i class="fa fa-folder-o"> Assign Term</i></a>
<div id="r_tagLayoutView"></div>
......@@ -16,7 +16,7 @@
* limitations under the License.
*/
/**
/**
* @file This is the common View file for displaying Table/Grid to be used overall in the application.
*/
define(['require',
......@@ -154,10 +154,10 @@ define(['require',
/** all events binding here */
bindEvents: function() {
this.listenTo(this.collection, 'request', function() {
this.$('div[data-id="r_tableSpinner"]').addClass('loading');
this.$('div[data-id="r_tableSpinner"]').addClass('show');
}, this);
this.listenTo(this.collection, 'sync error', function() {
this.$('div[data-id="r_tableSpinner"]').removeClass('loading');
this.$('div[data-id="r_tableSpinner"]').removeClass('show');
}, this);
this.listenTo(this.collection, 'reset', function(collection, response) {
......
......@@ -196,6 +196,9 @@ define(['require', 'utils/Globals'], function(require, Globals) {
isSearchTab: function() {
return this.getQueryUrl().firstValue == "search" ? true : false;
},
isDetailPage: function() {
return this.getQueryUrl().firstValue == "detailPage" ? true : false;
},
getLastValue: function() {
return this.getQueryUrl().lastValue;
},
......
......@@ -34,6 +34,12 @@ define(['require',
ui: {
tabs: '.tabs li a',
},
templateHelpers: function() {
return {
taxonomy: Globals.taxonomy,
tabClass: this.tabClass
};
},
events: function() {
var events = {},
that = this;
......@@ -61,12 +67,19 @@ define(['require',
},
initialize: function(options) {
_.extend(this, _.pick(options, 'globalVent', 'url', 'value', 'tag', 'selectFirst'));
if (Globals.taxonomy) {
this.tabClass = "tab col-sm-4";
} else {
this.tabClass = "tab col-sm-6";
}
},
onRender: function() {
this.bindEvent();
this.renderTagLayoutView();
this.renderSearchLayoutView();
this.rendeBusinessCatalogLayoutView();
if (Globals.taxonomy) {
this.rendeBusinessCatalogLayoutView();
}
this.selectTab();
},
......@@ -101,13 +114,13 @@ define(['require',
});
},
selectTab: function() {
if (Utils.getUrlState.isTagTab()) {
if (Utils.getUrlState.isTagTab() || (Utils.getUrlState.isInitial() && !Globals.taxonomy)) {
this.$('.tabs').find('li a[aria-controls="tab-tag"]').parents('li').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('div#tab-tag').addClass('active').siblings().removeClass('active');
} else if (Utils.getUrlState.isTaxonomyTab()) {
} else if (Utils.getUrlState.isTaxonomyTab() || (Utils.getUrlState.isInitial() && Globals.taxonomy)) {
this.$('.tabs').find('li a[aria-controls="tab-taxonomy"]').parents('li').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('div#tab-taxonomy').addClass('active').siblings().removeClass('active');
} else if (Utils.getUrlState.isSearchTab()) {
} else if (Utils.getUrlState.isSearchTab() || (Utils.getUrlState.isDetailPage())) {
this.$('.tabs').find('li a[aria-controls="tab-search"]').parents('li').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('div#tab-search').addClass('active').siblings().removeClass('active');
}
......
......@@ -65,6 +65,11 @@ define(['require',
tagList: '[data-id="tagList"]',
termList: '[data-id="termList"]'
},
templateHelpers: function() {
return {
taxonomy: Globals.taxonomy
};
},
/** ui events hash */
events: function() {
var events = {};
......
......@@ -22,8 +22,9 @@ define(['require',
'collection/VSchemaList',
'utils/Utils',
'utils/CommonViewFunction',
'utils/Messages'
], function(require, Backbone, SchemaTableLayoutViewTmpl, VSchemaList, Utils, CommonViewFunction, Messages) {
'utils/Messages',
'utils/Globals'
], function(require, Backbone, SchemaTableLayoutViewTmpl, VSchemaList, Utils, CommonViewFunction, Messages, Globals) {
'use strict';
var SchemaTableLayoutView = Backbone.Marionette.LayoutView.extend(
......@@ -225,13 +226,15 @@ define(['require',
})
};
});
col['Check'] = {
name: "selected",
label: "",
cell: "select-row",
headerCell: "select-all",
position: 1
};
if (Globals.taxonomy) {
col['Check'] = {
name: "selected",
label: "",
cell: "select-row",
headerCell: "select-all",
position: 1
};
}
col['tag'] = {
label: "Tags",
cell: "Html",
......@@ -244,23 +247,25 @@ define(['require',
}
})
};
col['terms'] = {
label: "Terms",
cell: "Html",
editable: false,
sortable: false,
orderable: true,
className: 'searchTerm',
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
var returnObject = CommonViewFunction.termTableBreadcrumbMaker(model, "schema");
if (returnObject.object) {
that.bradCrumbList.push(returnObject.object);
if (Globals.taxonomy) {
col['terms'] = {
label: "Terms",
cell: "Html",
editable: false,
sortable: false,
orderable: true,
className: 'searchTerm',
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
var returnObject = CommonViewFunction.termTableBreadcrumbMaker(model, "schema");
if (returnObject.object) {
that.bradCrumbList.push(returnObject.object);
}
return returnObject.html;
}
return returnObject.html;
}
})
};
})
};
}
}
return this.schemaCollection.constructor.getTableCols(col, this.schemaCollection);
},
......
......@@ -189,7 +189,7 @@ define(['require',
var that = this;
this.$('.fontLoader').show();
this.$('.searchTable').hide();
this.$('.searchResult').html('');
that.$('.searchResult').hide();
if (Globals.searchApiCallRef) {
Globals.searchApiCallRef.abort();
}
......@@ -260,8 +260,10 @@ define(['require',
},
checkTableFetch: function() {
if (this.fetchList <= 0) {
this.$('div[data-id="r_tableSpinner"]').removeClass('show')
this.$('.fontLoader').hide();
this.$('.searchTable').show();
this.$('.searchResult').show();
}
},
getEntityTableColumns: function() {
......@@ -273,13 +275,15 @@ define(['require',
if (responseData.dataType.attributeDefinitions.length == 2 && responseData.dataType.attributeDefinitions[1].name == "instanceInfo") {
return this.getFixedColumn();
} else {
col['Check'] = {
name: "selected",
label: "",
cell: "select-row",
headerCell: "select-all",
position: 1
};
if (Globals.taxonomy) {
col['Check'] = {
name: "selected",
label: "",
cell: "select-row",
headerCell: "select-all",
position: 1
};
}
var modelJSON = this.searchCollection.toJSON()[0];
_.keys(modelJSON).map(function(key) {
if (key.indexOf("$") == -1 && typeof modelJSON[key] != "object") {
......@@ -342,27 +346,29 @@ define(['require',
}
})
};
col['terms'] = {
label: "Terms",
cell: "Html",
editable: false,
sortable: false,
orderable: true,
className: 'searchTerm',
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
var returnObject = CommonViewFunction.termTableBreadcrumbMaker(model);
if (returnObject.object) {
that.bradCrumbList.push(returnObject.object);
}
if (Globals.entityStateReadOnly[model.get('$id$').state]) {
return '<div class="readOnly">' + returnObject.html + '</div>';
} else {
return returnObject.html;
if (Globals.taxonomy) {
col['terms'] = {
label: "Terms",
cell: "Html",
editable: false,
sortable: false,
orderable: true,
className: 'searchTerm',
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
var returnObject = CommonViewFunction.termTableBreadcrumbMaker(model);
if (returnObject.object) {
that.bradCrumbList.push(returnObject.object);
}
if (Globals.entityStateReadOnly[model.get('$id$').state]) {
return '<div class="readOnly">' + returnObject.html + '</div>';
} else {
return returnObject.html;
}
}
}
})
};
})
};
}
that.checkTableFetch();
return this.searchCollection.constructor.getTableCols(col, this.searchCollection);
}
......
......@@ -22,8 +22,9 @@ define(['require',
'collection/VTagList',
'collection/VEntityList',
'utils/Utils',
'utils/Messages'
], function(require, Backbone, TagLayoutViewTmpl, VTagList, VEntityList, Utils, Messages) {
'utils/Messages',
'utils/Globals'
], function(require, Backbone, TagLayoutViewTmpl, VTagList, VEntityList, Utils, Messages, Globals) {
'use strict';
var TagLayoutView = Backbone.Marionette.LayoutView.extend(
......@@ -113,18 +114,20 @@ define(['require',
}
},
setValues: function(manual) {
if (Utils.getUrlState.isTagTab()) {
if (Utils.getUrlState.isTagTab() || (Utils.getUrlState.isInitial() && !Globals.taxonomy)) {
if (!this.tag) {
this.selectFirst = false;
this.ui.tagsParent.find('li').first().addClass('active');
Utils.setUrl({
url: this.ui.tagsParent.find('li a').first().attr("href"),
mergeBrowserUrl: false,
trigger: true,
updateTabState: function() {
return { tagUrl: this.url, stateChanged: true };
}
});
if (this.ui.tagsParent.find('li a').first().length) {
Utils.setUrl({
url: this.ui.tagsParent.find('li a').first().attr("href"),
mergeBrowserUrl: false,
trigger: true,
updateTabState: function() {
return { tagUrl: this.url, stateChanged: true };
}
});
}
} else {
Utils.setUrl({
url: Utils.getUrlState.getQueryUrl().hash,
......
......@@ -186,3 +186,6 @@ atlas.rest-csrf.enabled=true
atlas.rest-csrf.browser-useragents-regex=^Mozilla.*,^Opera.*,^Chrome.*
atlas.rest-csrf.methods-to-ignore=GET,OPTIONS,HEAD,TRACE
atlas.rest-csrf.custom-header=X-XSRF-HEADER
######### Enable Taxonomy #########
atlas.feature.taxonomy.enable=true
......@@ -6,6 +6,7 @@ INCOMPATIBLE CHANGES:
ALL CHANGES:
ATLAS-1004 Option to enable taxonomy feature (kevalbhatt18 via shwethags)
ATLAS-1003 DataSetLineageServiceTest, GraphBackedDiscoveryServiceTest, and GraphRepoMapperScaleTest failing in some environments (dkantor via shwethags)
ATLAS-1002 Create default user rangertagsync in atlas file authentication for Ranger tag sync module (nixonrodrigues via shwethags)
ATLAS-949 UI improvement for modal and tag styling in table (Kalyanikashikar via shwethags)
......
......@@ -56,6 +56,7 @@ public class AdminResource {
private static final String BROWSER_USER_AGENT_PARAM = "atlas.rest-csrf.browser-useragents-regex";
private static final String CUSTOM_METHODS_TO_IGNORE_PARAM = "atlas.rest-csrf.methods-to-ignore";
private static final String CUSTOM_HEADER_PARAM = "atlas.rest-csrf.custom-header";
private static final String isTaxonomyEnabled = "atlas.feature.taxonomy.enable";
private Response version;
private ServiceState serviceState;
......@@ -141,7 +142,10 @@ public class AdminResource {
@Produces(Servlets.JSON_MEDIA_TYPE)
public Response getUserProfile() {
JSONObject responseData = new JSONObject();
Boolean enableTaxonomy = null;
try {
PropertiesConfiguration configProperties = new PropertiesConfiguration("atlas-application.properties");
enableTaxonomy = new Boolean(configProperties.getString(isTaxonomyEnabled, "false"));
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String userName = null;
Set<String> groups = new HashSet<String>();
......@@ -158,11 +162,13 @@ public class AdminResource {
responseData.put(CUSTOM_METHODS_TO_IGNORE_PARAM, AtlasCSRFPreventionFilter.METHODS_TO_IGNORE_DEFAULT);
responseData.put(CUSTOM_HEADER_PARAM, AtlasCSRFPreventionFilter.HEADER_DEFAULT);
responseData.put(isTaxonomyEnabled, enableTaxonomy);
responseData.put("userName", userName);
responseData.put("groups", groups);
Response response = Response.ok(responseData).build();
return response;
} catch (JSONException e) {
} catch (JSONException | ConfigurationException e) {
throw new WebApplicationException(Servlets.getErrorResponse(e, Response.Status.INTERNAL_SERVER_ERROR));
}
}
......
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