http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css b/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css deleted file mode 100644 index e9ec816..0000000 --- a/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Datetimepicker for Bootstrap 3 - * version : 4.14.30 - * https://github.com/Eonasdan/bootstrap-datetimepicker/ - */.bootstrap-datetimepicker-widget{list-style:none}.bootstrap-datetimepicker-widget.dropdown-menu{margin:2px 0;padding:4px;width:19em}@media (min-width:768px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:992px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:1200px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}.bootstrap-datetimepicker-widget.dropdown-menu:after,.bootstrap-datetimepicker-widget.dropdown-menu:before{content:'';display:inline-block;position:absolute}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);top:-7px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;top:-6px;left:8px}.bootstrap-datetime picker-widget.dropdown-menu.top:before{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,.2);bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.dropdown-menu.top:after{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget .list-unstyled{margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:700;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootst rap-datetimepicker-widget .btn[data-action=incrementHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Increment Hours"}.bootstrap-datetimepicker-widget .btn[data-action=incrementMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Increment Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=decrementHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Decrement Hours"}.bootstrap-datetimepicker-widget .btn[data-action=decrementMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Decrement Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=showHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content :"Show Hours"}.bootstrap-datetimepicker-widget .btn[data-action=showMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Show Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=togglePeriod]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Toggle AM/PM"}.bootstrap-datetimepicker-widget .btn[data-action=clear]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Clear the picker"}.bootstrap-datetimepicker-widget .btn[data-action=today]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Set the date to today"}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget .picker-switch::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflo w:hidden;clip:rect(0,0,0,0);border:0;content:"Toggle Date and Time Screens"}.bootstrap-datetimepicker-widget .picker-switch td{padding:0;margin:0;height:auto;width:auto;line-height:inherit}.bootstrap-datetimepicker-widget .picker-switch td span{line-height:2.5;height:2.5em;width:100%}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget table td,.bootstrap-datetimepicker-widget table th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget table th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table th.picker-switch{width:145px}.bootstrap-datetimepicker-widget table th.disabled,.bootstrap-datetimepicker-widget table th.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table th.prev::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Previous Month"}.bootstrap-datetimepicker-widget table th.next ::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Next Month"}.bootstrap-datetimepicker-widget table thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget table thead tr:first-child th:hover{background:#eee}.bootstrap-datetimepicker-widget table td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget table td.cw{font-size:.8em;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget table td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table td.day:hover,.bootstrap-datetimepicker-widget table td.hour:hover,.bootstrap-datetimepicker-widget table td.minute:hover,.bootstrap-datetimepicker-widget table td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget table td.new,.bootstrap-datetimepicker-widget table td.old{color:#777}.bootstrap-datetimepicker-widget table td.today{position:relative}.bootstrap-dateti mepicker-widget table td.today:before{content:'';display:inline-block;border:0 solid transparent;border-bottom-color:#337ab7;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget table td.active,.bootstrap-datetimepicker-widget table td.active:hover{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget table td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget table td.disabled,.bootstrap-datetimepicker-widget table td.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget table td span:hover{background:#eee}.bootstrap-datetimepicker-widget table td span.active{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widg et table td span.old{color:#777}.bootstrap-datetimepicker-widget table td span.disabled,.bootstrap-datetimepicker-widget table td span.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget.usetwentyfour td.hour{height:27px;line-height:27px}.bootstrap-datetimepicker-widget.wider{width:21em}.bootstrap-datetimepicker-widget .datepicker-decades .decade{line-height:1.8em!important}.input-group.date .input-group-addon{cursor:pointer}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/main.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js index 3b40451..9235d28 100644 --- a/dashboardv2/public/js/main.js +++ b/dashboardv2/public/js/main.js @@ -94,10 +94,6 @@ require.config({ 'deps': ['d3'], 'exports': ['d3-tip'] }, - 'datetimepicker': { - 'deps': ['jquery'], - 'exports': 'datetimepicker' - }, 'dagreD3': { 'deps': ['d3'], 'exports': ['dagreD3'] @@ -107,6 +103,12 @@ require.config({ }, 'jquery-placeholder': { 'deps': ['jquery'] + }, + 'query-builder': { + 'deps': ['jquery'] + }, + 'daterangepicker': { + 'deps': ['jquery', 'moment'] } }, @@ -137,12 +139,13 @@ require.config({ 'backgrid-select-all': 'libs/backgrid-select-all/backgrid-select-all.min', 'moment': 'libs/moment/js/moment.min', 'jquery-ui': 'external_lib/jquery-ui/jquery-ui.min', - 'datetimepicker': 'external_lib/datetimepicker/bootstrap-datetimepicker', 'pnotify': 'external_lib/pnotify/pnotify.custom.min', 'pnotify.buttons': 'external_lib/pnotify/pnotify.custom.min', 'pnotify.confirm': 'external_lib/pnotify/pnotify.custom.min', 'jquery-placeholder': 'libs/jquery-placeholder/js/jquery.placeholder', - 'platform': 'libs/platform/platform' + 'platform': 'libs/platform/platform', + 'query-builder': 'libs/jQueryQueryBuilder/js/query-builder.standalone.min', + 'daterangepicker': 'libs/bootstrap-daterangepicker/js/daterangepicker' }, /** @@ -167,7 +170,7 @@ require(['App', 'select2' ], function(App, Router, CommonViewFunction, Globals, UrlLinks, VEntityList, VTagList) { var that = this; - this.asyncFetchCounter = 4; + this.asyncFetchCounter = 5; this.entityDefCollection = new VEntityList(); this.entityDefCollection.url = UrlLinks.entitiesDefApiUrl(); this.typeHeaders = new VTagList(); @@ -175,11 +178,13 @@ require(['App', this.enumDefCollection = new VTagList(); this.enumDefCollection.url = UrlLinks.enumDefApiUrl(); this.enumDefCollection.modelAttrName = "enumDefs"; + this.classificationDefCollection = new VTagList(); App.appRouter = new Router({ entityDefCollection: this.entityDefCollection, typeHeaders: this.typeHeaders, - enumDefCollection: this.enumDefCollection + enumDefCollection: this.enumDefCollection, + classificationDefCollection: this.classificationDefCollection }); var startApp = function() { @@ -238,4 +243,11 @@ require(['App', startApp(); } }); + this.classificationDefCollection.fetch({ + skipDefaultError: true, + complete: function() { + --that.asyncFetchCounter; + startApp(); + } + }); }); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/models/VSearch.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/models/VSearch.js b/dashboardv2/public/js/models/VSearch.js index 5c3df97..700a909 100644 --- a/dashboardv2/public/js/models/VSearch.js +++ b/dashboardv2/public/js/models/VSearch.js @@ -49,7 +49,7 @@ define(['require', }, options); return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - }, + } }, {}); return VSearch; }); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/models/VTag.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/models/VTag.js b/dashboardv2/public/js/models/VTag.js index c875d5a..65010cf 100644 --- a/dashboardv2/public/js/models/VTag.js +++ b/dashboardv2/public/js/models/VTag.js @@ -23,7 +23,7 @@ define(['require', ], function(require, Globals, vBaseModel, UrlLinks) { 'use strict'; var VTag = vBaseModel.extend({ - urlRoot: UrlLinks.typesClassicationApiUrl(), + urlRoot: UrlLinks.classificationDefApiUrl(), defaults: {}, @@ -49,7 +49,7 @@ define(['require', return this.constructor.nonCrudOperation.call(this, url, 'DELETE', options); }, deleteTag: function(options) { - var url = UrlLinks.typesClassicationApiUrl(); + var url = UrlLinks.classificationDefApiUrl(); options = _.extend({ contentType: 'application/json', dataType: 'json' @@ -57,7 +57,7 @@ define(['require', return this.constructor.nonCrudOperation.call(this, url, 'DELETE', options); }, saveTagAttribute: function(options) { - var url = UrlLinks.typesClassicationApiUrl(); + var url = UrlLinks.classificationDefApiUrl(); options = _.extend({ contentType: 'application/json', dataType: 'json' http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/router/Router.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/router/Router.js b/dashboardv2/public/js/router/Router.js index f1250e7..8a1d241 100644 --- a/dashboardv2/public/js/router/Router.js +++ b/dashboardv2/public/js/router/Router.js @@ -42,16 +42,16 @@ define([ '*actions': 'defaultAction' }, initialize: function(options) { - _.extend(this, _.pick(options, 'entityDefCollection', 'typeHeaders', 'enumDefCollection')); + _.extend(this, _.pick(options, 'entityDefCollection', 'typeHeaders', 'enumDefCollection', 'classificationDefCollection')); this.showRegions(); this.bindCommonEvents(); this.listenTo(this, 'route', this.postRouteExecute, this); - this.tagCollection = new VTagList(); this.searchVent = new Backbone.Wreqr.EventAggregator(); this.preFetchedCollectionLists = { 'entityDefCollection': this.entityDefCollection, 'typeHeaders': this.typeHeaders, - 'enumDefCollection': this.enumDefCollection + 'enumDefCollection': this.enumDefCollection, + 'classificationDefCollection': this.classificationDefCollection } }, bindCommonEvents: function() { @@ -125,7 +125,6 @@ define([ App.rSideNav.show(new SideNavLayoutView( _.extend({ 'url': url, - 'collection': that.tagCollection }, that.preFetchedCollectionLists) )); } else { @@ -157,9 +156,7 @@ define([ App.rNHeader.show(new Header()); if (!App.rSideNav.currentView) { App.rSideNav.show(new SideNavLayoutView( - _.extend({ - 'collection': that.tagCollection, - }, that.preFetchedCollectionLists) + _.extend({}, that.preFetchedCollectionLists) )); } else { App.rSideNav.currentView.selectTab(); @@ -196,8 +193,7 @@ define([ } App.rSideNav.show(new SideNavLayoutView( _.extend({ - 'tag': tagName, - 'collection': that.tagCollection + 'tag': tagName }, that.preFetchedCollectionLists) )); } else { @@ -221,8 +217,7 @@ define([ } App.rNContent.show(new TagDetailLayoutView( _.extend({ - 'tag': tagName, - 'collection': that.tagCollection, + 'tag': tagName }, that.preFetchedCollectionLists) )); } @@ -236,12 +231,17 @@ define([ 'views/business_catalog/SideNavLayoutView', 'views/search/SearchDetailLayoutView', ], function(Header, BusinessCatalogLayoutView, SideNavLayoutView, SearchDetailLayoutView) { - var paramObj = Utils.getUrlState.getQueryParams(); + var paramObj = Utils.getUrlState.getQueryParams(), + filterObj = { + 'tagFilters': JSON.parse(Utils.localStorage.getValue('tagFilters')), + 'entityFilters': JSON.parse(Utils.localStorage.getValue('entityFilters')) + } App.rNHeader.show(new Header()); if (!App.rSideNav.currentView) { App.rSideNav.show(new SideNavLayoutView( _.extend({ - 'collection': that.tagCollection + 'searchVent': that.searchVent, + 'filterObj': filterObj }, that.preFetchedCollectionLists) )); } else { @@ -256,7 +256,9 @@ define([ App.rNContent.show(new SearchDetailLayoutView( _.extend({ 'value': paramObj, - 'initialView': true + 'initialView': true, + 'filterObj': filterObj, + 'searchVent': that.searchVent }, that.preFetchedCollectionLists) )); } else { @@ -273,14 +275,42 @@ define([ 'views/business_catalog/SideNavLayoutView', 'views/search/SearchDetailLayoutView' ], function(Header, BusinessCatalogLayoutView, SideNavLayoutView, SearchDetailLayoutView) { - var paramObj = Utils.getUrlState.getQueryParams(); + var paramObj = Utils.getUrlState.getQueryParams(), + filterObj = { + 'tagFilters': JSON.parse(Utils.localStorage.getValue('tagFilters')), + 'entityFilters': JSON.parse(Utils.localStorage.getValue('entityFilters')) + } + if (paramObj && paramObj.searchType === "basic") { + if (paramObj.type) { + if (_.has(filterObj.entityFilters, paramObj.type)) { + _.extend(paramObj, { + 'entityFilters': +new Date() + }) + } + } + if (paramObj.tag) { + if (_.has(filterObj.entityFilters, paramObj.type)) { + _.extend(paramObj, { + 'tagFilters': +new Date() + }) + } + } + Utils.setUrl({ + url: '#!/search/searchResult', + trigger: false, + urlParams: paramObj, + updateTabState: function() { + return { searchUrl: this.url, stateChanged: true }; + }, + }); + } App.rNHeader.show(new Header()); if (!App.rSideNav.currentView) { App.rSideNav.show(new SideNavLayoutView( _.extend({ 'value': paramObj, - 'collection': that.tagCollection, - 'searchVent': that.searchVent + 'searchVent': that.searchVent, + 'filterObj': filterObj }, that.preFetchedCollectionLists) )); } else { @@ -291,6 +321,7 @@ define([ _.extend({ 'value': paramObj, 'searchVent': that.searchVent, + 'filterObj': filterObj, 'initialView': (paramObj.type || (paramObj.dslChecked == "true" ? "" : paramObj.tag) || (paramObj.query ? paramObj.query.trim() : "")).length === 0 }, that.preFetchedCollectionLists) )); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html b/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html new file mode 100644 index 0000000..f204390 --- /dev/null +++ b/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html @@ -0,0 +1,17 @@ +<!-- + * 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. +--> +<div id="builder"></div> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html index a766cdf..a23057f 100644 --- a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html +++ b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html @@ -33,16 +33,26 @@ </div> <div class="col-sm-12"> <div class="form-group"> - <div class="srchType"> + <div class="srchType clearfix"> <span class="srchTitle">Search By Type</span> - <div class="typeLOV"> - <select data-id="typeLOV"></select> + <div class=""> + <div class="col-sm-10 no-padding temFilter"> + <select data-id="typeLOV"></select> + </div> + <div class="col-sm-2 no-padding temFilterBtn"> + <button type="button" class="btn btn-atlasAction btn-atlas pull-right typeLOV" title="Entity Attribute Filter" data-id="typeAttrFilter"><i class="fa fa-filter"></i></button> + </div> </div> </div> - <div class="srchType tagBox"> + <div class="srchType tagBox clearfix"> <span class="srchTitle">Search By Tag</span> - <div class="typeLOV"> - <select data-id="tagLOV"></select> + <div> + <div class="col-sm-10 no-padding"> + <select data-id="tagLOV"></select> + </div> + <div class="col-sm-2 no-padding"> + <button type="button" class="btn btn-atlasAction btn-atlas pull-right" title="Tag Attribute Filter" data-id="tagAttrFilter"><i class="fa fa-filter"></i></button> + </div> </div> </div> <div class="srchType"> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html b/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html new file mode 100644 index 0000000..05c2a61 --- /dev/null +++ b/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html @@ -0,0 +1,21 @@ +<!-- + * 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. +--> +<div id="r_queryBuilder"> + <div class="fontLoader"> + <i class="fa fa-refresh fa-spin-custom"></i> + </div> +</div> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html index 91f1a67..fc2fe8c 100644 --- a/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html +++ b/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html @@ -20,6 +20,21 @@ <div class="fontLoader"> <i class="fa fa-refresh fa-spin-custom"></i> </div> + <div> + <div id="r_searchQuery"> + <div class="panel panel-default" id="filterPanel"> + <div class="panel-heading clearfix"> + <h4 class="panel-title pull-left">Type,Tag filter/s</h4> + <div class="btn-group pull-right"> + <button type="button" id="expand_collapse_panel" class="expand_collapse_panel" title="Collapse"><i class="fa fa-chevron-up" aria-hidden="true"></i></button> + </div> + </div> + <div id="panel_body" class="panel-body collapse in" align="center"> + <p class="filterQuery" id="filterQuery"></p> + </div> + </div> + </div> + </div> <div class="ellipsis" style="display: none;"><span class="searchResult" style=" font-size: 16px;"></span> <a href="javascript:void(0)" class="inputAssignTag multiSelectTerm btnAssign" style="display:none" data-id="addTerm"><i class="fa fa-folder-o"></i> Assign Term</a> <a href="javascript:void(0)" class="inputAssignTag multiSelectTag assignTag btnAssign" style="display:none" data-id="addAssignTag"><i class="fa fa-plus"></i> Assign Tag</a> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html b/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html index a7f9146..26d283b 100644 --- a/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html +++ b/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. --> -<div class="fontLoader" style="margin-top:-10px"> +<div class="fontLoader"> <i class="fa fa-refresh fa-spin-custom"></i> </div> <div class="row row-margin-bottom hide"> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/templates/tag/createTagLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/tag/createTagLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/createTagLayoutView_tmpl.html index 0491c78..8b0b63d 100644 --- a/dashboardv2/public/js/templates/tag/createTagLayoutView_tmpl.html +++ b/dashboardv2/public/js/templates/tag/createTagLayoutView_tmpl.html @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. --> -<div class="fontLoader" style="margin-top:-10px"> +<div class="fontLoader"> <i class="fa fa-refresh fa-spin-custom"></i> </div> <form name="tagDefinitionform" class="css-form hide" data-id="createTagForm"> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/utils/Overrides.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/Overrides.js b/dashboardv2/public/js/utils/Overrides.js index b6fc17c..615e3b1 100644 --- a/dashboardv2/public/js/utils/Overrides.js +++ b/dashboardv2/public/js/utils/Overrides.js @@ -49,7 +49,6 @@ define(['require', 'utils/Utils', 'marionette', 'backgrid', 'asBreadcrumbs', 'jq } } }); - // For placeholder support if (!('placeholder' in HTMLInputElement.prototype)) { var originalRender = Backbone.Marionette.LayoutView.prototype.render; @@ -141,4 +140,8 @@ define(['require', 'utils/Utils', 'marionette', 'backgrid', 'asBreadcrumbs', 'jq return this; } }); + + String.prototype.capitalize = function() { + return this.charAt(0).toUpperCase() + this.slice(1); + } }); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/utils/UrlLinks.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/UrlLinks.js b/dashboardv2/public/js/utils/UrlLinks.js index c692d8d..df20cf1 100644 --- a/dashboardv2/public/js/utils/UrlLinks.js +++ b/dashboardv2/public/js/utils/UrlLinks.js @@ -28,6 +28,23 @@ define(['require', 'utils/Enums'], function(require, Enums) { def: this.baseUrlV2 + '/types/typedef' }; }, + entitiesDefApiUrl: function(name) { + return this.getDefApiUrl('entity', name); + }, + classificationDefApiUrl: function(name) { + return this.getDefApiUrl('classification', name); + }, + enumDefApiUrl: function(name) { + return this.getDefApiUrl('enum', name); + }, + getDefApiUrl: function(type, name) { + var defApiUrl = this.typedefsUrl(); + if (name) { + return defApiUrl.def + '/name/' + name + '?type=' + type; + } else { + return defApiUrl.defs + '?type=' + type; + } + }, taxonomiesApiUrl: function() { return this.baseUrl + '/v1/taxonomies'; }, @@ -44,22 +61,6 @@ define(['require', 'utils/Enums'], function(require, Enums) { return entitiesUrl; } }, - entitiesDefApiUrl: function(name) { - var entitieDefUrl = this.typedefsUrl(); - if (name) { - return entitieDefUrl.def + '/name/' + name + '?type=entity'; - } else { - return entitieDefUrl.defs + '?type=entity'; - } - }, - enumDefApiUrl: function(name) { - var enumDefApiUrl = this.typedefsUrl(); - if (name) { - return enumDefApiUrl.def + '/name/' + name + '?type=enum'; - } else { - return enumDefApiUrl.defs + '?type=enum'; - } - }, entitiesTraitsApiUrl: function(token) { if (token) { return this.baseUrlV2 + '/entity/guid/' + token + '/classifications'; @@ -67,19 +68,16 @@ define(['require', 'utils/Enums'], function(require, Enums) { // For Multiple Assignment return this.baseUrlV2 + '/entity/bulk/classification'; } - }, entityCollectionaudit: function(guid) { return this.baseUrl + '/entities/' + guid + '/audit'; }, - typesClassicationApiUrl: function(name, guid) { + classicationApiUrl: function(name, guid) { var typeUrl = this.typedefsUrl(); if (name) { return typeUrl.def + '/name/' + name + '?type=classification'; } else if (guid) { return typeUrl.def + '/guid/' + guid + '?type=classification'; - } else { - return typeUrl.defs + '?type=classification'; } }, typesApiUrl: function() { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/utils/Utils.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js index 1d614a8..9071df3 100644 --- a/dashboardv2/public/js/utils/Utils.js +++ b/dashboardv2/public/js/utils/Utils.js @@ -166,37 +166,11 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'pnotify.button }); } }; - Utils.localStorage = { - checkLocalStorage: function(key, value) { - if (typeof(Storage) !== "undefined") { - return this.getLocalStorage(key, value); - } else { - console.log('Sorry! No Web Storage support'); - Utils.cookie.checkCookie(key, value); - } - }, - setLocalStorage: function(key, value) { - localStorage.setItem(key, value); - return { found: false, 'value': value }; - }, - getLocalStorage: function(key, value) { - var keyValue = localStorage.getItem(key); - if (!keyValue || keyValue == "undefined") { - return this.setLocalStorage(key, value); - } else { - return { found: true, 'value': keyValue }; - } - } - }; Utils.cookie = { - setCookie: function(cname, cvalue) { - //var d = new Date(); - //d.setTime(d.getTime() + (exdays*24*60*60*1000)); - //var expires = "expires=" + d.toGMTString(); + setValue: function(cname, cvalue) { document.cookie = cname + "=" + cvalue + "; "; - return { found: false, 'value': cvalue }; }, - getCookie: function(findString) { + getValue: function(findString) { var search = findString + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { @@ -207,16 +181,34 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'pnotify.button } } return ""; - }, - checkCookie: function(key, value) { - var findString = getCookie(key); - if (findString != "" || keyValue != "undefined") { - return { found: true, 'value': ((findString == "undefined") ? (undefined) : (findString)) }; + } + }; + Utils.localStorage = function() { + this.setValue = function() { + localStorage.setItem(arguments[0], arguments[1]); + } + this.getValue = function(key, value) { + var keyValue = localStorage.getItem(key); + if ((!keyValue || keyValue == "undefined") && (value != undefined)) { + return this.setLocalStorage(key, value); } else { - return setCookie(key, value); + if (keyValue === "" || keyValue === "undefined" || keyValue === "null") { + return null; + } else { + return keyValue; + } + } } - }; + this.removeValue = function() { + localStorage.removeItem(arguments[0]); + } + if (typeof(Storage) === "undefined") { + _.extend(this, Utils.cookie); + console.log('Sorry! No Web Storage support'); + } + } + Utils.localStorage = new Utils.localStorage(); Utils.setUrl = function(options) { if (options) { @@ -509,16 +501,16 @@ define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'pnotify.button } $('body').on('click', '.expand_collapse_panel', function() { var icon = $(this).find('i'), - panel = $(this).parents('.panel'), + panel = $(this).parents('.panel').first(), panelBody = panel.find('.panel-body'); icon.toggleClass('fa-chevron-up fa-chevron-down'); $(this).toggleAttribute('title', 'Collapse', 'Expand'); - panelBody.toggle('0.5', 'linear'); + panelBody.toggle(); $(this).trigger('expand_collapse_panel', [$(this).parents('.panel')]); }); $('body').on('click', '.fullscreen_panel', function() { var icon = $(this).find('i'), - panel = $(this).parents('.panel'), + panel = $(this).parents('.panel').first(), panelBody = panel.find('.panel-body'); icon.toggleClass('fa-expand fa-compress'); $(this).toggleAttribute('title', 'Fullscreen', 'Exit Fullscreen'); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/business_catalog/SideNavLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/business_catalog/SideNavLayoutView.js b/dashboardv2/public/js/views/business_catalog/SideNavLayoutView.js index af18540..013c72e 100644 --- a/dashboardv2/public/js/views/business_catalog/SideNavLayoutView.js +++ b/dashboardv2/public/js/views/business_catalog/SideNavLayoutView.js @@ -66,7 +66,7 @@ define(['require', return events; }, initialize: function(options) { - _.extend(this, _.pick(options, 'url', 'value', 'tag', 'selectFirst', 'collection', 'typeHeaders', 'searchVent')); + _.extend(this, _.pick(options, 'url', 'value', 'tag', 'selectFirst', 'classificationDefCollection', 'typeHeaders', 'searchVent', 'entityDefCollection', 'enumDefCollection', 'filterObj')); if (Globals.taxonomy) { this.tabClass = "tab col-sm-4"; } else { @@ -94,7 +94,7 @@ define(['require', var that = this; require(['views/tag/TagLayoutView'], function(TagLayoutView) { that.RTagLayoutView.show(new TagLayoutView({ - collection: that.collection, + collection: that.classificationDefCollection, tag: that.tag, typeHeaders: that.typeHeaders })); @@ -105,8 +105,12 @@ define(['require', require(['views/search/SearchLayoutView'], function(SearchLayoutView) { that.RSearchLayoutView.show(new SearchLayoutView({ value: that.value, + filterObj: that.filterObj, searchVent: that.searchVent, - typeHeaders: that.typeHeaders + typeHeaders: that.typeHeaders, + entityDefCollection: that.entityDefCollection, + enumDefCollection: that.enumDefCollection, + classificationDefCollection: that.classificationDefCollection })); }); }, http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js b/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js index 704062f..d461d09 100644 --- a/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js +++ b/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js @@ -25,13 +25,13 @@ define(['require', 'models/VEntity', 'modules/Modal', 'utils/Messages', - 'datetimepicker', 'moment', 'utils/UrlLinks', 'collection/VSearchList', 'utils/Enums', - 'utils/Globals' -], function(require, Backbone, CreateEntityLayoutViewTmpl, Utils, VTagList, VEntityList, VEntity, Modal, Messages, datepicker, moment, UrlLinks, VSearchList, Enums, Globals) { + 'utils/Globals', + 'daterangepicker' +], function(require, Backbone, CreateEntityLayoutViewTmpl, Utils, VTagList, VEntityList, VEntity, Modal, Messages, moment, UrlLinks, VSearchList, Enums, Globals) { var CreateEntityLayoutView = Backbone.Marionette.LayoutView.extend( /** @lends CreateEntityLayoutView */ @@ -145,7 +145,7 @@ define(['require', } }); - this.ui.entityInputData.on('keyup change dp.change', 'input.true,select.true', function(e) { + this.ui.entityInputData.on('keyup change', 'input.true,select.true', function(e) { if (this.value !== "") { if ($(this).data('select2')) { $(this).data('select2').$container.find('.select2-selection').removeClass("errorClass"); @@ -171,7 +171,7 @@ define(['require', }, bindNonRequiredField: function() { var that = this; - this.ui.entityInputData.off('keyup change dp.change', 'input.false,select.false').on('keyup change dp.change', 'input.false,select.false', function(e) { + this.ui.entityInputData.off('keyup change', 'input.false,select.false').on('keyup change', 'input.false,select.false', function(e) { if (that.modal.$el.find('button.ok').prop('disabled') && that.ui.entityInputData.find('.errorClass').length === 0) { that.modal.$el.find('button.ok').prop("disabled", false); } @@ -331,11 +331,12 @@ define(['require', initilizeElements: function() { var that = this; this.$('input[data-type="date"]').each(function() { - if (!$(this).data('datepicker')) { - $(this).datetimepicker({ - format: 'DD MMMM YYYY', - keepInvalid: true - }); + if (!$(this).data('daterangepicker')) { + var dateObj = { "singleDatePicker": true, "showDropdowns": true }; + if (that.guid) { + dateObj["startDate"] = this.value + } + $(this).daterangepicker(dateObj); } }); this.initializeValidation(); @@ -387,9 +388,9 @@ define(['require', removeText(e, e.currentTarget.value); }); - this.$('input[data-type="date"]').on('dp.hide keydown', function(event) { + this.$('input[data-type="date"]').on('hide.daterangepicker keydown', function(event) { if (event.type) { - if (event.type == 'dp') { + if (event.type == 'hide') { this.blur(); } else if (event.type == 'keydown') { return false; @@ -462,7 +463,7 @@ define(['require', entityValue = dataValue; } if (value.typeName === "date" && dataValue) { - entityValue = moment(dataValue).format("DD MMMM YYYY"); + entityValue = moment(dataValue).format("MM/DD/YYYY"); } } } @@ -538,7 +539,7 @@ define(['require', if (dataTypeEnitity && datakeyEntity) { if (that.entityDefCollection.fullCollection.find({ name: dataTypeEnitity })) { entity[datakeyEntity] = extractValue(value, typeName); - } else if (typeof dataTypeEnitity === 'string' && datakeyEntity.indexOf("Time") > -1) { + } else if (dataTypeEnitity === 'date' || dataTypeEnitity === 'time') { entity[datakeyEntity] = Date.parse(value); } else if (dataTypeEnitity.indexOf("map") > -1 || (typeNameCategory && typeNameCategory.get('category') === 'STRUCT')) { try { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/search/QueryBuilderView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/QueryBuilderView.js b/dashboardv2/public/js/views/search/QueryBuilderView.js new file mode 100644 index 0000000..468a2d7 --- /dev/null +++ b/dashboardv2/public/js/views/search/QueryBuilderView.js @@ -0,0 +1,181 @@ +/** + * 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. + */ + +define(['require', + 'backbone', + 'hbs!tmpl/search/QueryBuilder_tmpl', + 'utils/Utils', + 'query-builder', + 'daterangepicker' +], function(require, Backbone, QueryBuilder_Tmpl, Utils) { + + var QueryBuilderView = Backbone.Marionette.LayoutView.extend( + /** @lends QueryBuilderView */ + { + _viewName: 'QueryBuilderView', + + template: QueryBuilder_Tmpl, + + + + /** Layout sub regions */ + regions: {}, + + + /** ui selector cache */ + ui: { + "builder": "#builder" + }, + /** ui events hash */ + events: function() { + var events = {}; + return events; + }, + /** + * intialize a new QueryBuilderView Layout + * @constructs + */ + initialize: function(options) { + _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'filterObj', 'entityDefCollection', 'enumDefCollection', 'tag')); + this.attrObj = _.sortBy(this.attrObj, 'name'); + }, + bindEvents: function() {}, + getOperator: function(type) { + var obj = { + operators: null + } + if (type === "string") { + obj.operators = ['=', '!=', 'contains', 'begins_with', 'ends_with']; + } + if (type === "enum" || type === "date" || type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double") { + obj.operators = ['=', '!=', '>', '<', '>=', '<=']; + } + return obj; + }, + isPrimitive: function(type) { + if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double" || type === "string" || type === "boolean" || type === "date") { + return true; + } + return false; + }, + getObjDef: function(attrObj, rules) { + var obj = { + id: attrObj.name, + label: attrObj.name.capitalize(), + type: attrObj.typeName + }; + if (obj.type === "date") { + obj['plugin'] = 'daterangepicker'; + obj['plugin_config'] = { + "singleDatePicker": true, + "showDropdowns": true, + "timePicker": true, + locale: { + format: 'MM/DD/YYYY h:mm A' + } + }; + if (rules && rules.rules) { + var valueObj = _.find(rules.rules, { id: obj.id }); + if (valueObj) { + obj.plugin_config["startDate"] = valueObj.value; + } + } + _.extend(obj, this.getOperator(obj.type)); + return obj; + } + if (this.isPrimitive(obj.type)) { + if (obj.type === "long" || obj.type === "float") { + obj.type = "double"; + } + if (obj.type === "int" || obj.type === "byte" || obj.type === "short") { + obj.type = "integer"; + } + if (obj.type === "boolean") { + obj['input'] = 'select'; + obj['values'] = ['true', 'false']; + } + _.extend(obj, this.getOperator(obj.type)); + return obj; + } + var enumObj = this.enumDefCollection.fullCollection.find({ name: obj.type }); + if (enumObj) { + obj.type = "string"; + obj['input'] = 'select'; + var value = []; + _.each(enumObj.get('elementDefs'), function(o) { + value.push(o.value) + }) + obj['values'] = value; + _.extend(obj, this.getOperator('enum')); + return obj; + } + }, + onRender: function() { + var that = this, + filters = []; + if (this.filterObj) { + var filter = this.filterObj[(this.tag ? 'tagFilters' : 'entityFilters')], + tagTermName = this.tag ? this.value.tag : this.value.type; + if (filter) { + ruleObj = filter[tagTermName]; + if (ruleObj) { + var rules_widgets = ruleObj.rule; + } + } + } + + _.each(this.attrObj, function(obj) { + var returnObj = that.getObjDef(obj, rules_widgets); + if (returnObj) { + filters.push(returnObj); + } + }); + if (filters && !_.isEmpty(filters)) { + this.ui.builder.queryBuilder({ + plugins: ['bt-tooltip-errors'], + filters: filters, + select_placeholder: '--Select Attribute--', + allow_empty: true, + conditions: ['AND'], + allow_groups: false, + allow_empty: true, + operators: [ + { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] } + ], + lang: { + add_rule: 'Add filter', + add_group: 'Add filter group' + }, + rules: rules_widgets + }); + this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-right pull-left'); + } else { + this.ui.builder.html('<h4>No Attributes are available !</h4>') + } + } + }); + return QueryBuilderView; +}); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/search/SearchDetailLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/SearchDetailLayoutView.js b/dashboardv2/public/js/views/search/SearchDetailLayoutView.js index b22fae8..32ad542 100644 --- a/dashboardv2/public/js/views/search/SearchDetailLayoutView.js +++ b/dashboardv2/public/js/views/search/SearchDetailLayoutView.js @@ -43,7 +43,7 @@ define(['require', * @constructs */ initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'initialView', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection')); + _.extend(this, _.pick(options, 'value', 'initialView', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'filterObj')); }, bindEvents: function() {}, onRender: function() { @@ -62,6 +62,7 @@ define(['require', entityDefCollection: that.entityDefCollection, typeHeaders: that.typeHeaders, searchVent: that.searchVent, + filterObj: that.filterObj, enumDefCollection: that.enumDefCollection })); } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/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 32b82d7..7ac394c 100644 --- a/dashboardv2/public/js/views/search/SearchLayoutView.js +++ b/dashboardv2/public/js/views/search/SearchLayoutView.js @@ -44,7 +44,9 @@ define(['require', typeLov: '[data-id="typeLOV"]', tagLov: '[data-id="tagLOV"]', refreshBtn: '[data-id="refreshBtn"]', - advancedInfoBtn: '[data-id="advancedInfo"]' + advancedInfoBtn: '[data-id="advancedInfo"]', + typeAttrFilter: '[data-id="typeAttrFilter"]', + tagAttrFilter: '[data-id="tagAttrFilter"]' }, /** ui events hash */ @@ -65,6 +67,12 @@ define(['require', events["change " + this.ui.tagLov] = 'checkForButtonVisiblity'; events["click " + this.ui.refreshBtn] = 'onRefreshButton'; events["click " + this.ui.advancedInfoBtn] = 'advancedInfo'; + events["click " + this.ui.typeAttrFilter] = function() { + this.openAttrFilter('type'); + }; + events["click " + this.ui.tagAttrFilter] = function() { + this.openAttrFilter('tag'); + }; return events; }, /** @@ -72,7 +80,7 @@ define(['require', * @constructs */ initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'typeHeaders', 'searchVent')); + _.extend(this, _.pick(options, 'value', 'typeHeaders', 'searchVent', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'filterObj')); this.type = "basic"; var param = Utils.getUrlState.getQueryParams(); this.query = { @@ -83,9 +91,14 @@ define(['require', basic: { query: null, type: null, + typeFilter: null, + tagFilter: null, tag: null } }; + if (!this.value) { + this.value = {}; + } this.dsl = false; if (param && param.searchType) { this.type = param.searchType; @@ -108,6 +121,51 @@ define(['require', this.checkForButtonVisiblity(); }, this); }, + bindSelect2Events: function(argument) { + var that = this; + this.ui.typeLov.on('select2:select', function(argument) { + // this function calles after checkForButtonVisiblity that is why disabled flter here + that.ui.typeAttrFilter.prop('disabled', false); + _.extend(that.value, { 'type': this.value }); + that.makeFilterButtonActive('type'); + }); + this.ui.tagLov.on('select2:select', function(argument) { + // this function calles after checkForButtonVisiblity that is why disabled flter here + that.ui.tagAttrFilter.prop('disabled', false); + _.extend(that.value, { 'tag': this.value }); + that.makeFilterButtonActive('tag'); + }); + this.ui.typeLov.on('select2:unselect', function(argument) { + _.extend(that.value, { 'type': null }); + }); + this.ui.tagLov.on('select2:unselect', function(argument) { + _.extend(that.value, { 'tag': null }); + }); + }, + makeFilterButtonActive: function(type) { + if (this.filterObj) { + var tagFilters = this.filterObj.tagFilters, + entityFilters = this.filterObj.entityFilters; + if (type == "type") { + if (_.has(entityFilters, this.value[type])) { + this.query[this.type]['entityFilters'] = +new Date(); + this.ui.typeAttrFilter.addClass('active'); + } else { + this.query[this.type]['entityFilters'] = null; + this.ui.typeAttrFilter.removeClass('active'); + } + } + if (type == "tag") { + if (_.has(tagFilters, this.value[type])) { + this.query[this.type]['tagFilters'] = +new Date(); + this.ui.tagAttrFilter.addClass('active'); + } else { + this.query[this.type]['tagFilters'] = null; + this.ui.tagAttrFilter.removeClass('active'); + } + } + } + }, checkForButtonVisiblity: function() { var that = this, value = this.ui.searchInput.val() || this.ui.typeLov.val(); @@ -122,6 +180,24 @@ define(['require', } else { this.ui.searchBtn.attr("disabled", "true"); } + if (this.value) { + if (this.value.tag) { + this.ui.tagAttrFilter.prop('disabled', false); + } else { + this.ui.tagAttrFilter.prop('disabled', true); + } + if (this.value.type) { + this.ui.typeAttrFilter.prop('disabled', false); + } else { + this.ui.typeAttrFilter.prop('disabled', true); + } + this.makeFilterButtonActive('type'); + this.makeFilterButtonActive('tag'); + } else { + this.ui.tagAttrFilter.prop('disabled', true); + this.ui.typeAttrFilter.prop('disabled', true); + } + }, onRender: function() { // array of tags which is coming from url @@ -135,19 +211,24 @@ define(['require', placeholder: "Select", allowClear: true }); - this.bindEvents(); + this.bindSelect2Events(); this.checkForButtonVisiblity(); }, updateQueryObject: function(param) { if (param && param.searchType) { this.type = param.searchType; } - _.extend(this.query[this.type], { + _.extend(this.query[this.type], + (this.type == "dsl" ? { + query: null, + type: null + } : { query: null, type: null, - tag: null - }, - param); + tag: null, + entityFilters: null, + tagFilters: null + }), param); }, fetchCollection: function(value) { this.typeHeaders.fetch({ reset: true }); @@ -176,6 +257,86 @@ define(['require', }); }); }, + openAttrFilter: function(filterType) { + var that = this; + require(['views/search/SearchQueryView'], function(SearchQueryView) { + that.attrModal = new SearchQueryView({ + value: that.value, + tag: (filterType === "tag" ? true : false), + type: (filterType === "type" ? true : false), + searchVent: that.searchVent, + typeHeaders: that.typeHeaders, + entityDefCollection: that.entityDefCollection, + enumDefCollection: that.enumDefCollection, + filterObj: that.filterObj, + classificationDefCollection: that.classificationDefCollection + }); + that.attrModal.on('ok', function(e) { + that.okAttrFilterButton(); + }); + }); + }, + okAttrFilterButton: function() { + var filtertype = this.attrModal.tag ? 'tagFilters' : 'entityFilters', + rule = this.attrModal.RQueryBuilder.currentView.ui.builder.queryBuilder('getRules'), + result = this.getQueryBuilderParsData(rule); + if (result && !_.isEmpty(result.criterion)) { + this.query[this.type][filtertype] = +new Date(); + if (result) { + var filterObj = this.filterObj ? this.filterObj[filtertype] : null; + if (!filterObj) { + filterObj = {}; + } + var temp = {}; // IE fix + temp[(this.attrModal.tag ? this.value.tag : this.value.type)] = { 'result': result, 'rule': rule }; + _.extend(filterObj, temp); + this.filterObj[filtertype] = filterObj; + this.makeFilterButtonActive(this.attrModal.tag ? 'tag' : 'type'); + Utils.localStorage.setValue((filtertype), JSON.stringify(filterObj)); + } else { + this.filterObj[filtertype] = null; + this.query[this.type][filtertype] = null; + this.makeFilterButtonActive(this.attrModal.tag ? 'tag' : 'type'); + Utils.localStorage.removeValue(filtertype); + } + } else { + this.filterObj[filtertype] = null; + this.query[this.type][filtertype] = null; + this.makeFilterButtonActive(this.attrModal.tag ? 'tag' : 'type'); + Utils.localStorage.removeValue(filtertype); + } + this.attrModal.modal.close(); + }, + getQueryBuilderParsData: function(obj) { + if (obj) { + var parsObj = { + "condition": obj.condition, + "criterion": convertKeyAndExtractObj(obj.rules) + } + } + + function convertKeyAndExtractObj(rules) { + var convertObj = []; + _.each(rules, function(rulObj) { + var tempObj = {} + if (rulObj.rules) { + tempObj = { + "condition": rulObj.condition, + "criterion": convertKeyAndExtractObj(rulObj.rules) + } + } else { + tempObj = { + "attributeName": rulObj.id, + "operator": rulObj.operator, + "attributeValue": (rulObj.type === "date" ? Date.parse(rulObj.value) : rulObj.value) + } + } + convertObj.push(tempObj); + }); + return convertObj; + } + return parsObj; + }, manualRender: function(paramObj) { this.updateQueryObject(paramObj); this.setValues(paramObj); @@ -232,6 +393,7 @@ define(['require', setTimeout(function() { that.ui.searchInput.focus(); }, 0); + //this.searchVent.trigger('searchAttribute', this.value); } }, findSearchResult: function() { @@ -243,7 +405,6 @@ define(['require', if (!this.dsl) { this.query[this.type].tag = this.ui.tagLov.select2('val') || null; } - Utils.setUrl({ url: '#!/search/searchResult', urlParams: _.extend(this.query[this.type], { @@ -263,7 +424,11 @@ define(['require', this.type = "dsl"; this.dsl = true; this.$('.tagBox').hide(); + this.$('.temFilterBtn').hide(); + this.$('.temFilter').toggleClass('col-sm-10 col-sm-12'); } else { + this.$('.temFilter').toggleClass('col-sm-10 col-sm-12'); + this.$('.temFilterBtn').show(); this.$('.tagBox').show(); this.dsl = false; this.type = "basic"; http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/search/SearchQueryView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/SearchQueryView.js b/dashboardv2/public/js/views/search/SearchQueryView.js new file mode 100644 index 0000000..37ccf90 --- /dev/null +++ b/dashboardv2/public/js/views/search/SearchQueryView.js @@ -0,0 +1,113 @@ +/** + * 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. + */ + +define(['require', + 'backbone', + 'modules/Modal', + 'utils/Utils', + 'hbs!tmpl/search/SearchQuery_tmpl', +], function(require, Backbone, Modal, Utils, SearchQuery_Tmpl) { + + var SearchQueryView = Backbone.Marionette.LayoutView.extend( + /** @lends SearchQueryView */ + { + _viewName: 'SearchQueryView', + + template: SearchQuery_Tmpl, + + + + /** Layout sub regions */ + regions: { + RQueryBuilder: '#r_queryBuilder', + }, + + + /** ui selector cache */ + ui: {}, + /** ui events hash */ + events: function() { + var events = {}; + return events; + }, + /** + * intialize a new SearchQueryView Layout + * @constructs + */ + initialize: function(options) { + _.extend(this, _.pick(options, 'value', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'classificationDefCollection', 'tag', 'filterObj')); + this.bindEvents(); + var that = this; + this.modal = new Modal({ + title: 'Attribute Filter', + content: this, + okText: 'Apply', + cancelText: "Cancel", + allowCancel: true, + okCloses: false, + width: '50%' + }).open(); + this.modal.on('closeModal', function() { + that.modal.trigger('cancel'); + }); + }, + onRender: function() { + this.$('.fontLoader').show(); + var obj = { + value: this.value, + searchVent: this.searchVent, + entityDefCollection: this.entityDefCollection, + enumDefCollection: this.enumDefCollection, + filterObj: this.filterObj, + classificationDefCollection: this.classificationDefCollection + } + + if (this.tag) { + obj['tag'] = true; + obj['attrObj'] = this.classificationDefCollection.fullCollection.find({ name: this.value.tag }); + if (obj.attrObj) { + obj.attrObj = Utils.getNestedSuperTypeObj({ + data: obj.attrObj.toJSON(), + collection: this.classificationDefCollection, + attrMerge: true, + }); + } + } else { + obj['type'] = true; + obj['attrObj'] = this.entityDefCollection.fullCollection.find({ name: this.value.type }); + if (obj.attrObj) { + obj.attrObj = Utils.getNestedSuperTypeObj({ + data: obj.attrObj.toJSON(), + collection: this.entityDefCollection, + attrMerge: true + }); + } + } + this.renderQueryBuilder(obj); + // this.showHideFilter(this.value); + }, + bindEvents: function() {}, + renderQueryBuilder: function(obj) { + var that = this; + require(['views/search/QueryBuilderView'], function(QueryBuilderView) { + that.RQueryBuilder.show(new QueryBuilderView(obj)); + }); + } + }); + return SearchQueryView; +}); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/search/SearchResultLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/SearchResultLayoutView.js b/dashboardv2/public/js/views/search/SearchResultLayoutView.js index 1198809..5236751 100644 --- a/dashboardv2/public/js/views/search/SearchResultLayoutView.js +++ b/dashboardv2/public/js/views/search/SearchResultLayoutView.js @@ -44,6 +44,7 @@ define(['require', RTagLayoutView: "#r_tagLayoutView", RSearchLayoutView: "#r_searchLayoutView", REntityTableLayoutView: "#r_searchResultTableLayoutView", + RSearchQuery: '#r_searchQuery' }, /** ui selector cache */ @@ -61,7 +62,9 @@ define(['require', editEntityButton: "[data-id='editEntityButton']", createEntity: "[data-id='createEntity']", checkDeletedEntity: "[data-id='checkDeletedEntity']", - containerCheckBox: "[data-id='containerCheckBox']" + containerCheckBox: "[data-id='containerCheckBox']", + filterPanel: "#filterPanel", + filterQuery: "#filterQuery" }, templateHelpers: function() { return { @@ -126,7 +129,7 @@ define(['require', * @constructs */ initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'initialView', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'tagCollection')); + _.extend(this, _.pick(options, 'value', 'initialView', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'tagCollection', 'filterObj')); var pagination = ""; this.entityModel = new VEntity(); this.searchCollection = new VSearchList(); @@ -198,7 +201,7 @@ define(['require', } else { if (response.statusText !== "abort") { Utils.notifyError({ - content: "Invalid Expression : " + model.queryParams.query + content: "Invalid Expression" }); } } @@ -206,6 +209,9 @@ define(['require', this.listenTo(this.searchVent, "search:refresh", function(model, response) { this.fetchCollection(); }, this); + this.listenTo(this.searchVent, "searchAttribute", function(obj) { + this.showHideFilter(obj); + }, this); }, onRender: function() { if (!this.initialView) { @@ -234,27 +240,74 @@ define(['require', this.$(".entityLink").show(); } } + this.showHideFilter(); + }, + generateQueryOfFilter: function() { + var value = this.value, + entityFilters = this.filterObj && this.filterObj.entityFilters ? this.filterObj.entityFilters[value.type] : null, + tagFilters = this.filterObj && this.filterObj.tagFilters ? this.filterObj.tagFilters[value.tag] : null, + queryArray = [], + objToString = function(filterObj) { + var tempObj = []; + _.each(filterObj.rules, function(obj) { + tempObj.push('<span class="key">' + obj.field + '</span> <span class="operator">' + obj.operator + '</span> <span class="value">' + obj.value + "</span>") + }); + return tempObj.join(' <span class="operator">AND</span> '); + } + if (entityFilters) { + var typeKeyValue = '<span class="key">Type:</span> <span class="value">' + value.type + '</span> <span class="operator">AND</span> '; + queryArray = queryArray.concat(typeKeyValue + objToString(entityFilters.rule)); + } + if (tagFilters) { + var tagKeyValue = '<span class="key">Tag:</span> <span class="value">' + value.tag + '</span> <span class="operator">AND</span> '; + queryArray = queryArray.concat(tagKeyValue + objToString(tagFilters.rule)); + + } + if (queryArray.length == 2) { + return "<span>(</span> " + queryArray.join('<span> )</span> <span>AND</span> <span>(</span> ') + " <span>)</span>"; + } else { + return queryArray.join(); + } + }, + showHideFilter: function() { + if (this.value) { + if (Utils.getUrlState.isSearchTab() && this.value.searchType == "basic") { + var query = this.generateQueryOfFilter(); + if (query) { + this.ui.filterQuery.html(query); + this.ui.filterPanel.show(); + } else + this.ui.filterPanel.hide(); + } else { + this.ui.filterPanel.hide(); + } + } else { + this.ui.filterPanel.hide(); + } }, fetchCollection: function(value, clickObj) { - var that = this; + var that = this, + isPostMethod = this.value.searchType === "basic" && Utils.getUrlState.isSearchTab(), + tagFilters = this.filterObj && this.filterObj.tagFilters ? this.filterObj.tagFilters[this.value.tag] : null, + entityFilters = this.filterObj && this.filterObj.entityFilters ? this.filterObj.entityFilters[this.value.type] : null, + filterObj = { + 'entityFilters': entityFilters ? entityFilters.result : null, + 'tagFilters': tagFilters ? tagFilters.result : null + } this.showLoader(); if (Globals.searchApiCallRef && Globals.searchApiCallRef.readyState === 1) { Globals.searchApiCallRef.abort(); } - if (value) { - $.extend(this.searchCollection.queryParams, { limit: this.limit, excludeDeletedEntities: true }); - if (value.searchType) { - this.searchCollection.url = UrlLinks.searchApiUrl(value.searchType); - } - _.extend(this.searchCollection.queryParams, { 'query': (value.query ? value.query.trim() : null), 'typeName': value.type || null, 'classification': value.tag || null }); - } - Globals.searchApiCallRef = this.searchCollection.fetch({ + var apiObj = { skipDefaultError: true, - success: function() { + success: function(model, response) { Globals.searchApiCallRef = undefined; if (!(that.ui.pageRecordText instanceof jQuery)) { return; } + if (isPostMethod) { + that.searchCollection.reset(model.entities); + } if (that.searchCollection.models.length === 0 && that.offset > that.limit) { that.ui.nextData.attr('disabled', true); that.offset = that.offset - that.limit; @@ -302,6 +355,38 @@ define(['require', }, silent: true, reset: true + } + if (value) { + $.extend(this.searchCollection.queryParams, { limit: this.limit, excludeDeletedEntities: true }); + if (value.searchType) { + this.searchCollection.url = UrlLinks.searchApiUrl(value.searchType); + } + _.extend(this.searchCollection.queryParams, { 'query': (value.query ? value.query.trim() : null), 'typeName': value.type || null, 'classification': value.tag || null }); + if (isPostMethod) { + apiObj['data'] = _.extend({}, filterObj, _.pick(this.searchCollection.queryParams, 'query', 'excludeDeletedEntities', 'limit', 'offset', 'typeName', 'classification')) + Globals.searchApiCallRef = this.searchCollection.getBasicRearchResult(apiObj); + this.showHideFilter(); + } else { + apiObj.data = null; + Globals.searchApiCallRef = this.searchCollection.fetch(apiObj); + } + } else { + if (isPostMethod) { + apiObj['data'] = _.extend({}, filterObj, _.pick(this.searchCollection.queryParams, 'query', 'excludeDeletedEntities', 'limit', 'offset', 'typeName', 'classification')); + Globals.searchApiCallRef = this.searchCollection.getBasicRearchResult(apiObj); + } else { + apiObj.data = null; + Globals.searchApiCallRef = this.searchCollection.fetch(apiObj); + } + } + }, + renderSearchQueryView: function() { + var that = this; + require(['views/search/SearchQueryView'], function(SearchQueryView) { + that.RSearchQuery.show(new SearchQueryView({ + value: that.value, + searchVent: that.searchVent + })); }); }, renderTableLayoutView: function(col) { @@ -343,7 +428,7 @@ define(['require', col = {}; col['Check'] = { name: "selected", - label: "", + label: "Select", cell: "select-row", headerCell: "select-all" }; http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/tag/TagDetailLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/tag/TagDetailLayoutView.js b/dashboardv2/public/js/views/tag/TagDetailLayoutView.js index 3bb27c3..410c629 100644 --- a/dashboardv2/public/js/views/tag/TagDetailLayoutView.js +++ b/dashboardv2/public/js/views/tag/TagDetailLayoutView.js @@ -44,7 +44,8 @@ define(['require', * @constructs */ initialize: function(options) { - _.extend(this, _.pick(options, 'tag', 'collection', 'entityDefCollection', 'typeHeaders', 'enumDefCollection')); + _.extend(this, _.pick(options, 'tag', 'classificationDefCollection', 'entityDefCollection', 'typeHeaders', 'enumDefCollection')); + this.collection = this.classificationDefCollection; }, bindEvents: function() {}, onRender: function() { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/9a4ed469/dashboardv2/public/js/views/tag/TagLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/tag/TagLayoutView.js b/dashboardv2/public/js/views/tag/TagLayoutView.js index a5b5665..b8a1cd1 100644 --- a/dashboardv2/public/js/views/tag/TagLayoutView.js +++ b/dashboardv2/public/js/views/tag/TagLayoutView.js @@ -64,7 +64,7 @@ define(['require', bindEvents: function() { var that = this; this.listenTo(this.collection, "reset add remove", function() { - this.tagsAndTypeGenerator('collection'); + this.tagsGenerator(); }, this); this.ui.tagsParent.on('click', 'li.parent-node a', function() { that.setUrl(this.getAttribute("href")); @@ -147,7 +147,7 @@ define(['require', } } }, - tagsAndTypeGenerator: function(collection, searchString) { + tagsGenerator: function(searchString) { var that = this, str = ''; that.collection.fullCollection.comparator = function(model) { @@ -340,7 +340,7 @@ define(['require', }, offlineSearchTag: function(e) { var type = $(e.currentTarget).data('type'); - this.tagsAndTypeGenerator('collection', $(e.currentTarget).val()); + this.tagsGenerator($(e.currentTarget).val()); }, createTagAction: function() { var that = this;