Commit b15aa400 by Hemanth Yamijala

ATLAS-664 UI: Add Support for Versioning / History (Kalyanikashikar via yhemanth)

parent 208e90b1
......@@ -27,7 +27,7 @@ $color_puerto_rico_approx: #3dd4af;
$color_star_dust_approx: #9a9a9a;
$color_mirage_approx: #1c1e2a;
$concrete: #f2f2f2;
//fonts
$lightGrey:#e1e2e4; //fonts
$font_0: Source Sans Pro;
$font_1: sans-serif;
$font_2: FontAwesome;
......@@ -132,6 +132,7 @@ ul {
}
.table {
background-color: $white;
.table {
width: auto;
}
......@@ -155,3 +156,13 @@ ul {
bottom: 0;
display: none;
}
.auditCreateBtn {
background-color: #359f89;
color: white;
cursor: pointer;
}
.aditCreateBtn {
cursor: pointer;
}
......@@ -41,15 +41,32 @@
}
.table-quickMenu {
border: 1px #ddd solid;
border: thin $lightGrey solid;
border-collapse: separate;
border-radius: 6px;
box-shadow: 0px 0px 4px #d8d8d8;
overflow: visible !important;
}
.table-quickMenu>thead>tr>th {
border-bottom-width: 0px;
padding: 24px 8px;
border-width: thin;
border-color: $action_gray;
border-bottom-style: solid;
box-shadow: none;
padding: 20px 30px;
background-color: transparent;
text-align: left;
font-weight: 800;
font-size: 14px;
letter-spacing: 0.25px;
color: rgba(52, 52, 52, 1);
}
.table-quickMenu > tbody > tr > td {
border-color: $color_gallery_approx;
color: #333333;
font-weight: 100;
padding: 15px 30px;
}
.backgrid-paginator ul > li > a:hover,
......
......@@ -47,7 +47,7 @@
max-width: 93%;
}
}
&.parentChiled {
&.parentChild {
ul {
padding-left: 9%;
}
......
......@@ -14,13 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<table class="table table-quickMenu">
<table class="table table-bordered table-striped" data-id="tableAudit">
<thead>
<tr>
<th>Key</th>
<th>Value</th>
<tr data-id="auditHeaderValue">
</tr>
</thead>
<tbody data-id="auditValue">
</tbody>
</table>
<h3 data-id="noData" style="display:none">No details to show</h3>
......@@ -58,6 +58,7 @@
<!-- <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>
<li role="presentation"><a href="#tab-termTable" aria-controls="tab-termTable" role="tab" data-toggle="tab">Terms</a></li>
<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>
<div class="tab-content">
......@@ -70,6 +71,9 @@
<div id="tab-termTable" role="tabpanel" class="tab-pane">
<div id="r_termTableLayoutView"></div>
</div>
<div id="tab-audit" role="tabpanel" class="tab-pane">
<div id="r_auditTableLayoutView"></div>
</div>
<div id="tab-schema" role="tabpanel" class="tab-pane">
<div id="r_schemaTableLayoutView"></div>
</div>
......
......@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<div class="container-fluid">
<div class="container-fluid gray-bg">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<div class="atlast-tabbable">
......
......@@ -90,5 +90,85 @@ define(['require', 'utils/Utils', 'modules/Modal'], function(require, Utils, Mod
}
});
};
CommonViewFunction.propertyTable = function(valueObject, scope) {
var table = "",
fetchInputOutputValue = function(id) {
var that = this;
scope.model.getEntity(id, {
beforeSend: function() {},
success: function(data) {
var value = "";
if (data.definition.values.name) {
value = data.definition.values.name;
} else {
value = data.GUID;
}
scope.$('td div[data-id="' + data.GUID + '"]').html('<a href="#!/detailPage/' + data.GUID + '">' + value + '</a>');
},
error: function(error, data, status) {},
complete: function() {}
});
}
_.keys(valueObject).map(function(key) {
var keyValue = valueObject[key];
if (_.isArray(keyValue)) {
var subLink = "";
for (var i = 0; i < keyValue.length; i++) {
var inputOutputField = keyValue[i],
id = undefined;
if (_.isObject(inputOutputField.id)) {
id = inputOutputField.id.id;
} else {
id = inputOutputField.id;
}
if (id) {
fetchInputOutputValue(id);
subLink += '<div data-id="' + id + '"></div>';
} else {
subLink += '<div></div>';
}
}
table += '<tr><td>' + key + '</td><td>' + subLink + '</td></tr>';
} else if (_.isObject(keyValue)) {
var id = undefined;
if (_.isObject(keyValue.id)) {
id = keyValue.id.id;
} else {
id = keyValue.id;
}
if (id) {
fetchInputOutputValue(id);
table += '<tr><td>' + key + '</td><td><div data-id="' + id + '"></div></td></tr>';
} else {
var stringArr = [];
_.each(keyValue, function(val, key) {
var value = "";
if (_.isObject(val)) {
value = JSON.stringify(val);
} else {
value = val;
}
var attrName = "<span>" + key + " : " + value + "</span>";
stringArr.push(attrName);
});
var jointValues = stringArr.join(", ");
if (jointValues.length) {
table += '<tr><td>' + key + '</td><td><div>' + jointValues + '</div></td></tr>';
} else {
table += '<tr><td>' + key + '</td><td></td></tr>';
}
}
} else {
if (key == "createTime" || key == "lastAccessTime" || key == "retention") {
table += '<tr><td>' + key + '</td><td>' + new Date(valueObject[key]) + '</td></tr>';
} else {
table += '<tr><td>' + key + '</td><td>' + valueObject[key] + '</td></tr>';
}
}
});
return table;
}
return CommonViewFunction;
});
......@@ -34,6 +34,13 @@ define(['require'], function(require) {
},
detailPageState: {}
};
Globals.auditAction = {
ENTITY_CREATE: "Entity Created",
ENTITY_UPDATE: "Entity Updated",
ENTITY_DELETE: "Entity Deleted",
TAG_ADD: "Tag Added",
TAG_DELETE: "Tag Deleted"
}
return Globals;
});
......@@ -20,8 +20,8 @@ define(['require',
'backbone',
'hbs!tmpl/audit/AuditTableLayoutView_tmpl',
'collection/VEntityList',
'moment'
], function(require, Backbone, AuditTableLayoutView_tmpl, VEntityList, moment) {
'utils/Globals'
], function(require, Backbone, AuditTableLayoutView_tmpl, VEntityList, Globals) {
'use strict';
var AuditTableLayoutView = Backbone.Marionette.LayoutView.extend(
......@@ -61,11 +61,11 @@ define(['require',
this.commonTableOptions = {
collection: this.entityCollection,
includeFilter: false,
includePagination: false,
includePageSize: false,
includePagination: true,
includePageSize: true,
includeFooterRecords: true,
gridOpts: {
className: "table table-striped table-condensed backgrid table-quickMenu",
className: "table table-hover backgrid table-quickMenu",
emptyText: 'No records found!'
},
filterOpts: {},
......@@ -88,10 +88,7 @@ define(['require',
var cols = new Backgrid.Columns(that.getAuditTableColumns());
that.RAuditTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, {
globalVent: that.globalVent,
columns: cols,
gridOpts: {
className: "table table-quickMenu",
},
columns: cols
})));
});
},
......@@ -99,41 +96,52 @@ define(['require',
var that = this;
return this.entityCollection.constructor.getTableCols({
user: {
label: "User",
label: "Users",
cell: "html",
editable: false,
sortable: false,
},
timestamp: {
label: "Timestamp",
cell: "time",
cell: "html",
editable: false,
sortable: false,
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
return moment(rawValue).format("YYYY-MM-DD HH:mm:ss,SSS");
return new Date(rawValue);
}
})
},
action: {
label: "Action",
label: "Actions",
cell: "html",
editable: false,
sortable: false
sortable: false,
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
that.detailBtnDisable = false;
if (Globals.auditAction[rawValue]) {
return Globals.auditAction[rawValue]
} else {
return rawValue
}
}
})
},
tool: {
label: "Tool",
label: "Tools",
cell: "html",
editable: false,
sortable: false,
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
return '<div class="label label-success auditCreateBtn" data-id="auditCreate">Create</div>';
return '<div class="label label-success aditCreateBtn" data-id="auditCreate" data-action="' + Globals.auditAction[model.attributes.action] + '" disabled="' + that.detailBtnDisable + '" data-modalId="' + model.get('eventKey') + '">Detail</div>';
}
})
},
}, this.entityCollection);
},
onClickAuditCreate: function(e) {
var that = this;
......@@ -141,14 +149,18 @@ define(['require',
'modules/Modal',
'views/audit/CreateAuditTableLayoutView',
], function(Modal, CreateAuditTableLayoutView) {
var view = new CreateAuditTableLayoutView({ guid: that.guid });
var collectionModel = that.entityCollection.findWhere({ 'eventKey': $(e.currentTarget).data('modalid') });
that.action = $(e.target).data("action");
var view = new CreateAuditTableLayoutView({ guid: that.guid, model: collectionModel, action: that.action });
var modal = new Modal({
title: 'Create',
title: that.action,
content: view,
okCloses: true,
showFooter: true,
}).open();
view.on('closeModal', function() {
modal.trigger('cancel');
});
});
}
});
......
......@@ -19,8 +19,9 @@
define(['require',
'backbone',
'hbs!tmpl/audit/CreateAuditTableLayoutView_tmpl',
'collection/VEntityList'
], function(require, Backbone, CreateAuditTableLayoutViewTmpl, VEntityList) {
'utils/Globals',
'utils/CommonViewFunction'
], function(require, Backbone, CreateAuditTableLayoutViewTmpl, Globals, CommonViewFunction) {
'use strict';
var CreateAuditTableLayoutView = Backbone.Marionette.LayoutView.extend(
......@@ -37,6 +38,9 @@ define(['require',
ui: {
auditValue: "[data-id='auditValue']",
auditCreate: "[data-id='auditCreate']",
noData: "[data-id='noData']",
tableAudit: "[data-id='tableAudit']",
auditHeaderValue: "[data-id='auditHeaderValue']"
},
/** ui events hash */
events: function() {
......@@ -45,87 +49,47 @@ define(['require',
return events;
},
/**
* intialize a new AuditTableLayoutView Layout
* intialize a new CreateAuditTableLayoutView Layout
* @constructs
*/
initialize: function(options) {
_.extend(this, _.pick(options, 'globalVent', 'guid'));
this.entityCollection = new VEntityList();
this.entityCollection.url = "/api/atlas/entities/" + this.guid + "/audit";
this.entityCollection.modelAttrName = "events";
this.entityModel = new this.entityCollection.model();
},
bindEvents: function() {
this.listenTo(this.entityCollection, "reset", function(value) {
this.auditTableGenerate();
}, this);
_.extend(this, _.pick(options, 'globalVent', 'guid', 'model', 'action'));
},
bindEvents: function() {},
onRender: function() {
this.entityCollection.fetch({ reset: true });
this.bindEvents();
this.auditTableGenerate();
},
auditTableGenerate: function() {
var that = this,
table = "";
var collectionObject = this.entityCollection.models[0].toJSON();
var appendedString = "{" + collectionObject.details + "}";
if (this.model.get('details').search('{') >= 0) {
var appendedString = "{" + this.model.get('details') + "}";
var auditData = appendedString.split('"')[0].split(':')[0].split("{")[1];
var detailsObject = JSON.parse(appendedString.replace("{" + auditData + ":", '{"' + auditData + '":'))[auditData];
//Append string for JSON parse
var valueObject = detailsObject.values;
_.keys(valueObject).map(function(key) {
var keyValue = valueObject[key];
if (_.isArray(keyValue)) {
var subLink = "";
for (var i = 0; i < keyValue.length; i++) {
var inputOutputField = keyValue[i];
if (_.isObject(inputOutputField.id)) {
id = inputOutputField.id.id;
if (this.action == Globals.auditAction.TAG_ADD) {
this.ui.auditHeaderValue.html('<th>Tag</th>');
this.ui.auditValue.html("<tr><td>" + detailsObject.typeName + "</td></tr>");
} else {
id = inputOutputField.id;
}
that.fetchInputOutputValue(id);
//var coma = (i = 0) ? ('') : (',');
subLink += '<div data-id="' + id + '"></div>';
}
table += '<tr><td>' + key + '</td><td>' + subLink + '</td></tr>';
} else if (_.isObject(keyValue)) {
var id = "";
if (_.isObject(keyValue.id)) {
id = keyValue.id.id;
this.ui.auditHeaderValue.html('<th>Key</th><th>New Value</th>');
table = CommonViewFunction.propertyTable(valueObject, this);
if (table.length) {
this.ui.noData.hide();
this.ui.tableAudit.show();
this.ui.auditValue.html(table);
} else {
id = keyValue.id;
this.ui.noData.show();
this.ui.tableAudit.hide();
}
that.fetchInputOutputValue(id);
table += '<tr><td>' + key + '</td><td><div data-id="' + id + '"></div></td></tr>';
} else {
if (key == "createTime" || key == "lastAccessTime" || key == "retention") {
table += '<tr><td>' + key + '</td><td>' + new Date(valueObject[key]) + '</td></tr>';
} else {
table += '<tr><td>' + key + '</td><td>' + valueObject[key] + '</td></tr>';
}
} else if (this.action == Globals.auditAction.TAG_DELETE) {
var appendedString = this.model.get('details').split(':');
this.ui.auditHeaderValue.html('<th>Tag</th>');
this.ui.auditValue.html("<tr><td>" + appendedString[1] + "</td></tr>");
}
});
that.ui.auditValue.append(table);
},
fetchInputOutputValue: function(id) {
var that = this;
this.entityModel.getEntity(id, {
beforeSend: function() {},
success: function(data) {
var value = "";
if (data.definition.values.name) {
value = data.definition.values.name;
} else {
value = data.GUID;
}
that.$('td div[data-id="' + data.GUID + '"]').html('<a href="#!/detailPage/' + data.GUID + '">' + value + '</a>');
},
error: function(error, data, status) {},
complete: function() {}
});
}
});
return CreateAuditTableLayoutView;
});
......@@ -40,6 +40,7 @@ define(['require',
RSchemaTableLayoutView: "#r_schemaTableLayoutView",
RTagTableLayoutView: "#r_tagTableLayoutView",
RLineageLayoutView: "#r_lineageLayoutView",
RAuditTableLayoutView: "#r_auditTableLayoutView",
RTermTableLayoutView: "#r_termTableLayoutView"
},
......@@ -162,6 +163,7 @@ define(['require',
this.renderTagTableLayoutView(tagGuid);
this.renderLineageLayoutView(tagGuid);
this.renderSchemaLayoutView(tagGuid);
this.renderAuditTableLayoutView(tagGuid);
this.renderTermTableLayoutView(tagGuid);
}, this);
},
......@@ -313,6 +315,15 @@ define(['require',
}));
});
},
renderAuditTableLayoutView: function(tagGuid) {
var that = this;
require(['views/audit/AuditTableLayoutView'], function(AuditTableLayoutView) {
that.RAuditTableLayoutView.show(new AuditTableLayoutView({
globalVent: that.globalVent,
guid: tagGuid
}));
});
},
renderTermTableLayoutView: function(tagGuid) {
var that = this;
require(['views/tag/TagDetailTableLayoutView'], function(TagDetailTableLayoutView) {
......
......@@ -19,7 +19,8 @@
define(['require',
'backbone',
'hbs!tmpl/entity/EntityDetailTableLayoutView_tmpl',
], function(require, Backbone, EntityDetailTableLayoutView_tmpl) {
'utils/CommonViewFunction'
], function(require, Backbone, EntityDetailTableLayoutView_tmpl, CommonViewFunction) {
'use strict';
var EntityDetailTableLayoutView = Backbone.Marionette.LayoutView.extend(
......@@ -48,7 +49,7 @@ define(['require',
initialize: function(options) {
_.extend(this, _.pick(options, 'globalVent', 'collection'));
this.collectionObject = this.collection.toJSON();
this.entityModel = new this.collection.model();
this.model = new this.collection.model();
},
bindEvents: function() {},
onRender: function() {
......@@ -56,87 +57,9 @@ define(['require',
},
entityTableGenerate: function() {
var that = this,
table = "",
valueObject = this.collectionObject[0].values;
_.keys(valueObject).map(function(key) {
/* if (key == 'columns')
return;*/
var keyValue = valueObject[key];
if (_.isArray(keyValue)) {
var subLink = "";
for (var i = 0; i < keyValue.length; i++) {
var inputOutputField = keyValue[i],
id = undefined;
if (_.isObject(inputOutputField.id)) {
id = inputOutputField.id.id;
} else {
id = inputOutputField.id;
}
if (id) {
that.fetchInputOutputValue(id);
subLink += '<div data-id="' + id + '"></div>';
} else {
subLink += '<div></div>';
}
}
table += '<tr><td>' + key + '</td><td>' + subLink + '</td></tr>';
} else if (_.isObject(keyValue)) {
var id = undefined;
if (_.isObject(keyValue.id)) {
id = keyValue.id.id;
} else {
id = keyValue.id;
}
if (id) {
that.fetchInputOutputValue(id);
table += '<tr><td>' + key + '</td><td><div data-id="' + id + '"></div></td></tr>';
} else {
var stringArr = [];
_.each(keyValue, function(val, key) {
var value = "";
if (_.isObject(val)) {
value = JSON.stringify(val);
} else {
value = val;
}
var attrName = "<span>" + key + " : " + value + "</span>";
stringArr.push(attrName);
});
var jointValues = stringArr.join(", ");
if (jointValues.length) {
table += '<tr><td>' + key + '</td><td><div>' + jointValues + '</div></td></tr>';
} else {
table += '<tr><td>' + key + '</td><td></td></tr>';
}
}
} else {
if (key == "createTime" || key == "lastAccessTime" || key == "retention") {
table += '<tr><td>' + key + '</td><td>' + new Date(valueObject[key]) + '</td></tr>';
} else {
table += '<tr><td>' + key + '</td><td>' + valueObject[key] + '</td></tr>';
}
}
});
valueObject = this.collectionObject[0].values,
table = CommonViewFunction.propertyTable(valueObject, this);
that.ui.detailValue.append(table);
},
fetchInputOutputValue: function(id) {
var that = this;
this.entityModel.getEntity(id, {
beforeSend: function() {},
success: function(data) {
var value = "";
if (data.definition.values.name) {
value = data.definition.values.name;
} else {
value = data.GUID;
}
that.$('td div[data-id="' + data.GUID + '"]').html('<a href="#!/detailPage/' + data.GUID + '">' + value + '</a>');
},
error: function(error, data, status) {},
complete: function() {}
});
}
});
return EntityDetailTableLayoutView;
......
......@@ -74,8 +74,8 @@ define(['require',
this.commonTableOptions = {
collection: this.schemaCollection,
includeFilter: false,
includePagination: false,
includePageSize: false,
includePagination: true,
includePageSize: true,
includeFooterRecords: true,
gridOpts: {
className: "table table-striped table-condensed backgrid table-quickMenu",
......
......@@ -60,10 +60,12 @@ define(['require',
'searchType': that.value.searchType
};
}
if (that.RSearchResultLayoutView) {
that.RSearchResultLayoutView.show(new SearchResultLayoutView({
value: value,
tag: that.tag
}));
}
});
}
});
......
......@@ -176,9 +176,10 @@ define(['require',
} else if (model.get('name') == "owner") {
model.set("position", 3, { silent: true });
model.set("label", "Owner");
} else {
model.set("position", ++count, { silent: true });
}
/*else {
model.set("position", ++count, { silent: true });
}*/
});
return this;
}
......
......@@ -22,6 +22,7 @@ ATLAS-409 Atlas will not import avro tables with schema read from a file (dosset
ATLAS-379 Create sqoop and falcon metadata addons (venkatnrangan,bvellanki,sowmyaramesh via shwethags)
ALL CHANGES:
ATLAS-664 UI: Add Support for Versioning / History (Kalyanikashikar via yhemanth)
ATLAS-833 Make default build profile for External HBase and Solr (tbeerbower via yhemanth)
ATLAS-841 mvn clean install of Atlas is failing python unit tests (yhemanth)
ATLAS-834 Handle exceptions from HiveHook executor.submit() (sumasai)
......
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