You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2018/01/29 17:56:12 UTC
atlas git commit: ATLAS-2152 : basic-search UI updated to support OR
conditions
Repository: atlas
Updated Branches:
refs/heads/master 37b271072 -> dcdd3d686
ATLAS-2152 : basic-search UI updated to support OR conditions
Signed-off-by: Madhan Neethiraj <ma...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/dcdd3d68
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/dcdd3d68
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/dcdd3d68
Branch: refs/heads/master
Commit: dcdd3d6864479930f3ed9cc471961579d189c940
Parents: 37b2710
Author: pratik24mac <pr...@gmail.com>
Authored: Mon Jan 29 18:15:00 2018 +0530
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Mon Jan 29 09:44:27 2018 -0800
----------------------------------------------------------------------
dashboardv2/public/css/scss/override.scss | 41 ++++-
.../public/js/utils/CommonViewFunction.js | 169 ++++++++++---------
.../public/js/views/search/QueryBuilderView.js | 6 +-
.../public/js/views/search/SearchLayoutView.js | 2 +-
.../public/js/views/search/SearchQueryView.js | 2 +-
5 files changed, 128 insertions(+), 92 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/atlas/blob/dcdd3d68/dashboardv2/public/css/scss/override.scss
----------------------------------------------------------------------
diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss
index 605bcd5..f1e2c6b 100644
--- a/dashboardv2/public/css/scss/override.scss
+++ b/dashboardv2/public/css/scss/override.scss
@@ -112,8 +112,8 @@ td {
td {
white-space: normal;
}
- .select-all-header-cell{
- width : 42px;
+ .select-all-header-cell {
+ width: 42px;
}
}
@@ -316,18 +316,41 @@ td {
.rules-list>:first-child::before {
top: -8px;
}
- .rules-group-header .btn-group.group-conditions label {
- display: none;
- }
.rules-group-container {
- border: none;
+ border-color: transparent;
background: none;
+ .rules-group-header {
+ .group-actions {
+ .btn-success {
+ color: #38BB9B !important;
+ background-color: transparent !important;
+ border-color: #38BB9B !important;
+ }
+ .btn-danger {
+ color: #e14f00;
+ background-color: transparent;
+ border-color: #e14f00;
+ }
+ }
+ .group-conditions {
+ .btn-primary {
+ color: #333 !important;
+ background-color: #fff !important;
+ border-color: #ccc !important;
+ }
+ .active {
+ color: #fff !important;
+ background-color: #5bc0de !important;
+ border-color: #46b8da !important;
+ }
+ }
+ }
}
-}
-.rules-group-header .btn-group.pull-right.group-actions {
- float: left !important;
+ .rules-group-header .btn-group.pull-right.group-actions {
+ float: right !important;
+ }
}
div.columnmanager-visibilitycontrol {
http://git-wip-us.apache.org/repos/asf/atlas/blob/dcdd3d68/dashboardv2/public/js/utils/CommonViewFunction.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js b/dashboardv2/public/js/utils/CommonViewFunction.js
index 6cba9c0..6a5fe25 100644
--- a/dashboardv2/public/js/utils/CommonViewFunction.js
+++ b/dashboardv2/public/js/utils/CommonViewFunction.js
@@ -261,25 +261,29 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
CommonViewFunction.generateQueryOfFilter = function(value) {
var entityFilters = CommonViewFunction.attributeFilter.extractUrl({ "value": value.entityFilters, "formatDate": true }),
tagFilters = CommonViewFunction.attributeFilter.extractUrl({ "value": value.tagFilters, "formatDate": true }),
- queryArray = [],
- objToString = function(filterObj) {
- var tempObj = [];
- _.each(filterObj, function(obj) {
- tempObj.push('<span class="key">' + _.escape(obj.id) + '</span> <span class="operator">' + _.escape(obj.operator) + '</span> <span class="value">' + _.escape(obj.value) + "</span>")
- });
- return tempObj.join(' <span class="operator">AND</span> ');
- }
+ queryArray = [];
+
+ function objToString(filterObj) {
+ var generatedQuery = _.map(filterObj.rules, function(obj, key) {
+ if (_.has(obj, 'condition')) {
+ return ' <span class="operator">' + obj.condition + '</span> ' + '(' + objToString(obj) + ')';
+ } else {
+ return '<span class="key">' + _.escape(obj.id) + '</span> <span class="operator">' + _.escape(obj.operator) + '</span> <span class="value">' + _.escape(obj.value) + "</span>";
+ }
+ });
+ return generatedQuery;
+ }
if (value.type) {
var typeKeyValue = '<span class="key">Type:</span> <span class="value">' + _.escape(value.type) + '</span>';
if (entityFilters) {
- typeKeyValue += ' <span class="operator">AND</span> ' + objToString(entityFilters);
+ typeKeyValue += ' <span class="operator">AND</span> (<span class="operator">' + entityFilters.condition + '</span> (' + objToString(entityFilters) + '))';
}
queryArray.push(typeKeyValue)
}
if (value.tag) {
var tagKeyValue = '<span class="key">Tag:</span> <span class="value">' + _.escape(value.tag) + '</span>';
if (tagFilters) {
- tagKeyValue += ' <span class="operator">AND</span> ' + objToString(tagFilters);
+ tagKeyValue += ' <span class="operator">AND</span> (<span class="operator">' + tagFilters.condition + '</span> (' + objToString(tagFilters) + '))';
}
queryArray.push(tagKeyValue);
}
@@ -335,7 +339,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
obj = {};
if (value) {
_.each(Enums.extractFromUrlForSearch, function(svalue, skey) {
- if(_.isObject(svalue)) {
+ if (_.isObject(svalue)) {
_.each(svalue, function(v, k) {
var val = value[skey][v];
if (!_.isUndefinedNull(val)) {
@@ -349,15 +353,8 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
attrMerge: true,
data: classificationDef.toJSON()
});
- _.each(val.criterion, function(obj) {
- var attributeDef = _.findWhere(attributeDefs, { 'name': obj.attributeName });
- if (attributeDef) {
- obj.attributeValue = obj.attributeValue;
- obj['attributeType'] = attributeDef.typeName;
- }
- });
}
- val = CommonViewFunction.attributeFilter.generateUrl({ "value": val.criterion });
+ val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs });
} else if (k == "entityFilters") {
if (entityDefCollection) {
var entityDef = entityDefCollection.fullCollection.findWhere({ 'name': value[skey].typeName }),
@@ -366,22 +363,15 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
attrMerge: true,
data: entityDef.toJSON()
});
- _.each(val.criterion, function(obj) {
- var attributeDef = _.findWhere(attributeDefs, { 'name': obj.attributeName });
- if (attributeDef) {
- obj.attributeValue = obj.attributeValue;
- obj['attributeType'] = attributeDef.typeName;
- }
- });
}
- val = CommonViewFunction.attributeFilter.generateUrl({ "value": val.criterion });
+ val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs });
} else if (_.contains(["includeDE", "excludeST", "excludeSC"], k)) {
val = val ? false : true;
}
}
obj[k] = val;
});
- }else{
+ } else {
obj[skey] = value[skey];
}
});
@@ -392,23 +382,39 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
generateUrl: function(options) {
var attrQuery = [],
attrObj = options.value,
- formatedDateToLong = options.formatedDateToLong;
- if (attrObj) {
- _.each(attrObj, function(obj) {
- var type = (obj.type || obj.attributeType),
- //obj.value will come as an object when selected type is Date and operator is isNull or not_null;
- value = (_.isObject(obj.value) ? "" : _.trim(obj.value || obj.attributeValue)),
- url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), (type === 'date' && formatedDateToLong && value.length ? Date.parse(value) : value)];
- if (type) {
- url.push(type);
- }
- attrQuery.push(url.join("::"));
- });
- if (attrQuery.length) {
- return attrQuery.join(":,:");
+ formatedDateToLong = options.formatedDateToLong,
+ attributeDefs = options.attributeDefs, /* set attributeType for criterion while creating object*/
+ spliter = 1;
+ attrQuery = conditionalURl(attrObj, spliter);
+
+ function conditionalURl(options, spliter) {
+ if (options) {
+ return _.map(options.rules || options.criterion, function(obj, key) {
+ if (_.has(obj, 'condition')) {
+ return obj.condition + '(' + conditionalURl(obj, (spliter + 1)) + ')';
+ }
+ if (attributeDefs) {
+ var attributeDef = _.findWhere(attributeDefs, { 'name': obj.attributeName });
+ if (attributeDef) {
+ obj.attributeValue = obj.attributeValue;
+ obj['attributeType'] = attributeDef.typeName;
+ }
+ }
+ var type = (obj.type || obj.attributeType),
+ //obj.value will come as an object when selected type is Date and operator is isNull or not_null;
+ value = ((_.isString(obj.value) && _.contains(["is_null","not_null"], obj.operator) && type === 'date') || _.isObject(obj.value) ? "" : _.trim(obj.value || obj.attributeValue)),
+ url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), (type === 'date' && formatedDateToLong && value.length ? Date.parse(value) : value)];
+ if (type) {
+ url.push(type);
+ }
+ return url.join("::");
+ }).join('|' + spliter + '|')
} else {
return null;
}
+ }
+ if (attrQuery.length) {
+ return attrObj.condition + '(' + attrQuery + ')';
} else {
return null;
}
@@ -441,48 +447,48 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
}
},
extractUrl: function(options) {
- var attrObj = [],
+ var attrObj = {},
urlObj = options.value,
- formatDate = options.formatDate;
+ formatDate = options.formatDate,
+ spliter = 1,
+ apiObj = options.apiObj; //if apiObj then create object for API call else for QueryBuilder.
if (urlObj && urlObj.length) {
- _.each(urlObj.split(":,:"), function(obj) {
- var temp = obj.split("::");
- var finalObj = { id: temp[0], operator: temp[1], value: _.trim(temp[2]) }
- if (temp[3]) {
- finalObj['type'] = temp[3];
- }
- finalObj.value = finalObj.type === 'date' && formatDate && finalObj.value.length ? moment(parseInt(finalObj.value)).format('MM/DD/YYYY h:mm A') : finalObj.value;
- attrObj.push(finalObj);
- });
- return attrObj;
- } else {
- return null;
- }
- },
- generateAPIObj: function(url) {
- if (url && url.length) {
- var parsObj = {
- "condition": 'AND',
- "criterion": convertKeyAndExtractObj(this.extractUrl({ "value": url }))
+ attrObj = createObject(urlObj);
+
+ function createObject(urlObj) {
+ var finalObj = {};
+ finalObj['condition'] = /^AND\(/.test(urlObj) ? "AND" : "OR";
+ urlObj = finalObj.condition === "AND" ? urlObj.substr(4).slice(0, -1) : urlObj.substr(3).slice(0, -1);
+ finalObj[apiObj ? "criterion" : "rules"] = _.map(urlObj.split('|' + spliter + '|'), function(obj, key) {
+ var isStringNested = obj.split('|' + (spliter + 1) + '|').length > 1,
+ isCondition = /^AND\(/.test(obj) || /^OR\(/.test(obj);
+ if (isStringNested && isCondition) {
+ ++spliter;
+ return createObject(obj);
+ } else if (isCondition) {
+ return createObject(obj);
+ } else {
+ var temp = obj.split("::") || obj.split('|' + spliter + '|'),
+ rule = {};
+ if (apiObj) {
+ rule = { attributeName: temp[0], operator: mapUiOperatorToAPI(temp[1]), attributeValue: _.trim(temp[2]) }
+ rule.attributeValue = rule.type === 'date' && formatDate && rule.attributeValue.length ? moment(parseInt(rule.attributeValue)).format('MM/DD/YYYY h:mm A') : rule.attributeValue;
+ } else {
+ rule = { id: temp[0], operator: temp[1], value: _.trim(temp[2]) }
+ if (temp[3]) {
+ rule['type'] = temp[3];
+ }
+ rule.value = rule.type === 'date' && formatDate && rule.value.length ? moment(parseInt(rule.value)).format('MM/DD/YYYY h:mm A') : rule.value;
+ }
+ return rule;
+ }
+ });
+ return finalObj;
}
- return parsObj;
} else {
return null;
}
-
- function convertKeyAndExtractObj(rules) {
- var convertObj = [];
- _.each(rules, function(rulObj) {
- var tempObj = {};
- tempObj = {
- "attributeName": rulObj.id,
- "operator": mapUiOperatorToAPI(rulObj.operator),
- "attributeValue": _.trim(rulObj.value)
- }
- convertObj.push(tempObj);
- });
- return convertObj;
- }
+ return attrObj;
function mapUiOperatorToAPI(oper) {
if (oper == "=") {
@@ -510,6 +516,13 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
}
return oper;
}
+ },
+ generateAPIObj: function(url) {
+ if (url && url.length) {
+ return this.extractUrl({ "value": url, "apiObj": true });
+ } else {
+ return null;
+ }
}
}
CommonViewFunction.addRestCsrfCustomHeader = function(xhr, settings) {
http://git-wip-us.apache.org/repos/asf/atlas/blob/dcdd3d68/dashboardv2/public/js/views/search/QueryBuilderView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/search/QueryBuilderView.js b/dashboardv2/public/js/views/search/QueryBuilderView.js
index fdb3c22..9b58271 100644
--- a/dashboardv2/public/js/views/search/QueryBuilderView.js
+++ b/dashboardv2/public/js/views/search/QueryBuilderView.js
@@ -158,8 +158,8 @@ define(['require',
filters: filters,
select_placeholder: '--Select Attribute--',
allow_empty: true,
- conditions: ['AND'],
- allow_groups: false,
+ conditions: ['AND','OR'],
+ allow_groups: true,
allow_empty: true,
operators: [
{ type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
@@ -188,7 +188,7 @@ define(['require',
},
rules: rules_widgets
});
- this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-right pull-left');
+ this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-left');
} else {
this.ui.builder.html('<h4>No Attributes are available !</h4>')
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/dcdd3d68/dashboardv2/public/js/views/search/SearchLayoutView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/search/SearchLayoutView.js b/dashboardv2/public/js/views/search/SearchLayoutView.js
index 255cf74..a0cd41e 100644
--- a/dashboardv2/public/js/views/search/SearchLayoutView.js
+++ b/dashboardv2/public/js/views/search/SearchLayoutView.js
@@ -388,7 +388,7 @@ define(['require',
var rule = queryBuilderRef.queryBuilder('getRules');
}
if (rule) {
- var ruleUrl = CommonViewFunction.attributeFilter.generateUrl({ "value": rule.rules, "formatedDateToLong": true });
+ var ruleUrl = CommonViewFunction.attributeFilter.generateUrl({ "value": rule, "formatedDateToLong": true });
this.searchTableFilters[filtertype][(isTag ? this.value.tag : this.value.type)] = ruleUrl;
this.makeFilterButtonActive(filtertype);
if (!isTag && this.value && this.value.type && this.searchTableColumns) {
http://git-wip-us.apache.org/repos/asf/atlas/blob/dcdd3d68/dashboardv2/public/js/views/search/SearchQueryView.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/views/search/SearchQueryView.js b/dashboardv2/public/js/views/search/SearchQueryView.js
index 2446d3d..61a4311 100644
--- a/dashboardv2/public/js/views/search/SearchQueryView.js
+++ b/dashboardv2/public/js/views/search/SearchQueryView.js
@@ -57,8 +57,8 @@ define(['require',
title: 'Attribute Filter',
content: this,
allowCancel: true,
+ mainClass : 'modal-lg',
okCloses: false,
- width: '50%',
buttons: [{
text: 'Cancel',
btnClass: "cancel btn-action",