Repository: atlas
Updated Branches:
  refs/heads/branch-1.0 2f7ad90e3 -> 96de07966


ATLAS-2979: Added service type dropdown to filter entitydef type

Signed-off-by: Sarath Subramanian <ssubraman...@hortonworks.com>
(cherry picked from commit 6ed883b3dfc74fd86b81f1bb0325a05a88e9e5b2)


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/96de0796
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/96de0796
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/96de0796

Branch: refs/heads/branch-1.0
Commit: 96de07966095ce98b3e8a0d14ccd4a19ec96ff12
Parents: 2f7ad90
Author: Abhishek Kadam <abhishek.kada...@gmail.com>
Authored: Fri Dec 21 11:43:31 2018 -0800
Committer: Sarath Subramanian <ssubraman...@hortonworks.com>
Committed: Fri Dec 21 11:48:38 2018 -0800

----------------------------------------------------------------------
 dashboardv2/public/css/scss/search.scss         | 90 ++++++++++++++++++++
 dashboardv2/public/js/utils/Overrides.js        | 89 +++++++++++++++++++
 .../public/js/views/search/SearchLayoutView.js  | 66 ++++++++++----
 3 files changed, 227 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/96de0796/dashboardv2/public/css/scss/search.scss
----------------------------------------------------------------------
diff --git a/dashboardv2/public/css/scss/search.scss 
b/dashboardv2/public/css/scss/search.scss
index 0f9cb1c..0bb8781 100644
--- a/dashboardv2/public/css/scss/search.scss
+++ b/dashboardv2/public/css/scss/search.scss
@@ -139,4 +139,94 @@ $color_celeste_approx: #1D1F2B;
             margin: 0px;
         }
     }
+}
+
+.typeFilter {
+    .dropdown {
+        span.type-clear-btn {
+            position: absolute;
+            color: #444444;
+            font-size: 8px;
+            right: 23px;
+            top: 12px;
+            cursor: pointer;
+        }
+    }
+    button.dropdown-toggle {
+        width: 99.5%;
+        text-align: left;
+        background-color: white;
+        color: $color_star_dust_approx;
+        border: $color_star_dust_approx;
+        &:hover {
+            color: $color_star_dust_approx !important;
+            border: $color_star_dust_approx !important;
+        }
+    }
+}
+
+ul.type-filter-ul {
+    color: black;
+    padding: 10px;
+    max-height: 415px;
+    overflow: auto;
+    width: 100%;
+    padding-top: 0px;
+    margin-bottom: 0px;
+    li {
+        padding: 2px;
+    }
+    .typeLi li {
+        padding: 3px;
+        background-color: #f7fbff;
+        margin: 3px;
+        border: 1px solid #dbd6d6;
+        border-radius: 4px;
+        &:hover {
+            color: $white;
+            background-color: $color_star_dust_approx;
+            cursor: pointer;
+        }
+        &.active {
+            background-color: #37bb9b;
+            color: white;
+        }
+    }
+    .filterLi li {
+        padding: 2px;
+        margin: 4px;
+    }
+}
+
+.dark-text {
+    color: black;
+}
+
+.type-filter-dropdown {
+    position: absolute;
+    top: 5px;
+    background-color: #323544;
+}
+
+.filter-sticky-div {
+    text-align: center;
+    position: sticky;
+    position: -webkit-sticky;
+    top: 0px;
+    background-color: white;
+    padding-top: 8px;
+    & .row {
+        margin-right: -10px;
+        margin-left: -10px;
+    }
+    & input.form-control {
+        border: 1px #c9c9c9 solid;
+    }
+}
+
+hr.hr-filter {
+    margin-top: 7px;
+    margin-bottom: 7px;
+    border: 0;
+    border-top: 1px solid #bdc3c7;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/96de0796/dashboardv2/public/js/utils/Overrides.js
----------------------------------------------------------------------
diff --git a/dashboardv2/public/js/utils/Overrides.js 
b/dashboardv2/public/js/utils/Overrides.js
index 44c277d..b3b591c 100644
--- a/dashboardv2/public/js/utils/Overrides.js
+++ b/dashboardv2/public/js/utils/Overrides.js
@@ -133,6 +133,95 @@ define(['require', 'utils/Utils', 'marionette', 
'backgrid', 'asBreadcrumbs', 'jq
         $(this).blur();
     });
 
+    $.fn.select2.amd.define("ServiceTypeFilterDropdownAdapter", [
+            "select2/utils",
+            "select2/dropdown",
+            "select2/dropdown/attachBody",
+            "select2/dropdown/attachContainer",
+            "select2/dropdown/search",
+            "select2/dropdown/minimumResultsForSearch",
+            "select2/dropdown/closeOnSelect",
+        ],
+        function(Utils, Dropdown, AttachBody, AttachContainer, Search, 
MinimumResultsForSearch, CloseOnSelect) {
+
+            // Decorate Dropdown with Search functionalities
+            var dropdownWithSearch = Utils.Decorate(Utils.Decorate(Dropdown, 
CloseOnSelect), Search);
+
+            dropdownWithSearch.prototype.render = function() {
+                // Copy and modify default search render method
+                var $rendered = Dropdown.prototype.render.call(this);
+
+                // Add ability for a placeholder in the search box
+                var placeholder = this.options.get("placeholderForSearch") || 
"";
+                var $search = $(
+                    '<span class="select2-search 
select2-search--dropdown"><div class="row">' +
+                    '<div class="col-md-10"><input 
class="select2-search__field" placeholder="' + placeholder + '" type="search"' +
+                    ' tabindex="-1" autocomplete="off" autocorrect="off" 
autocapitalize="off"' +
+                    ' spellcheck="false" role="textbox" /></div>' +
+                    '<div class="col-md-2"><button type="button" 
style="margin-left: -20px" class="btn btn-action btn-sm filter " title="Entity 
Attribute Filter"><i class="fa fa-filter"></i></button></div>' +
+                    '</div></span>'
+                );
+                if (!this.options.options.getFilterBox) {
+                    throw "In order to render the filter options adapter 
needed getFilterBox function"
+                }
+                var $Filter = $('<ul class="type-filter-ul"></ul>');
+                this.$Filter = $Filter;
+                this.$Filter.append(this.options.options.getFilterBox());
+                this.$Filter.hide();
+
+                this.$searchContainer = $search;
+                if ($Filter.find('input[type="checkbox"]:checked').length) {
+                    $search.find('button.filter').addClass('active');
+                } else {
+                    $search.find('button.filter').removeClass('active');
+                }
+                this.$search = $search.find('input');
+
+                $rendered.prepend($search);
+                $rendered.append($Filter);
+                return $rendered;
+            };
+            var oldDropdownWithSearchBindRef = 
dropdownWithSearch.prototype.bind;
+            dropdownWithSearch.prototype.bind = function(container, 
$container) {
+                var self = this;
+                oldDropdownWithSearchBindRef.call(this, container, $container);
+                var self = this;
+                this.$Filter.on('click', 'li', function() {
+                    var itemCallback = self.options.options.onFilterItemSelect;
+                    itemCallback && itemCallback(this);
+                })
+
+                this.$searchContainer.find('button.filter').click(function() {
+                    container.$dropdown.find('.select2-search').hide(150);
+                    container.$dropdown.find('.select2-results').hide(150);
+                    self.$Filter.html(self.options.options.getFilterBox());
+                    self.$Filter.show();
+                });
+                this.$Filter.on('click', 'button.filterDone', function() {
+                    container.$dropdown.find('.select2-search').show(150);
+                    container.$dropdown.find('.select2-results').show(150);
+                    self.$Filter.hide();
+                    var filterSubmitCallback = 
self.options.options.onFilterSubmit;
+                    filterSubmitCallback && filterSubmitCallback({
+                        filterVal: 
_.map(self.$Filter.find('input[type="checkbox"]:checked'), function(item) {
+                            return $(item).data('value')
+                        })
+                    });
+                });
+                container.$element.on('hideFilter', function() {
+                    container.$dropdown.find('.select2-search').show();
+                    container.$dropdown.find('.select2-results').show();
+                    self.$Filter.hide();
+                });
+
+            }
+            // Decorate the dropdown+search with necessary containers
+            var adapter = Utils.Decorate(dropdownWithSearch, AttachContainer);
+            adapter = Utils.Decorate(adapter, AttachBody);
+
+            return adapter;
+        });
+
     // For placeholder support 
     if (!('placeholder' in HTMLInputElement.prototype)) {
         var originalRender = Backbone.Marionette.LayoutView.prototype.render;

http://git-wip-us.apache.org/repos/asf/atlas/blob/96de0796/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 b57bb63..78d683d 100644
--- a/dashboardv2/public/js/views/search/SearchLayoutView.js
+++ b/dashboardv2/public/js/views/search/SearchLayoutView.js
@@ -15,7 +15,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 define(['require',
     'backbone',
     'hbs!tmpl/search/SearchLayoutView_tmpl',
@@ -92,6 +91,7 @@ define(['require',
                 _.extend(this, _.pick(options, 'value', 'typeHeaders', 
'searchVent', 'entityDefCollection', 'enumDefCollection', 
'classificationDefCollection', 'searchTableColumns', 'searchTableFilters', 
'entityCountCollection'));
                 this.type = "basic";
                 this.entityCountObj = 
_.first(this.entityCountCollection.toJSON());
+                this.filterTypeSelected = [];
                 var param = Utils.getUrlState.getQueryParams();
                 this.query = {
                     dsl: {
@@ -438,40 +438,68 @@ define(['require',
                 this.updateQueryObject(paramObj);
                 this.setValues(paramObj);
             },
-            renderTypeTagList: function() {
+            getFilterBox: function() {
+                var serviceStr = '',
+                    serviceArr = [],
+                    that = this;
+                this.typeHeaders.fullCollection.each(function(model) {
+                    var serviceType = model.toJSON().serviceType;
+                    if (serviceType) {
+                        serviceArr.push(serviceType);
+                    }
+                });
+                _.each(_.uniq(serviceArr), function(service) {
+                    serviceStr += '<li><div class="pretty p-switch 
p-fill"><input type="checkbox" class="pull-left" data-value="' + (service) + '" 
value="" ' + (_.contains(that.filterTypeSelected, service) ? "checked" : "") + 
'/><div class="state p-primary"><label>' + (service.toUpperCase()) + 
'</label></div></div></li>';
+                });
+                var templt = serviceStr + '<hr class="hr-filter"/><div 
class="text-right"><div class="divider"></div><button class="btn btn-action 
btn-sm filterDone">Done</button></div>';
+                return templt;
+            },
+            renderTypeTagList: function(options) {
                 var that = this;
+                var serviceTypeToBefiltered = (options && options.filterList);
+                var isTypeOnly = options && options.isTypeOnly;
                 this.ui.typeLov.empty();
                 var typeStr = '<option></option>',
                     tagStr = typeStr;
                 this.typeHeaders.fullCollection.each(function(model) {
                     var name = Utils.getName(model.toJSON(), 'name');
-                    if (model.get('category') == 'ENTITY') {
+                    if (model.get('category') == 'ENTITY' && 
(serviceTypeToBefiltered && serviceTypeToBefiltered.length ? 
_.contains(serviceTypeToBefiltered, model.get('serviceType')) : true)) {
                         var entityCount = 
(that.entityCountObj.entity.entityActive[name] + 
(that.entityCountObj.entity.entityDeleted[name] ? 
that.entityCountObj.entity.entityDeleted[name] : 0));
-                        typeStr += '<option value="'+ (name) +'" data-name="' 
+ (name) + '">' + (name) + ' ' + (entityCount ? "(" + entityCount + ")" : '') + 
'</option>';
+                        typeStr += '<option value="' + (name) + '" 
data-name="' + (name) + '">' + (name) + ' ' + (entityCount ? "(" + entityCount 
+ ")" : '') + '</option>';
                     }
-                    if (model.get('category') == 'CLASSIFICATION') {
+                    if (isTypeOnly == undefined && model.get('category') == 
'CLASSIFICATION') {
                         var tagEntityCount = 
that.entityCountObj.tag.tagEntities[name];
-                        tagStr += '<option value="'+ (name) +'" data-name="' + 
(name) + '">' + (name) + ' ' + (tagEntityCount ? "(" + tagEntityCount + ")" : 
'') + '</option>';
+                        tagStr += '<option value="' + (name) + '" data-name="' 
+ (name) + '">' + (name) + ' ' + (tagEntityCount ? "(" + tagEntityCount + ")" : 
'') + '</option>';
                     }
                 });
-                //to insert extra classification list
-                _.each(Enums.addOnClassification, function(classificationName) 
{
-                    tagStr += '<option>' + classificationName + '</option>';
-                });
+                if (_.isUndefined(isTypeOnly)) {
+                    //to insert extra classification list
+                    _.each(Enums.addOnClassification, 
function(classificationName) {
+                        tagStr += '<option>' + classificationName + 
'</option>';
+                    });
+                    that.ui.tagLov.html(tagStr);
+                    this.ui.tagLov.select2({
+                        placeholder: "Select Classification",
+                        allowClear: true
+                    });
+                }
                 that.ui.typeLov.html(typeStr);
-                that.ui.tagLov.html(tagStr);
-                this.ui.typeLov.select2({
+                var typeLovSelect2 = this.ui.typeLov.select2({
                     placeholder: "Select Type",
+                    dropdownAdapter: 
$.fn.select2.amd.require("ServiceTypeFilterDropdownAdapter"),
                     allowClear: true,
-                    templateSelection: function(data, container) {
-                        $(data.element).attr('data-name', data.customValue);
-                        return data.text;
+                    getFilterBox: this.getFilterBox.bind(this),
+                    onFilterSubmit: function(options) {
+                        that.filterTypeSelected = options.filterVal;
+                        that.renderTypeTagList({ "filterList": 
options.filterVal, isTypeOnly: true })
                     }
                 });
-                this.ui.tagLov.select2({
-                    placeholder: "Select Classification",
-                    allowClear: true
+                typeLovSelect2.on("select2:close", function() {
+                    typeLovSelect2.trigger("hideFilter");
                 });
+                if (typeLovSelect2 && serviceTypeToBefiltered) {
+                    typeLovSelect2.select2('open').trigger("change", { 
'manual': true });
+                }
             },
             renderTermList: function() {
                 var getTypeAheadData = function(data, params) {
@@ -669,6 +697,8 @@ define(['require',
                 }
             },
             clearSearchData: function() {
+                this.filterTypeSelected = [];
+                this.renderTypeTagList();
                 this.updateQueryObject();
                 this.ui.typeLov.val("").trigger("change");
                 this.ui.tagLov.val("").trigger("change");

Reply via email to