You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by kb...@apache.org on 2020/01/29 09:48:42 UTC

[atlas] branch branch-2.0 updated (b7772fd -> 3850684)

This is an automated email from the ASF dual-hosted git repository.

kbhatt pushed a change to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/atlas.git.


    from b7772fd  ATLAS-3592 : UI: Ignore any empty values for Date type attribute in Entity property table
     new 3941a8a  ATLAS-3596: UI: Improved System attribute presentation for user friendliness
     new 3850684  ATLAS-3599 : Beta UI: While Saving search , limit and offset are not set properly when using Beta UI.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 dashboardv2/public/css/scss/override.scss          |  31 ++-
 dashboardv2/public/css/scss/search.scss            |  47 ++++-
 .../js/templates/search/UserDefine_tmpl.html       |  44 ++++
 dashboardv2/public/js/utils/Enums.js               |   4 +-
 .../public/js/views/entity/EntityUserDefineView.js |   4 +-
 .../public/js/views/search/QueryBuilderView.js     | 228 +++++++++++++++++++-
 .../public/js/views/search/SearchQueryView.js      |   3 +-
 .../js/views/search/SearchResultLayoutView.js      |  25 +++
 dashboardv3/public/css/scss/override.scss          |  31 ++-
 dashboardv3/public/css/scss/search.scss            |  53 ++++-
 .../js/templates/search/UserDefine_tmpl.html       |  44 ++++
 dashboardv3/public/js/utils/Enums.js               |   8 +-
 .../public/js/views/entity/EntityUserDefineView.js |   2 +-
 .../public/js/views/search/QueryBuilderView.js     | 229 ++++++++++++++++++++-
 .../js/views/search/SearchDefaultLayoutView.js     | 125 +++++------
 .../js/views/search/SearchResultLayoutView.js      |  25 +++
 .../search/tree/CustomFilterTreeLayoutView.js      |  28 ++-
 17 files changed, 819 insertions(+), 112 deletions(-)
 create mode 100644 dashboardv2/public/js/templates/search/UserDefine_tmpl.html
 create mode 100644 dashboardv3/public/js/templates/search/UserDefine_tmpl.html


[atlas] 01/02: ATLAS-3596: UI: Improved System attribute presentation for user friendliness

Posted by kb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kbhatt pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/atlas.git

commit 3941a8a2a1079b8df46dc9792b47c850da401b7f
Author: kevalbhatt <kb...@apache.org>
AuthorDate: Tue Jan 28 16:11:00 2020 +0530

    ATLAS-3596: UI: Improved System attribute presentation for user friendliness
    
    (cherry picked from commit e04c4f5c332322e191e1d8abdadc250bf03e2840)
---
 dashboardv2/public/css/scss/override.scss          |  31 ++-
 dashboardv2/public/css/scss/search.scss            |  47 ++++-
 .../js/templates/search/UserDefine_tmpl.html       |  44 ++++
 dashboardv2/public/js/utils/Enums.js               |   4 +-
 .../public/js/views/entity/EntityUserDefineView.js |   4 +-
 .../public/js/views/search/QueryBuilderView.js     | 228 +++++++++++++++++++-
 .../public/js/views/search/SearchQueryView.js      |   3 +-
 .../js/views/search/SearchResultLayoutView.js      |  25 +++
 dashboardv3/public/css/scss/override.scss          |  31 ++-
 dashboardv3/public/css/scss/search.scss            |  53 ++++-
 .../js/templates/search/UserDefine_tmpl.html       |  44 ++++
 dashboardv3/public/js/utils/Enums.js               |   8 +-
 .../public/js/views/entity/EntityUserDefineView.js |   2 +-
 .../public/js/views/search/QueryBuilderView.js     | 229 ++++++++++++++++++++-
 .../js/views/search/SearchDefaultLayoutView.js     | 125 +++++------
 .../js/views/search/SearchResultLayoutView.js      |  25 +++
 16 files changed, 800 insertions(+), 103 deletions(-)

diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss
index d918f66..b6c42f6 100644
--- a/dashboardv2/public/css/scss/override.scss
+++ b/dashboardv2/public/css/scss/override.scss
@@ -294,6 +294,21 @@ td {
 .query-builder {
     .rule-container {
         margin: 6px 0;
+        display: flex;
+        flex-wrap: wrap;
+
+        .values-box {
+            display: flex;
+            flex-grow: 1;
+            width: 100%;
+            padding-right: 26px;
+        }
+
+        .action-box {
+            position: absolute;
+            right: 4px;
+            top: calc(50% - 18px);
+        }
 
         .rule-header {
             .rule-actions {
@@ -301,24 +316,34 @@ td {
             }
         }
 
+        .error-container {
+            color: $color_trinidad_approx;
+        }
+
         .rule-value-container {
             display: inline-block !important;
+            border-left: none;
+            width: calc(65% - 105px);
 
             .form-control {
-                width: 220px !important;
+                width: 100% !important;
                 padding: 6px 12px !important;
             }
         }
 
         .rule-filter-container {
+            width: 35%;
+
             .form-control {
-                width: 200px !important;
+                width: 100% !important;
             }
         }
 
         .rule-operator-container {
+            width: 105px;
+
             .form-control {
-                width: auto !important;
+                width: 100% !important;
             }
         }
     }
diff --git a/dashboardv2/public/css/scss/search.scss b/dashboardv2/public/css/scss/search.scss
index 11d7144..fdb4d69 100644
--- a/dashboardv2/public/css/scss/search.scss
+++ b/dashboardv2/public/css/scss/search.scss
@@ -57,7 +57,7 @@ $color_celeste_approx: #1D1F2B;
         background-color: $color_jungle_green_approx;
         border-radius: 10px;
         box-shadow: inset 0 1px rgba(black, .02);
-        @include transition(inherit)
+        @include transition(inherit);
     }
 
     .switch-input:checked~& {
@@ -240,6 +240,47 @@ hr.hr-filter {
     }
 }
 
-.filter-btn-wrapper {
-    padding-left: 0;
+.query-builder {
+    .rule-container {
+        &.user-define {
+            .values-box {
+                display: flex;
+                flex-wrap: wrap;
+
+                .rule-filter-container {
+                    width: 200px;
+                }
+
+                .rule-value-container {
+                    width: 100%;
+                    padding: 7px 0px 0px 0px;
+                }
+            }
+        }
+
+        .rule-value-container {
+            &>table.custom-table {
+                tr {
+                    display: none;
+
+                    &.custom-tr {
+                        display: table-row;
+
+                        td.custom-col-1 {
+                            width: 48%;
+
+                            .errorMsg {
+                                display: none;
+                            }
+                        }
+                    }
+                }
+
+                input,
+                textarea {
+                    width: 100% !important;
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/dashboardv2/public/js/templates/search/UserDefine_tmpl.html b/dashboardv2/public/js/templates/search/UserDefine_tmpl.html
new file mode 100644
index 0000000..8868e90
--- /dev/null
+++ b/dashboardv2/public/js/templates/search/UserDefine_tmpl.html
@@ -0,0 +1,44 @@
+<!--
+ * 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.
+-->
+<table class="custom-table">
+    <tbody>
+        <tr class="custom-tr">
+            <td class="custom-col-1">
+                <input placeholder="key" type="text" data-type="key" data-index="0" class="form-control" value="">
+                <p class="errorMsg"></p>
+            </td>
+            <td class="custom-col-0"> : </td>
+            <td class="custom-col-1">
+                <textarea placeholder="value" data-type="value" data-index="0" class="form-control"></textarea>
+                <p class="errorMsg"></p>
+            </td>
+            <!-- <td class="custom-col-2">
+                <button class="btn btn-default btn-sm" title="" data-index="0" data-id="deleteUserDefineItem">
+                    <i class="fa fa-minus"> </i>
+                </button>
+                <button class="btn btn-default btn-sm" title="" data-index="0" data-id="addUserDefineItem">
+                    <i class="fa fa-plus"> </i>
+                </button>
+            </td> -->
+        </tr>
+        <tr>
+            <td colspan="4">
+                <p class="errorMsg" data-id="charSupportMsg"></p>
+            </td>
+        </tr>
+    </tbody>
+</table>
\ No newline at end of file
diff --git a/dashboardv2/public/js/utils/Enums.js b/dashboardv2/public/js/utils/Enums.js
index f5d1ba6..82e11ca 100644
--- a/dashboardv2/public/js/utils/Enums.js
+++ b/dashboardv2/public/js/utils/Enums.js
@@ -194,8 +194,8 @@ define(['require'], function(require) {
     };
     Enums.systemAttributes = {
         "__classificationNames": "Classification(s)",
-        "__createdBy": "Created By",
-        "__customAttributes": "User-defined attributes",
+        "__createdBy": "Created By User",
+        "__customAttributes": "User-defined Properties",
         "__guid": "Guid",
         "__isIncomplete": "IsIncomplete",
         "__labels": "Label(s)",
diff --git a/dashboardv2/public/js/views/entity/EntityUserDefineView.js b/dashboardv2/public/js/views/entity/EntityUserDefineView.js
index e206d55..1cb0d8c 100644
--- a/dashboardv2/public/js/views/entity/EntityUserDefineView.js
+++ b/dashboardv2/public/js/views/entity/EntityUserDefineView.js
@@ -54,7 +54,7 @@ define(['require',
         },
         initialize: function(options) {
             _.extend(this, _.pick(options, 'entity', 'customFilter'));
-            this.userDefineAttr = this.entity.customAttributes || [];
+            this.userDefineAttr = this.entity && this.entity.customAttributes || [];
             this.initialCall = false;
             this.swapItem = false, this.saveAttrItems = false;
             this.readOnlyEntity = this.customFilter === undefined ? Enums.entityStateReadOnly[this.entity.status] : this.customFilter;
@@ -123,7 +123,7 @@ define(['require',
                 data: JSON.stringify(payload),
                 type: 'POST',
                 success: function() {
-                    var msg = _.isEmpty(that.customAttibutes) ? 'addSuccessMessage' : 'editSuccessMessage',
+                    var msg = that.initialCall ? 'addSuccessMessage' : 'editSuccessMessage',
                         caption = "One or more user-defined propertie"; // 's' will be added in abbreviation function
                     that.customAttibutes = list;
                     if (list.length === 0) {
diff --git a/dashboardv2/public/js/views/search/QueryBuilderView.js b/dashboardv2/public/js/views/search/QueryBuilderView.js
index 5cbbbc3..cca7992 100644
--- a/dashboardv2/public/js/views/search/QueryBuilderView.js
+++ b/dashboardv2/public/js/views/search/QueryBuilderView.js
@@ -19,19 +19,20 @@
 define(['require',
     'backbone',
     'hbs!tmpl/search/QueryBuilder_tmpl',
+    'hbs!tmpl/search/UserDefine_tmpl',
     'utils/Utils',
     'utils/CommonViewFunction',
     'utils/Enums',
     'query-builder',
     'daterangepicker'
-], function(require, Backbone, QueryBuilder_Tmpl, Utils, CommonViewFunction, Enums) {
+], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums) {
 
     var QueryBuilderView = Backbone.Marionette.LayoutView.extend(
         /** @lends QueryBuilderView */
         {
             _viewName: 'QueryBuilderView',
 
-            template: QueryBuilder_Tmpl,
+            template: QueryBuilderTmpl,
 
 
 
@@ -53,13 +54,22 @@ define(['require',
              * @constructs
              */
             initialize: function(options) {
-                _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'tag', 'searchTableFilters', 'systemAttrArr'));
+                _.extend(this, _.pick(options,
+                    'attrObj',
+                    'value',
+                    'typeHeaders',
+                    'entityDefCollection',
+                    'enumDefCollection',
+                    'classificationDefCollection',
+                    'tag',
+                    'searchTableFilters',
+                    'systemAttrArr'));
                 this.attrObj = _.sortBy(this.attrObj, 'name');
-                this.systemAttrArr = _.sortBy(this.systemAttrArr, 'name');
+                //this.systemAttrArr = _.sortBy(this.systemAttrArr, 'name');
                 this.filterType = this.tag ? 'tagFilters' : 'entityFilters';
             },
             bindEvents: function() {},
-            getOperator: function(type) {
+            getOperator: function(type, skipDefault) {
                 var obj = {
                     operators: null
                 }
@@ -72,7 +82,7 @@ define(['require',
                 if (type === "enum" || type === "boolean") {
                     obj.operators = ['=', '!='];
                 }
-                if (obj.operators) {
+                if (_.isEmpty(skipDefault) && obj.operators) {
                     obj.operators = obj.operators.concat(['is_null', 'not_null']);
                 }
                 return obj;
@@ -83,34 +93,180 @@ define(['require',
                 }
                 return false;
             },
+            getUserDefineInput: function() {
+                return UserDefineTmpl();
+            },
             getObjDef: function(attrObj, rules, isGroup, groupType, isSystemAttr) {
+                var that = this;
                 if (attrObj.name === "__classificationsText" || attrObj.name === "__historicalGuids") {
                     return;
                 }
+                var getLableWithType = function(label, name) {
+                    if (name === "__classificationNames" || name === "__customAttributes" || name === "__labels" || name === "__propagatedClassificationNames") {
+                        return label;
+                    } else {
+                        return label + " (" + attrObj.typeName + ")";
+                    }
+
+                }
+                var label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize()));
                 var obj = {
                     id: attrObj.name,
-                    label: (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (" + attrObj.typeName + ")",
-                    type: _.escape(attrObj.typeName)
+                    label: getLableWithType(label, attrObj.name),
+                    plainLabel: label,
+                    type: _.escape(attrObj.typeName),
+                    validation: {
+                        callback: function(value, rule) {
+                            if (rule.operator.nb_inputs === false || !_.isEmpty(value) || !value instanceof Error) {
+                                return true;
+                            } else {
+                                if (value instanceof Error) {
+                                    return value.message; // with params
+                                } else {
+                                    return rule.filter.plainLabel + ' is required'; // with params
+                                }
+                            }
+                        }
+                    }
                 };
                 if (isGroup) {
                     obj.optgroup = groupType;
                 }
+                /* __isIncomplete / IsIncomplete */
                 if (isSystemAttr && attrObj.name === "__isIncomplete" || isSystemAttr && attrObj.name === "IsIncomplete") {
                     obj.type = "boolean";
                     obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (boolean)";
                     obj['input'] = 'select';
                     obj['values'] = [{ 1: 'true' }, { 0: 'false' }];
-                    obj.operators = ['=', '!=', 'is_null', 'not_null'];
+                    _.extend(obj, this.getOperator("boolean"));
                     return obj;
                 }
+                /* Status / __state */
                 if (isSystemAttr && attrObj.name === "Status" || isSystemAttr && attrObj.name === "__state") {
                     obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (enum)";
                     obj['input'] = 'select';
                     obj['values'] = ['ACTIVE', 'DELETED'];
-                    obj.operators = ['=', '!='];
+                    _.extend(obj, this.getOperator("boolean", true));
+                    return obj;
+                }
+                /* __classificationNames / __propagatedClassificationNames */
+                if (isSystemAttr && attrObj.name === "__classificationNames" || attrObj.name === "__propagatedClassificationNames") {
+                    obj["plugin"] = "select2";
+                    obj["input"] = 'select';
+                    obj["plugin_config"] = {
+                        placeholder: "Select classfication",
+                        tags: true,
+                        multiple: false,
+                        data: this.classificationDefCollection.fullCollection.models.map(function(o) { return { "id": o.get("name"), "text": o.get("name") } })
+                    };
+                    obj["valueSetter"] = function(rule) {
+                        if (rule && !_.isEmpty(rule.value)) {
+                            var selectEl = rule.$el.find('.rule-value-container select')
+                            var valFound = that.classificationDefCollection.fullCollection.find(function(o) {
+                                return o.get("name") === rule.value
+                            })
+                            if (valFound) {
+                                selectEl.val(rule.value).trigger("change");
+                            } else {
+                                var newOption = new Option(rule.value, rule.value, false, false);
+                                selectEl.append(newOption).val(rule.value);
+                            }
+                        }
+                    };
+                    _.extend(obj, this.getOperator("string"));
                     return obj;
                 }
+                /* __customAttributes */
+                if (isSystemAttr && attrObj.name === "__customAttributes") {
+                    obj["input"] = function(rule) {
+                        return rule.operator.nb_inputs ? that.getUserDefineInput() : null
+                    }
+                    obj["valueGetter"] = function(rule) {
+                        if (rule.operator.type === "contains") {
+                            var $el = rule.$el.find('.rule-value-container'),
+                                key = $el.find("[data-type='key']").val(),
+                                val = $el.find("[data-type='value']").val();
+                            if (!_.isEmpty(key) && !_.isEmpty(val)) {
+                                return key + "=" + val;
+                            } else {
+                                return new Error("Key & Value is Required");
+                            }
+                        }
+                    }
+                    obj["valueSetter"] = function(rule) {
+                        if (!rule.$el.hasClass("user-define")) {
+                            rule.$el.addClass("user-define");
+                        }
+                        if (rule.value && !(rule.value instanceof Error)) {
+                            var $el = rule.$el.find('.rule-value-container'),
+                                value = rule.value.split("=");
+                            if (value) {
+                                $el.find("[data-type='key']").val(value[0]),
+                                    $el.find("[data-type='value']").val(value[1]);
+                            }
+                        }
+                    }
 
+                    obj.operators = ['contains', 'is_null', 'not_null'];
+                    return obj;
+                }
+                /* __labels */
+                if (isSystemAttr && attrObj.name === "__labels") {
+                    obj["plugin"] = "select2";
+                    obj["input"] = 'select';
+                    obj["plugin_config"] = {
+                        placeholder: "Enter Label(s)",
+                        tags: true,
+                        "language": {
+                            "noResults": function() { return ''; }
+                        },
+                        multiple: false
+                    };
+                    obj["valueSetter"] = function(rule) {
+                        if (rule && !_.isEmpty(rule.value)) {
+                            var newOption = new Option(rule.value, rule.value, true, false);
+                            return rule.$el.find('.rule-value-container select').append(newOption);
+                        }
+                    }
+                    _.extend(obj, this.getOperator("string"));
+                    return obj;
+                }
+                /* __typeName */
+                if (isSystemAttr && attrObj.name === "__typeName") {
+                    var entityType = [];
+                    that.typeHeaders.fullCollection.each(function(model) {
+                        if (model.get('category') == 'ENTITY') {
+                            entityType.push({
+                                "id": model.get("name"),
+                                "text": model.get("name")
+                            })
+                        }
+                    });
+                    obj["plugin"] = "select2";
+                    obj["input"] = 'select';
+                    obj["plugin_config"] = {
+                        placeholder: "Select type",
+                        tags: true,
+                        multiple: false,
+                        data: entityType
+                    };
+                    obj["valueSetter"] = function(rule) {
+                        if (rule && !_.isEmpty(rule.value)) {
+                            var selectEl = rule.$el.find('.rule-value-container select')
+                            var valFound = that.typeHeaders.fullCollection.find(function(o) {
+                                return o.get("name") === rule.value
+                            })
+                            if (valFound) {
+                                selectEl.val(rule.value).trigger("change");
+                            } else {
+                                var newOption = new Option(rule.value, rule.value, false, false);
+                                selectEl.append(newOption).val(rule.value);
+                            }
+                        }
+                    };
+                    _.extend(obj, this.getOperator("string"));
+                    return obj;
+                }
                 if (obj.type === "date") {
                     obj['plugin'] = 'daterangepicker';
                     obj['plugin_config'] = {
@@ -185,6 +341,23 @@ define(['require',
                         filters.push(returnObj);
                     }
                 });
+                var sortMap = {
+                    "__guid": 1,
+                    "__typeName": 2,
+                    "__timestamp": 3,
+                    "__modificationTimestamp": 4,
+                    "__createdBy": 5,
+                    "__modifiedBy": 6,
+                    "__isIncomplete": 7,
+                    "__state": 8,
+                    "__classificationNames": 9,
+                    "__propagatedClassificationNames": 10,
+                    "__labels": 11,
+                    "__customAttributes": 12,
+                }
+                this.systemAttrArr = _.sortBy(this.systemAttrArr, function(obj) {
+                    return sortMap[obj.name]
+                })
                 _.each(this.systemAttrArr, function(obj) {
                     var returnObj = that.getObjDef(obj, rules_widgets, isGroupView, 'Select System Attribute', true);
                     if (returnObj) {
@@ -201,6 +374,23 @@ define(['require',
                         conditions: ['AND', 'OR'],
                         allow_groups: true,
                         allow_empty: true,
+                        templates: {
+                            rule: '<div id="{{= it.rule_id }}" class="rule-container"> \
+                                      <div class="values-box"><div class="rule-filter-container"></div> \
+                                      <div class="rule-operator-container"></div> \
+                                      <div class="rule-value-container"></div></div> \
+                                      <div class="action-box"><div class="rule-header"> \
+                                        <div class="btn-group rule-actions"> \
+                                          <button type="button" class="btn btn-xs btn-danger" data-delete="rule"> \
+                                            <i class="{{= it.icons.remove_rule }}"></i> \
+                                          </button> \
+                                        </div> \
+                                      </div> </div>\
+                                      {{? it.settings.display_errors }} \
+                                        <div class="error-container"><i class="{{= it.icons.error }}"></i>&nbsp;<span></span></div> \
+                                      {{?}} \
+                                </div>'
+                        },
                         operators: [
                             { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
                             { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
@@ -227,7 +417,25 @@ define(['require',
                             error: 'fa fa-exclamation-triangle'
                         },
                         rules: rules_widgets
+                    }).on("afterCreateRuleInput.queryBuilder", function(e, rule) {
+                        rule.error = null;
+                        if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") {
+                            rule.$el.addClass("user-define");
+                        } else if (rule.$el.hasClass("user-define")) {
+                            rule.$el.removeClass("user-define");
+                        }
+                    }).on('validationError.queryBuilder', function(e, rule, error, value) {
+                        // never display error for my custom filter
+                        var errorMsg = error[0];
+                        if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) {
+                            errorMsg = that.queryBuilderLang.errors[errorMsg];
+                        }
+                        rule.$el.find(".error-container span").html(errorMsg);
                     });
+                    var queryBuilderEl = that.ui.builder.data("queryBuilder");
+                    if (queryBuilderEl && queryBuilderEl.lang) {
+                        this.queryBuilderLang = queryBuilderEl.lang;
+                    }
                     this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-left');
                 } else {
                     this.ui.builder.html('<h4>No Attributes are available !</h4>')
diff --git a/dashboardv2/public/js/views/search/SearchQueryView.js b/dashboardv2/public/js/views/search/SearchQueryView.js
index 6e5f1a4..692a9df 100644
--- a/dashboardv2/public/js/views/search/SearchQueryView.js
+++ b/dashboardv2/public/js/views/search/SearchQueryView.js
@@ -89,7 +89,8 @@ define(['require',
                     entityDefCollection: this.entityDefCollection,
                     enumDefCollection: this.enumDefCollection,
                     classificationDefCollection: this.classificationDefCollection,
-                    searchTableFilters: this.searchTableFilters
+                    searchTableFilters: this.searchTableFilters,
+                    typeHeaders: this.typeHeaders
                 }
 
                 if (this.tag) {
diff --git a/dashboardv2/public/js/views/search/SearchResultLayoutView.js b/dashboardv2/public/js/views/search/SearchResultLayoutView.js
index e69c7c4..a94a0f7 100644
--- a/dashboardv2/public/js/views/search/SearchResultLayoutView.js
+++ b/dashboardv2/public/js/views/search/SearchResultLayoutView.js
@@ -807,6 +807,9 @@ define(['require',
                                     }
                                     return;
                                 }
+                                if (key == "__historicalGuids" || key == "__classificationsText" || key == "__classificationNames" || key == "__propagatedClassificationNames") {
+                                    return;
+                                }
                                 col[obj.name] = {
                                     label: Enums.systemAttributes[obj.name] ? Enums.systemAttributes[obj.name] : _.escape(obj.name).capitalize(),
                                     cell: "Html",
@@ -826,6 +829,28 @@ define(['require',
                                                     'valueObject': {},
                                                     'isTable': false
                                                 };
+                                                if (key == "__labels") {
+                                                    var values = modelObj.attributes[key] ? modelObj.attributes[key].split("|") : null,
+                                                        valueOfArray = [];
+                                                    if (values) {
+                                                        if (values[values.length - 1] === "") { values.pop(); }
+                                                        if (values[0] === "") { values.shift(); }
+                                                        _.each(values, function(names) {
+                                                            valueOfArray.push('<span class="json-string"><a class="btn btn-action btn-sm btn-blue btn-icon" ><span title="" data-original-title="' + names + '" >' + names + '</span></a></span>');
+                                                        });
+                                                        return valueOfArray.join(' ');
+                                                    }
+                                                }
+                                                if (key == "__customAttributes") {
+                                                    var customAttributes = modelObj.attributes[key] ? JSON.parse(modelObj.attributes[key]) : null,
+                                                        valueOfArray = [];
+                                                    if (customAttributes) {
+                                                        _.each(Object.keys(customAttributes), function(value, index) {
+                                                            valueOfArray.push('<span class="json-string"><a class="btn btn-action btn-sm btn-blue btn-icon" ><span title="" data-original-title="' + value + ' : ' + Object.values(customAttributes)[index] + '" ><span>' + value + '</span> : <span>' + Object.values(customAttributes)[index] + '</span></span></a></span>');
+                                                        });
+                                                        return valueOfArray.join(' ');
+                                                    }
+                                                }
                                                 tempObj.valueObject[key] = modelObj.attributes[key];
                                                 var tablecolumn = CommonViewFunction.propertyTable(tempObj);
                                                 if (_.isArray(modelObj.attributes[key])) {
diff --git a/dashboardv3/public/css/scss/override.scss b/dashboardv3/public/css/scss/override.scss
index ab7d423..ab4d601 100644
--- a/dashboardv3/public/css/scss/override.scss
+++ b/dashboardv3/public/css/scss/override.scss
@@ -246,6 +246,21 @@
 .query-builder {
     .rule-container {
         margin: 6px 0;
+        display: flex;
+        flex-wrap: wrap;
+
+        .values-box {
+            display: flex;
+            flex-grow: 1;
+            width: 100%;
+            padding-right: 26px;
+        }
+
+        .action-box {
+            position: absolute;
+            right: 4px;
+            top: calc(50% - 18px);
+        }
 
         .rule-header {
             .rule-actions {
@@ -253,24 +268,34 @@
             }
         }
 
+        .error-container {
+            color: $color_trinidad_approx;
+        }
+
         .rule-value-container {
             display: inline-block !important;
+            border-left: none;
+            width: calc(65% - 105px);
 
             .form-control {
-                width: 220px !important;
+                width: 100% !important;
                 padding: 6px 12px !important;
             }
         }
 
         .rule-filter-container {
+            width: 35%;
+
             .form-control {
-                width: 200px !important;
+                width: 100% !important;
             }
         }
 
         .rule-operator-container {
+            width: 105px;
+
             .form-control {
-                width: auto !important;
+                width: 100% !important;
             }
         }
     }
diff --git a/dashboardv3/public/css/scss/search.scss b/dashboardv3/public/css/scss/search.scss
index a995ad5..3ac2769 100644
--- a/dashboardv3/public/css/scss/search.scss
+++ b/dashboardv3/public/css/scss/search.scss
@@ -425,10 +425,10 @@ hr.hr-filter {
                 padding: 0px 15px;
             }
 
-            .attribute-result-footer,
-            .attribute-edit-footer {
-                display: inline-block;
-            }
+            // .attribute-result-footer,
+            // .attribute-edit-footer {
+            //     display: inline-block;
+            // }
         }
 
         .filter-box {
@@ -477,4 +477,49 @@ hr.hr-filter {
     .attributePopOver {
         min-height: 190px;
     }
+}
+
+.query-builder {
+    .rule-container {
+        &.user-define {
+            .values-box {
+                display: flex;
+                flex-wrap: wrap;
+
+                .rule-filter-container {
+                    width: 200px;
+                }
+
+                .rule-value-container {
+                    width: 100%;
+                    padding: 7px 0px 0px 0px;
+                }
+            }
+        }
+
+        .rule-value-container {
+            &>table.custom-table {
+                tr {
+                    display: none;
+
+                    &.custom-tr {
+                        display: table-row;
+
+                        td.custom-col-1 {
+                            width: 48%;
+
+                            .errorMsg {
+                                display: none;
+                            }
+                        }
+                    }
+                }
+
+                input,
+                textarea {
+                    width: 100% !important;
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/dashboardv3/public/js/templates/search/UserDefine_tmpl.html b/dashboardv3/public/js/templates/search/UserDefine_tmpl.html
new file mode 100644
index 0000000..8868e90
--- /dev/null
+++ b/dashboardv3/public/js/templates/search/UserDefine_tmpl.html
@@ -0,0 +1,44 @@
+<!--
+ * 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.
+-->
+<table class="custom-table">
+    <tbody>
+        <tr class="custom-tr">
+            <td class="custom-col-1">
+                <input placeholder="key" type="text" data-type="key" data-index="0" class="form-control" value="">
+                <p class="errorMsg"></p>
+            </td>
+            <td class="custom-col-0"> : </td>
+            <td class="custom-col-1">
+                <textarea placeholder="value" data-type="value" data-index="0" class="form-control"></textarea>
+                <p class="errorMsg"></p>
+            </td>
+            <!-- <td class="custom-col-2">
+                <button class="btn btn-default btn-sm" title="" data-index="0" data-id="deleteUserDefineItem">
+                    <i class="fa fa-minus"> </i>
+                </button>
+                <button class="btn btn-default btn-sm" title="" data-index="0" data-id="addUserDefineItem">
+                    <i class="fa fa-plus"> </i>
+                </button>
+            </td> -->
+        </tr>
+        <tr>
+            <td colspan="4">
+                <p class="errorMsg" data-id="charSupportMsg"></p>
+            </td>
+        </tr>
+    </tbody>
+</table>
\ No newline at end of file
diff --git a/dashboardv3/public/js/utils/Enums.js b/dashboardv3/public/js/utils/Enums.js
index e0486d3..82e11ca 100644
--- a/dashboardv3/public/js/utils/Enums.js
+++ b/dashboardv3/public/js/utils/Enums.js
@@ -194,8 +194,8 @@ define(['require'], function(require) {
     };
     Enums.systemAttributes = {
         "__classificationNames": "Classification(s)",
-        "__createdBy": "Created By",
-        "__customAttributes": "User-defined attributes",
+        "__createdBy": "Created By User",
+        "__customAttributes": "User-defined Properties",
         "__guid": "Guid",
         "__isIncomplete": "IsIncomplete",
         "__labels": "Label(s)",
@@ -208,7 +208,7 @@ define(['require'], function(require) {
     };
     Enums.__isIncomplete = {
         0: "false",
-        1: "rue"
-    }
+        1: "true"
+    };
     return Enums;
 });
\ No newline at end of file
diff --git a/dashboardv3/public/js/views/entity/EntityUserDefineView.js b/dashboardv3/public/js/views/entity/EntityUserDefineView.js
index 61e603e..1cb0d8c 100644
--- a/dashboardv3/public/js/views/entity/EntityUserDefineView.js
+++ b/dashboardv3/public/js/views/entity/EntityUserDefineView.js
@@ -54,7 +54,7 @@ define(['require',
         },
         initialize: function(options) {
             _.extend(this, _.pick(options, 'entity', 'customFilter'));
-            this.userDefineAttr = this.entity.customAttributes || [];
+            this.userDefineAttr = this.entity && this.entity.customAttributes || [];
             this.initialCall = false;
             this.swapItem = false, this.saveAttrItems = false;
             this.readOnlyEntity = this.customFilter === undefined ? Enums.entityStateReadOnly[this.entity.status] : this.customFilter;
diff --git a/dashboardv3/public/js/views/search/QueryBuilderView.js b/dashboardv3/public/js/views/search/QueryBuilderView.js
index 39bb242..cca7992 100644
--- a/dashboardv3/public/js/views/search/QueryBuilderView.js
+++ b/dashboardv3/public/js/views/search/QueryBuilderView.js
@@ -19,19 +19,20 @@
 define(['require',
     'backbone',
     'hbs!tmpl/search/QueryBuilder_tmpl',
+    'hbs!tmpl/search/UserDefine_tmpl',
     'utils/Utils',
     'utils/CommonViewFunction',
     'utils/Enums',
     'query-builder',
     'daterangepicker'
-], function(require, Backbone, QueryBuilder_Tmpl, Utils, CommonViewFunction, Enums) {
+], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums) {
 
     var QueryBuilderView = Backbone.Marionette.LayoutView.extend(
         /** @lends QueryBuilderView */
         {
             _viewName: 'QueryBuilderView',
 
-            template: QueryBuilder_Tmpl,
+            template: QueryBuilderTmpl,
 
 
 
@@ -53,13 +54,22 @@ define(['require',
              * @constructs
              */
             initialize: function(options) {
-                _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'tag', 'searchTableFilters', 'systemAttrArr'));
+                _.extend(this, _.pick(options,
+                    'attrObj',
+                    'value',
+                    'typeHeaders',
+                    'entityDefCollection',
+                    'enumDefCollection',
+                    'classificationDefCollection',
+                    'tag',
+                    'searchTableFilters',
+                    'systemAttrArr'));
                 this.attrObj = _.sortBy(this.attrObj, 'name');
-                this.systemAttrArr = _.sortBy(this.systemAttrArr, 'name');
+                //this.systemAttrArr = _.sortBy(this.systemAttrArr, 'name');
                 this.filterType = this.tag ? 'tagFilters' : 'entityFilters';
             },
             bindEvents: function() {},
-            getOperator: function(type) {
+            getOperator: function(type, skipDefault) {
                 var obj = {
                     operators: null
                 }
@@ -72,7 +82,7 @@ define(['require',
                 if (type === "enum" || type === "boolean") {
                     obj.operators = ['=', '!='];
                 }
-                if (obj.operators) {
+                if (_.isEmpty(skipDefault) && obj.operators) {
                     obj.operators = obj.operators.concat(['is_null', 'not_null']);
                 }
                 return obj;
@@ -83,31 +93,178 @@ define(['require',
                 }
                 return false;
             },
+            getUserDefineInput: function() {
+                return UserDefineTmpl();
+            },
             getObjDef: function(attrObj, rules, isGroup, groupType, isSystemAttr) {
+                var that = this;
                 if (attrObj.name === "__classificationsText" || attrObj.name === "__historicalGuids") {
                     return;
                 }
+                var getLableWithType = function(label, name) {
+                    if (name === "__classificationNames" || name === "__customAttributes" || name === "__labels" || name === "__propagatedClassificationNames") {
+                        return label;
+                    } else {
+                        return label + " (" + attrObj.typeName + ")";
+                    }
+
+                }
+                var label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize()));
                 var obj = {
                     id: attrObj.name,
-                    label: (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (" + attrObj.typeName + ")",
-                    type: _.escape(attrObj.typeName)
+                    label: getLableWithType(label, attrObj.name),
+                    plainLabel: label,
+                    type: _.escape(attrObj.typeName),
+                    validation: {
+                        callback: function(value, rule) {
+                            if (rule.operator.nb_inputs === false || !_.isEmpty(value) || !value instanceof Error) {
+                                return true;
+                            } else {
+                                if (value instanceof Error) {
+                                    return value.message; // with params
+                                } else {
+                                    return rule.filter.plainLabel + ' is required'; // with params
+                                }
+                            }
+                        }
+                    }
                 };
                 if (isGroup) {
                     obj.optgroup = groupType;
                 }
+                /* __isIncomplete / IsIncomplete */
                 if (isSystemAttr && attrObj.name === "__isIncomplete" || isSystemAttr && attrObj.name === "IsIncomplete") {
                     obj.type = "boolean";
                     obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (boolean)";
                     obj['input'] = 'select';
                     obj['values'] = [{ 1: 'true' }, { 0: 'false' }];
-                    obj.operators = ['=', '!=', 'is_null', 'not_null'];
+                    _.extend(obj, this.getOperator("boolean"));
                     return obj;
                 }
+                /* Status / __state */
                 if (isSystemAttr && attrObj.name === "Status" || isSystemAttr && attrObj.name === "__state") {
                     obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (enum)";
                     obj['input'] = 'select';
                     obj['values'] = ['ACTIVE', 'DELETED'];
-                    obj.operators = ['=', '!='];
+                    _.extend(obj, this.getOperator("boolean", true));
+                    return obj;
+                }
+                /* __classificationNames / __propagatedClassificationNames */
+                if (isSystemAttr && attrObj.name === "__classificationNames" || attrObj.name === "__propagatedClassificationNames") {
+                    obj["plugin"] = "select2";
+                    obj["input"] = 'select';
+                    obj["plugin_config"] = {
+                        placeholder: "Select classfication",
+                        tags: true,
+                        multiple: false,
+                        data: this.classificationDefCollection.fullCollection.models.map(function(o) { return { "id": o.get("name"), "text": o.get("name") } })
+                    };
+                    obj["valueSetter"] = function(rule) {
+                        if (rule && !_.isEmpty(rule.value)) {
+                            var selectEl = rule.$el.find('.rule-value-container select')
+                            var valFound = that.classificationDefCollection.fullCollection.find(function(o) {
+                                return o.get("name") === rule.value
+                            })
+                            if (valFound) {
+                                selectEl.val(rule.value).trigger("change");
+                            } else {
+                                var newOption = new Option(rule.value, rule.value, false, false);
+                                selectEl.append(newOption).val(rule.value);
+                            }
+                        }
+                    };
+                    _.extend(obj, this.getOperator("string"));
+                    return obj;
+                }
+                /* __customAttributes */
+                if (isSystemAttr && attrObj.name === "__customAttributes") {
+                    obj["input"] = function(rule) {
+                        return rule.operator.nb_inputs ? that.getUserDefineInput() : null
+                    }
+                    obj["valueGetter"] = function(rule) {
+                        if (rule.operator.type === "contains") {
+                            var $el = rule.$el.find('.rule-value-container'),
+                                key = $el.find("[data-type='key']").val(),
+                                val = $el.find("[data-type='value']").val();
+                            if (!_.isEmpty(key) && !_.isEmpty(val)) {
+                                return key + "=" + val;
+                            } else {
+                                return new Error("Key & Value is Required");
+                            }
+                        }
+                    }
+                    obj["valueSetter"] = function(rule) {
+                        if (!rule.$el.hasClass("user-define")) {
+                            rule.$el.addClass("user-define");
+                        }
+                        if (rule.value && !(rule.value instanceof Error)) {
+                            var $el = rule.$el.find('.rule-value-container'),
+                                value = rule.value.split("=");
+                            if (value) {
+                                $el.find("[data-type='key']").val(value[0]),
+                                    $el.find("[data-type='value']").val(value[1]);
+                            }
+                        }
+                    }
+
+                    obj.operators = ['contains', 'is_null', 'not_null'];
+                    return obj;
+                }
+                /* __labels */
+                if (isSystemAttr && attrObj.name === "__labels") {
+                    obj["plugin"] = "select2";
+                    obj["input"] = 'select';
+                    obj["plugin_config"] = {
+                        placeholder: "Enter Label(s)",
+                        tags: true,
+                        "language": {
+                            "noResults": function() { return ''; }
+                        },
+                        multiple: false
+                    };
+                    obj["valueSetter"] = function(rule) {
+                        if (rule && !_.isEmpty(rule.value)) {
+                            var newOption = new Option(rule.value, rule.value, true, false);
+                            return rule.$el.find('.rule-value-container select').append(newOption);
+                        }
+                    }
+                    _.extend(obj, this.getOperator("string"));
+                    return obj;
+                }
+                /* __typeName */
+                if (isSystemAttr && attrObj.name === "__typeName") {
+                    var entityType = [];
+                    that.typeHeaders.fullCollection.each(function(model) {
+                        if (model.get('category') == 'ENTITY') {
+                            entityType.push({
+                                "id": model.get("name"),
+                                "text": model.get("name")
+                            })
+                        }
+                    });
+                    obj["plugin"] = "select2";
+                    obj["input"] = 'select';
+                    obj["plugin_config"] = {
+                        placeholder: "Select type",
+                        tags: true,
+                        multiple: false,
+                        data: entityType
+                    };
+                    obj["valueSetter"] = function(rule) {
+                        if (rule && !_.isEmpty(rule.value)) {
+                            var selectEl = rule.$el.find('.rule-value-container select')
+                            var valFound = that.typeHeaders.fullCollection.find(function(o) {
+                                return o.get("name") === rule.value
+                            })
+                            if (valFound) {
+                                selectEl.val(rule.value).trigger("change");
+                            } else {
+                                var newOption = new Option(rule.value, rule.value, false, false);
+                                selectEl.append(newOption).val(rule.value);
+                            }
+                        }
+                    };
+                    _.extend(obj, this.getOperator("string"));
                     return obj;
                 }
                 if (obj.type === "date") {
@@ -184,6 +341,23 @@ define(['require',
                         filters.push(returnObj);
                     }
                 });
+                var sortMap = {
+                    "__guid": 1,
+                    "__typeName": 2,
+                    "__timestamp": 3,
+                    "__modificationTimestamp": 4,
+                    "__createdBy": 5,
+                    "__modifiedBy": 6,
+                    "__isIncomplete": 7,
+                    "__state": 8,
+                    "__classificationNames": 9,
+                    "__propagatedClassificationNames": 10,
+                    "__labels": 11,
+                    "__customAttributes": 12,
+                }
+                this.systemAttrArr = _.sortBy(this.systemAttrArr, function(obj) {
+                    return sortMap[obj.name]
+                })
                 _.each(this.systemAttrArr, function(obj) {
                     var returnObj = that.getObjDef(obj, rules_widgets, isGroupView, 'Select System Attribute', true);
                     if (returnObj) {
@@ -200,6 +374,23 @@ define(['require',
                         conditions: ['AND', 'OR'],
                         allow_groups: true,
                         allow_empty: true,
+                        templates: {
+                            rule: '<div id="{{= it.rule_id }}" class="rule-container"> \
+                                      <div class="values-box"><div class="rule-filter-container"></div> \
+                                      <div class="rule-operator-container"></div> \
+                                      <div class="rule-value-container"></div></div> \
+                                      <div class="action-box"><div class="rule-header"> \
+                                        <div class="btn-group rule-actions"> \
+                                          <button type="button" class="btn btn-xs btn-danger" data-delete="rule"> \
+                                            <i class="{{= it.icons.remove_rule }}"></i> \
+                                          </button> \
+                                        </div> \
+                                      </div> </div>\
+                                      {{? it.settings.display_errors }} \
+                                        <div class="error-container"><i class="{{= it.icons.error }}"></i>&nbsp;<span></span></div> \
+                                      {{?}} \
+                                </div>'
+                        },
                         operators: [
                             { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
                             { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] },
@@ -226,7 +417,25 @@ define(['require',
                             error: 'fa fa-exclamation-triangle'
                         },
                         rules: rules_widgets
+                    }).on("afterCreateRuleInput.queryBuilder", function(e, rule) {
+                        rule.error = null;
+                        if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") {
+                            rule.$el.addClass("user-define");
+                        } else if (rule.$el.hasClass("user-define")) {
+                            rule.$el.removeClass("user-define");
+                        }
+                    }).on('validationError.queryBuilder', function(e, rule, error, value) {
+                        // never display error for my custom filter
+                        var errorMsg = error[0];
+                        if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) {
+                            errorMsg = that.queryBuilderLang.errors[errorMsg];
+                        }
+                        rule.$el.find(".error-container span").html(errorMsg);
                     });
+                    var queryBuilderEl = that.ui.builder.data("queryBuilder");
+                    if (queryBuilderEl && queryBuilderEl.lang) {
+                        this.queryBuilderLang = queryBuilderEl.lang;
+                    }
                     this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-left');
                 } else {
                     this.ui.builder.html('<h4>No Attributes are available !</h4>')
diff --git a/dashboardv3/public/js/views/search/SearchDefaultLayoutView.js b/dashboardv3/public/js/views/search/SearchDefaultLayoutView.js
index a831d34..707ff14 100644
--- a/dashboardv3/public/js/views/search/SearchDefaultLayoutView.js
+++ b/dashboardv3/public/js/views/search/SearchDefaultLayoutView.js
@@ -55,12 +55,12 @@ define(["require", "backbone", "utils/Globals", "hbs!tmpl/search/SearchDefaultLa
                 var events = {},
                     that = this;
                 events["click " + this.ui.attrFilter] = function(e) {
-                    // this.$('.fa-chevron-right').toggleClass('fa-chevron-down');
+                    if (this.$('.attribute-filter-container').hasClass("hide")) {
+                        this.onClickAttrFilter();
+                    }
                     this.$('.fa-angle-right').toggleClass('fa-angle-down');
                     this.$('.attributeResultContainer').addClass("overlay");
                     this.$('.attribute-filter-container, .attr-filter-overlay').toggleClass('hide');
-                    // this.$('.attribute-filter-container').toggleClass('attribute-filter-container')
-                    this.onClickAttrFilter();
                 };
 
                 events["click " + this.ui.attrApply] = function(e) {
@@ -201,6 +201,7 @@ define(["require", "backbone", "utils/Globals", "hbs!tmpl/search/SearchDefaultLa
             manualRender: function(options) {
                 _.extend(this.options, options);
                 this.updateView();
+                this.onClickAttrFilter();
                 this.renderSearchResult();
             },
             renderGlobalSearch: function() {
@@ -226,77 +227,81 @@ define(["require", "backbone", "utils/Globals", "hbs!tmpl/search/SearchDefaultLa
                 }
                 return options.searchTableFilters;
             },
-            onClickAttrFilter: function(filterType) {
+            onClickAttrFilter: function() {
                 var that = this,
                     obj = {
                         value: that.options.value,
                         searchVent: that.options.searchVent,
                         entityDefCollection: that.options.entityDefCollection,
                         enumDefCollection: that.options.enumDefCollection,
+                        typeHeaders: that.options.typeHeaders,
                         classificationDefCollection: that.options.classificationDefCollection,
                         searchTableFilters: that.checkEntityFilter(that.options)
                     };
-                this.ui.checkDeletedEntity.prop('checked', this.options.value.includeDE ? this.options.value.includeDE : false);
-                this.ui.checkSubClassification.prop('checked', this.options.value.excludeSC ? this.options.value.excludeSC : false);
-                this.ui.checkSubType.prop('checked', this.options.value.excludeST ? this.options.value.excludeST : false);
+                if (that.options.value) {
+                    this.ui.checkDeletedEntity.prop('checked', this.options.value.includeDE ? this.options.value.includeDE : false);
+                    this.ui.checkSubClassification.prop('checked', this.options.value.excludeSC ? this.options.value.excludeSC : false);
+                    this.ui.checkSubType.prop('checked', this.options.value.excludeST ? this.options.value.excludeST : false);
 
-                if (that.options.value.tag && that.options.value.type) {
-                    this.$('.attribute-filter-container').removeClass('no-attr');
-                    this.ui.classificationRegion.show();
-                    this.ui.entityRegion.show();
-                } else {
-                    if (!that.options.value.tag && !that.options.value.type) {
-                        this.$('.attribute-filter-container').addClass('no-attr');
+                    if (that.options.value.tag && that.options.value.type) {
+                        this.$('.attribute-filter-container').removeClass('no-attr');
+                        this.ui.classificationRegion.show();
+                        this.ui.entityRegion.show();
+                    } else {
+                        if (!that.options.value.tag && !that.options.value.type) {
+                            this.$('.attribute-filter-container').addClass('no-attr');
+                        }
+                        this.ui.entityRegion.hide();
+                        this.ui.classificationRegion.hide();
                     }
-                    this.ui.entityRegion.hide();
-                    this.ui.classificationRegion.hide();
-                }
-                if (that.options.value.tag) {
-                    this.ui.classificationRegion.show();
-                    // this.ui.entityRegion.hide();
-                    var attrTagObj = that.options.classificationDefCollection.fullCollection.find({ name: that.options.value.tag });
-                    if (attrTagObj) {
-                        attrTagObj = Utils.getNestedSuperTypeObj({
-                            data: attrTagObj.toJSON(),
-                            collection: that.options.classificationDefCollection,
-                            attrMerge: true,
-                        });
-                        this.tagAttributeLength = attrTagObj.length;
+                    if (that.options.value.tag) {
+                        this.ui.classificationRegion.show();
+                        // this.ui.entityRegion.hide();
+                        var attrTagObj = that.options.classificationDefCollection.fullCollection.find({ name: that.options.value.tag });
+                        if (attrTagObj) {
+                            attrTagObj = Utils.getNestedSuperTypeObj({
+                                data: attrTagObj.toJSON(),
+                                collection: that.options.classificationDefCollection,
+                                attrMerge: true,
+                            });
+                            this.tagAttributeLength = attrTagObj.length;
+                        }
+                        if (Globals[that.options.value.tag] || Globals[Enums.addOnClassification[0]]) {
+                            obj.systemAttrArr = (Globals[that.options.value.tag] || Globals[Enums.addOnClassification[0]]).attributeDefs;
+                            this.tagAttributeLength = obj.systemAttrArr.length;
+                        }
+                        this.renderQueryBuilder(_.extend({}, obj, {
+                            tag: true,
+                            type: false,
+                            attrObj: attrTagObj
+                        }), this.RQueryBuilderClassification);
+                        this.ui.classificationName.html(that.options.value.tag);
                     }
-                    if (Globals[that.options.value.tag] || Globals[Enums.addOnClassification[0]]) {
-                        obj.systemAttrArr = (Globals[that.options.value.tag] || Globals[Enums.addOnClassification[0]]).attributeDefs;
-                        this.tagAttributeLength = obj.systemAttrArr.length;
+                    if (that.options.value.type) {
+                        this.ui.entityRegion.show();
+                        var attrTypeObj = that.options.entityDefCollection.fullCollection.find({ name: that.options.value.type });
+                        if (attrTypeObj) {
+                            attrTypeObj = Utils.getNestedSuperTypeObj({
+                                data: attrTypeObj.toJSON(),
+                                collection: that.options.entityDefCollection,
+                                attrMerge: true
+                            });
+                            this.entityAttributeLength = attrTypeObj.length;
+                        }
+                        if (Globals[that.options.value.type] || Globals[Enums.addOnEntities[0]]) {
+                            obj.systemAttrArr = (Globals[that.options.value.type] || Globals[Enums.addOnEntities[0]]).attributeDefs;
+                            this.entityAttributeLength = obj.systemAttrArr.length;
+                        }
+                        this.renderQueryBuilder(_.extend({}, obj, {
+                            tag: false,
+                            type: true,
+                            attrObj: attrTypeObj
+                        }), this.RQueryBuilderEntity);
+
+                        this.ui.entityName.html(that.options.value.type);
                     }
-                    this.renderQueryBuilder(_.extend({}, obj, {
-                        tag: true,
-                        type: false,
-                        attrObj: attrTagObj
-                    }), this.RQueryBuilderClassification);
-                    this.ui.classificationName.html(that.options.value.tag);
                 }
-                if (that.options.value.type) {
-                    this.ui.entityRegion.show();
-                    var attrTypeObj = that.options.entityDefCollection.fullCollection.find({ name: that.options.value.type });
-                    if (attrTypeObj) {
-                        attrTypeObj = Utils.getNestedSuperTypeObj({
-                            data: attrTypeObj.toJSON(),
-                            collection: that.options.entityDefCollection,
-                            attrMerge: true
-                        });
-                        this.entityAttributeLength = attrTypeObj.length;
-                    }
-                    if (Globals[that.options.value.type] || Globals[Enums.addOnEntities[0]]) {
-                        obj.systemAttrArr = (Globals[that.options.value.type] || Globals[Enums.addOnEntities[0]]).attributeDefs;
-                        this.entityAttributeLength = obj.systemAttrArr.length;
-                    }
-                    this.renderQueryBuilder(_.extend({}, obj, {
-                        tag: false,
-                        type: true,
-                        attrObj: attrTypeObj
-                    }), this.RQueryBuilderEntity);
 
-                    this.ui.entityName.html(that.options.value.type);
-                }
             },
             okAttrFilterButton: function(e) {
                 var isTag,
@@ -349,7 +354,7 @@ define(["require", "backbone", "utils/Globals", "hbs!tmpl/search/SearchDefaultLa
                         that.options.value.includeDE = (obj.value === "ACTIVE" && obj.operator === "=") || (obj.value === "DELETED" && obj.operator === "!=") ? false : true;
                     }
                     if (_.has(obj, "condition")) {
-                        return this.getIdFromRuleObj(obj);
+                        return that.getIdFromRuleObj(obj);
                     } else {
                         return col.push(obj.id);
                     }
diff --git a/dashboardv3/public/js/views/search/SearchResultLayoutView.js b/dashboardv3/public/js/views/search/SearchResultLayoutView.js
index 4d58fad..f11d903 100644
--- a/dashboardv3/public/js/views/search/SearchResultLayoutView.js
+++ b/dashboardv3/public/js/views/search/SearchResultLayoutView.js
@@ -819,6 +819,9 @@ define(['require',
                                     }
                                     return;
                                 }
+                                if (key == "__historicalGuids" || key == "__classificationsText" || key == "__classificationNames" || key == "__propagatedClassificationNames") {
+                                    return;
+                                }
                                 col[obj.name] = {
                                     label: Enums.systemAttributes[obj.name] ? Enums.systemAttributes[obj.name] : _.escape(obj.name).capitalize(),
                                     cell: "Html",
@@ -838,6 +841,28 @@ define(['require',
                                                     'valueObject': {},
                                                     'isTable': false
                                                 };
+                                                if (key == "__labels") {
+                                                    var values = modelObj.attributes[key] ? modelObj.attributes[key].split("|") : null,
+                                                        valueOfArray = [];
+                                                    if (values) {
+                                                        if (values[values.length - 1] === "") { values.pop(); }
+                                                        if (values[0] === "") { values.shift(); }
+                                                        _.each(values, function(names) {
+                                                            valueOfArray.push('<span class="json-string"><a class="btn btn-action btn-sm btn-blue btn-icon" ><span title="" data-original-title="' + names + '" >' + names + '</span></a></span>');
+                                                        });
+                                                        return valueOfArray.join(' ');
+                                                    }
+                                                }
+                                                if (key == "__customAttributes") {
+                                                    var customAttributes = modelObj.attributes[key] ? JSON.parse(modelObj.attributes[key]) : null,
+                                                        valueOfArray = [];
+                                                    if (customAttributes) {
+                                                        _.each(Object.keys(customAttributes), function(value, index) {
+                                                            valueOfArray.push('<span class="json-string"><a class="btn btn-action btn-sm btn-blue btn-icon" ><span title="" data-original-title="' + value + ' : ' + Object.values(customAttributes)[index] + '" ><span>' + value + '</span> : <span>' + Object.values(customAttributes)[index] + '</span></span></a></span>');
+                                                        });
+                                                        return valueOfArray.join(' ');
+                                                    }
+                                                }
                                                 tempObj.valueObject[key] = modelObj.attributes[key];
                                                 var tablecolumn = CommonViewFunction.propertyTable(tempObj);
                                                 if (_.isArray(modelObj.attributes[key])) {


[atlas] 02/02: ATLAS-3599 : Beta UI: While Saving search , limit and offset are not set properly when using Beta UI.

Posted by kb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kbhatt pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/atlas.git

commit 385068418fdc5c26f3d7233dbc08e2b2b3db2ca9
Author: kevalbhatt <kb...@apache.org>
AuthorDate: Tue Jan 28 16:25:28 2020 +0530

    ATLAS-3599 : Beta UI: While Saving search , limit and offset are not set properly when using Beta UI.
    
    (cherry picked from commit b3563fd319fa530021cb7358c1cc232f06bda24a)
---
 .../search/tree/CustomFilterTreeLayoutView.js      | 28 +++++++++++++++-------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/dashboardv3/public/js/views/search/tree/CustomFilterTreeLayoutView.js b/dashboardv3/public/js/views/search/tree/CustomFilterTreeLayoutView.js
index d4f3d19..1c44669 100644
--- a/dashboardv3/public/js/views/search/tree/CustomFilterTreeLayoutView.js
+++ b/dashboardv3/public/js/views/search/tree/CustomFilterTreeLayoutView.js
@@ -354,15 +354,18 @@ define([
                             entityDefCollection: that.entityDefCollection
                         });
                     searchType === 'ADVANCED' ? that.isBasic = false : that.isBasic = true;
-                    _.extend({}, this.options.value, params),
+                    _.extend({}, this.options.value, params);
+                    // Utils.notifyInfo({
+                    //     content: "Saved values are selected."
+                    // })
 
-                        Utils.setUrl({
-                            url: '#!/search/searchResult',
-                            urlParams: _.extend({}, { 'searchType': that.isBasic ? 'basic' : 'dsl', 'isCF': true }, params),
-                            mergeBrowserUrl: false,
-                            trigger: true,
-                            updateTabState: true
-                        });
+                    Utils.setUrl({
+                        url: '#!/search/searchResult',
+                        urlParams: _.extend({}, { 'searchType': that.isBasic ? 'basic' : 'dsl', 'isCF': true }, params),
+                        mergeBrowserUrl: false,
+                        trigger: true,
+                        updateTabState: true
+                    });
                 }
 
             } else {
@@ -447,11 +450,18 @@ define([
             var value = this.getValue();
             if (value && (value.type || value.tag || value.query || value.term)) {
                 value.searchType == "basic" ? this.isBasic = true : this.isBasic = false;
+                var urlObj = Utils.getUrlState.getQueryParams();
+                if (urlObj) {
+                    // includeDE value in because we need to send "true","false" to the server.
+                    urlObj.includeDE = urlObj.includeDE == "true" ? true : false;
+                    urlObj.excludeSC = urlObj.excludeSC == "true" ? true : false;
+                    urlObj.excludeST = urlObj.excludeST == "true" ? true : false;
+                }
                 this.customFilterSwitchBtnUpdate();
                 this.callSaveModalLayoutView({
                     'collection': this.isBasic ? this.saveSearchBaiscCollection.fullCollection : this.saveSearchAdvanceCollection.fullCollection,
                     getValue: function() {
-                        return value
+                        return _.extend({}, value, urlObj);
                     },
                     'isBasic': this.isBasic
                 });