Commit b9779eca by kevalbhatt

ATLAS-1608 :Search UI improvement

parent 670a4c00
......@@ -255,3 +255,8 @@
.ui-pnotify-text {
word-break: break-all;
}
.advancedInfo{
margin-left: 5px;
cursor: pointer;
}
\ No newline at end of file
......@@ -19,68 +19,65 @@
//colors
$color_celeste_approx: #1D1F2B;
$switchTransition: .4s ease-out;
@mixin transition($transition...) {
-webkit-transition: $transition;
-moz-transition: $transition;
-o-transition: $transition;
transition: $transition;
-webkit-transition: $transition;
-moz-transition: $transition;
-o-transition: $transition;
transition: $transition;
}
@mixin transition-property($properties...) {
-webkit-transition-property: $properties;
-moz-transition-property: $properties;
-o-transition-property: $properties;
transition-property: $properties;
-webkit-transition-property: $properties;
-moz-transition-property: $properties;
-o-transition-property: $properties;
transition-property: $properties;
}
.switch {
position: relative;
width: 50px;
height: 22px;
margin-left: 8px;
padding: 3px;
vertical-align: top;
background-color: $color_celeste_approx;
border-radius: 18px;
cursor: pointer;
position: relative;
width: 50px;
height: 22px;
margin-left: 8px;
padding: 3px;
vertical-align: top;
background-color: $color_celeste_approx;
border-radius: 18px;
cursor: pointer;
}
.switch-input {
position: absolute;
top: 0;
left: 0;
opacity: 0;
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
.switch-slider {
position: absolute;
top: 1px;
left: 3px;
width: 16px;
height: 16px;
border-radius: 10px;
box-shadow: 1px 1px 5px rgba(black, .2);
@include transition(left #{$switchTransition});
&:before {
content: '';
position: absolute;
top: 50%;
left: 50%;
margin: -6px 0 0 -8px;
top: 1px;
left: 3px;
width: 16px;
height: 16px;
background-color: $color_jungle_green_approx;
border-radius: 10px;
box-shadow: inset 0 1px rgba(black, .02);
@include transition(inherit)
}
.switch-input:checked ~ & {
left: 30px;
box-shadow: -1px 1px 5px rgba(black, .2);
}
box-shadow: 1px 1px 5px rgba(black, .2);
@include transition(left #{$switchTransition});
&:before {
content: '';
position: absolute;
top: 50%;
left: 50%;
margin: -6px 0 0 -8px;
width: 16px;
height: 16px;
background-color: $color_jungle_green_approx;
border-radius: 10px;
box-shadow: inset 0 1px rgba(black, .02);
@include transition(inherit)
}
.switch-input:checked ~ & {
left: 30px;
box-shadow: -1px 1px 5px rgba(black, .2);
}
}
.advanceSearchBtn {
......@@ -109,3 +106,11 @@ $switchTransition: .4s ease-out;
.btnAssign {
margin-bottom: 15px;
}
.srchType {
margin: 5px 0px;
.srchTitle {
font-size: 14px;
color: $gray
}
}
......@@ -37,11 +37,7 @@ define(['require',
parseRecords: function(resp, options) {
this.queryType = resp.queryType;
this.queryText = resp.queryText;
if (resp.queryType && resp.queryType == "DSL") {
return resp.entities ? resp.entities : [];
} else {
return resp.fullTextResult ? resp.fullTextResult : [];
}
return resp.entities ? resp.entities : [];
},
},
//Static Class Members
......
......@@ -29,7 +29,7 @@ define([
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'': 'commonAction',
'': 'defaultAction',
'!/': 'tagAttributePageLoad',
'!/tag/tagAttribute/(*name)': 'tagAttributePageLoad',
'!/taxonomy/detailCatalog/(*url)': 'detailCatalog',
......@@ -243,31 +243,20 @@ define([
'value': paramObj,
'entityDefCollection': that.entityDefCollection,
'typeHeaders': that.typeHeaders,
'initialView': paramObj.query.trim().length === 0
'initialView': (paramObj.query.trim() || paramObj.type || (paramObj.dslChecked == "true" ? "" : paramObj.tag)).length === 0
}));
});
},
defaultAction: function(actions) {
// We have no matching route, lets just log what the URL was
if (Globals.taxonomy) {
Utils.setUrl({
url: '#!/taxonomy',
mergeBrowserUrl: false,
updateTabState: function() {
return { taxonomyUrl: this.url, stateChanged: false };
},
trigger: true
});
} else {
Utils.setUrl({
url: '#!/tag',
mergeBrowserUrl: false,
updateTabState: function() {
return { tagUrl: this.url, stateChanged: false };
},
trigger: true
});
}
Utils.setUrl({
url: '#!/search',
mergeBrowserUrl: false,
updateTabState: function() {
return { searchUrl: this.url, stateChanged: false };
},
trigger: true
});
console.log('No route:', actions);
}
......
......@@ -19,11 +19,11 @@
<a href="index.html"><i class="fa fa-globe"></i> Apache Atlas</a>
</li>
<ul class="tabs" style="width: 100%;" role="tablist">
<li role="presentation" class="{{tabClass}}"><a href="#tab-tag" aria-controls="tab-tag" data-name="tab-tag" role="tab" data-toggle="tab">Tags</a></li>
<li role="presentation" class="{{tabClass}}"><a href="#tab-search" aria-controls="tab-search" data-name="tab-search" role="tab" data-toggle="tab" class=""><i class="fa fa-search"></i> Search</a></li>
<li role="presentation" class="{{tabClass}}"><a href="#tab-tag" aria-controls="tab-tag" data-name="tab-tag" role="tab" data-toggle="tab"><i class="fa fa-tags"></i> Tags</a></li>
{{#if taxonomy}}
<li role="presentation" class="tab col-sm-4"><a href="#tab-taxonomy" aria-controls="tab-taxonomy" data-name="tab-taxonomy" role="tab" data-toggle="tab" class="">Taxonomy</a></li>
<li role="presentation" class="tab col-sm-4"><a href="#tab-taxonomy" aria-controls="tab-taxonomy" data-name="tab-taxonomy" role="tab" data-toggle="tab" class=""><i class="fa fa-sitemap"></i> Taxonomy</a></li>
{{/if}}
<li role="presentation" class="{{tabClass}}"><a href="#tab-search" aria-controls="tab-search" data-name="tab-search" role="tab" data-toggle="tab" class=""><i class="fa fa-search"></i> Search</a></li>
</ul>
</ul>
<div class="tab-content">
......
<!--
* 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 class="">
<h4>Use DSL (Doamin Specific Language) to build queries</h4>
<ul>
<li><b>Entity Name</b></li>
<li>name="string"</li>
</ul>
<ul>
<li><b>Joining queries</b></li>
<li>name="sales_fact",columns as column select column.name</li>
</ul>
<ul>
<li><b>Query Name</b></li>
<li>Query Example</li>
</ul>
<ul>
<li><b>Query Name</b></li>
<li>Query Example</li>
</ul>
<ul>
<a href="http://atlas.incubator.apache.org/Search.html" target="_blank">More sample queries and use-cases >></a>
</ul>
</div>
......@@ -17,29 +17,41 @@
<div class="row row-margin-bottom">
<div class="col-sm-12" style="margin:15px 0px;">
<div class="row">
<div class="col-md-6">
<span class="pull-left">Text</span>
<div class="col-md-9" style="margin-top: 5px;">
<span class="pull-left">Basic</span>
<label class="switch pull-left">
<input type="checkbox" class="switch-input" name="queryType" value="text" />
<span class="switch-slider"></span>
</label>
<span class="pull-left">DSL</span>
<span class="pull-left">Advanced</span>
<span class="advancedInfo" data-id="advancedInfo"><i class="fa fa-question-circle-o"></i></span>
</div>
<div class="col-md-6">
<div class="col-md-3">
<button type="button" class="btn btn-atlasAction btn-atlas pull-right typeLOV" title="Refresh" data-id="refreshBtn"><i class="fa fa-refresh"></i></button>
</div>
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<div class="typeLOV">
<select data-id="typeLOV"></select>
<div class="srchType">
<span class="srchTitle">Search By Type</span>
<div class="typeLOV">
<select data-id="typeLOV"></select>
</div>
</div>
<div class="searchInputClick">
<input type="text" class="form-control" data-id="searchInput" placeholder="Search using a query string: e.g. sales_fact" style="margin-top: 5px;">
<div class="srchType tagBox">
<span class="srchTitle">Search By Tag</span>
<div class="typeLOV">
<select data-id="tagLOV"></select>
</div>
</div>
<div class="srchType">
<span class="srchTitle">Search By Query</span>
<input type="text" class="form-control" data-id="searchInput" placeholder="Search using a query string: e.g. sales_fact" style="margin: 5px 0px;">
</div>
</div>
<div class="clearAdvanceSearch" data-id="clearSearch">Clear</div>
<button type="button" class="btn btn-atlas advanceSearchBtn" data-id="searchBtn" disabled="disabled">Search</button>
</div>
<div id="searchResult"></div>
</div>
......@@ -34,9 +34,9 @@
<div id="r_searchResultTableLayoutView">
{{#if entityCreate}}
<div class="entityLink" style="display:none">
<h1><b>Atlas Search</b></h1>
<h1><b>{{searchType}}</b></h1>
<p class="entityLink">Search Atlas for existing entities or
<a href="javascript:void(0)" data-id='createEntity'> create new entity </a><i class="fa fa-question-circle" aria-hidden="true"></i>
<a href="javascript:void(0)" data-id='createEntity'> create new entity </a>
</p>
</div>
{{/if}}
......
......@@ -44,7 +44,7 @@ define(['require'], function(require) {
Enums.searchUrlType = {
DSL: 'dsl',
FULLTEXT: 'fulltext'
FULLTEXT: 'basic'
}
return Enums;
......
......@@ -111,13 +111,13 @@ define(['require',
});
},
selectTab: function() {
if (Utils.getUrlState.isTagTab() || (Utils.getUrlState.isInitial() && !Globals.taxonomy)) {
if (Utils.getUrlState.isTagTab()) {
this.$('.tabs').find('li a[aria-controls="tab-tag"]').parents('li').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('div#tab-tag').addClass('active').siblings().removeClass('active');
} else if (Utils.getUrlState.isTaxonomyTab() || (Utils.getUrlState.isInitial() && Globals.taxonomy)) {
} else if (Utils.getUrlState.isTaxonomyTab()) {
this.$('.tabs').find('li a[aria-controls="tab-taxonomy"]').parents('li').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('div#tab-taxonomy').addClass('active').siblings().removeClass('active');
} else if (Utils.getUrlState.isSearchTab() || (Utils.getUrlState.isDetailPage())) {
} else if (Utils.getUrlState.isSearchTab() || (Utils.getUrlState.isDetailPage()) || Utils.getUrlState.isInitial()) {
this.$('.tabs').find('li a[aria-controls="tab-search"]').parents('li').addClass('active').siblings().removeClass('active');
this.$('.tab-content').find('div#tab-search').addClass('active').siblings().removeClass('active');
}
......
......@@ -338,7 +338,7 @@ define(['require',
var dataURL = this.$('.taxonomyTree').find('li[data-id="Parent"]').find("a").data('href');
if (dataURL) {
this.url = dataURL;
if (this.viewBased) {
if (this.viewBased && Utils.getUrlState.isTaxonomyTab()) {
Utils.setUrl({
url: "#!/taxonomy/detailCatalog" + dataURL,
mergeBrowserUrl: false,
......
/**
* 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/AdvancedSearchInfo_tmpl',
], function(require, Backbone, AdvancedSearchInfoTmpl) {
var AdvancedSearchInfoView = Backbone.Marionette.LayoutView.extend(
/** @lends AdvancedSearchInfoView */
{
_viewName: 'AdvancedSearchInfoView',
template: AdvancedSearchInfoTmpl,
/** Layout sub regions */
regions: {},
/** ui selector cache */
ui: {
},
/** ui events hash */
events: function() {
var events = {};
return events;
},
/**
* intialize a new AdvancedSearchInfoView Layout
* @constructs
*/
initialize: function(options) {
},
bindEvents: function() {},
onRender: function() {
},
});
return AdvancedSearchInfoView;
});
......@@ -53,16 +53,10 @@ define(['require',
var that = this;
require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) {
var value = {};
if (that.value) {
value = {
'query': that.value.query,
'searchType': that.value.searchType
};
}
if (that.RSearchResultLayoutView) {
that.RSearchResultLayoutView.show(new SearchResultLayoutView({
value: value,
value: that.value,
tag: that.tag,
initialView: that.initialView,
entityDefCollection: that.entityDefCollection,
......
......@@ -63,7 +63,8 @@ define(['require',
},
templateHelpers: function() {
return {
entityCreate: Globals.entityCreate
entityCreate: Globals.entityCreate,
searchType: this.searchType
};
},
/** ui events hash */
......@@ -147,6 +148,10 @@ define(['require',
this.bindEvents();
this.bradCrumbList = [];
this.arr = [];
this.searchType = 'Basic Search';
if (this.value && this.value.searchType && this.value.searchType == 'dsl') {
this.searchType = 'Advanced Search';
}
},
bindEvents: function() {
var that = this;
......@@ -160,11 +165,7 @@ define(['require',
this.searchCollection.find(function(item) {
if (item.get('isEnable')) {
var term = [];
if (that.searchCollection.queryType == "DSL") {
var obj = item.toJSON();
} else {
var obj = item.get('entity');
}
var obj = model.toJSON();
that.arr.push({
id: obj.guid,
model: obj
......@@ -202,7 +203,7 @@ define(['require',
} else {
value = {
'query': '',
'searchType': 'fulltext'
'searchType': 'basic'
};
}
this.fetchCollection(value);
......@@ -223,9 +224,6 @@ define(['require',
},
fetchCollection: function(value) {
var that = this;
if (value && (value.query === undefined || value.query.trim() === "")) {
return;
}
this.showLoader();
if (Globals.searchApiCallRef && Globals.searchApiCallRef.readyState === 1) {
Globals.searchApiCallRef.abort();
......@@ -240,7 +238,7 @@ define(['require',
if (Utils.getUrlState.isTagTab()) {
this.searchCollection.url = UrlLinks.searchApiUrl(Enums.searchUrlType.DSL);
}
_.extend(this.searchCollection.queryParams, { 'query': value.query.trim() });
_.extend(this.searchCollection.queryParams, { 'query': value.query.trim() || null, 'type': value.type || null, 'classification': value.tag || null });
}
Globals.searchApiCallRef = this.searchCollection.fetch({
skipDefaultError: true,
......@@ -293,7 +291,7 @@ define(['require',
if (Globals.taxonomy) {
multiAssignDataTerm = '<a href="javascript:void(0)" class="inputAssignTag multiSelect" style="display:none" data-id="addTerm"><i class="fa fa-folder-o"></i>' + " " + 'Assign Term</a>';
}
if (Globals.entityCreate && (resultText.indexOf("\`") != 0) && Globals.entityTypeConfList) {
if (Globals.entityCreate && Globals.entityTypeConfList) {
createEntityTag = "<p>If you do not find the entity in search result below then you can" + '<a href="javascript:void(0)" data-id="createEntity"> create new entity</a></p>';
}
that.$('.searchResult').html(resultData + multiAssignDataTag + multiAssignDataTerm + createEntityTag);
......@@ -349,14 +347,9 @@ define(['require',
className: "searchTableName",
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
if (that.searchCollection.queryType == "DSL") {
var obj = model.toJSON();
} else {
var obj = model.get('entity');
}
var nameHtml = "";
var name = Utils.getName(obj);
var obj = model.toJSON(),
nameHtml = "",
name = Utils.getName(obj);
if (obj.guid) {
nameHtml = '<a title="' + name + '" href="#!/detailPage/' + obj.guid + '">' + name + '</a>';
} else {
......@@ -388,11 +381,7 @@ define(['require',
sortable: false,
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
if (that.searchCollection.queryType == "DSL") {
var obj = model.toJSON();
} else {
var obj = model.get('entity');
}
var obj = model.toJSON();
if (obj && obj.attributes && obj.attributes.description) {
return obj.attributes.description;
}
......@@ -406,11 +395,7 @@ define(['require',
sortable: false,
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
if (that.searchCollection.queryType == "DSL") {
var obj = model.toJSON();
} else {
var obj = model.get('entity');
}
var obj = model.toJSON();
if (obj && obj.typeName) {
return '<a title="Search ' + obj.typeName + '" href="#!/search/searchResult?query=' + obj.typeName + ' &searchType=dsl&dslChecked=true">' + obj.typeName + '</a>';
}
......@@ -424,11 +409,7 @@ define(['require',
sortable: false,
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
if (that.searchCollection.queryType == "DSL") {
var obj = model.toJSON();
} else {
var obj = model.get('entity');
}
var obj = model.toJSON();
if (obj && obj.attributes && obj.attributes.owner) {
return obj.attributes.owner;
}
......@@ -444,11 +425,7 @@ define(['require',
className: 'searchTag',
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
if (that.searchCollection.queryType == "DSL") {
var obj = model.toJSON();
} else {
var obj = model.get('entity');
}
var obj = model.toJSON();
if (obj.status && Enums.entityStateReadOnly[obj.status]) {
return '<div class="readOnly">' + CommonViewFunction.tagForTable(obj); + '</div>';
} else {
......@@ -468,11 +445,7 @@ define(['require',
className: 'searchTerm',
formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
fromRaw: function(rawValue, model) {
if (that.searchCollection.queryType == "DSL") {
var obj = model.toJSON();
} else {
var obj = model.get('entity');
}
var obj = model.toJSON();
var returnObject = CommonViewFunction.termTableBreadcrumbMaker(obj);
if (returnObject.object) {
that.bradCrumbList.push(returnObject.object);
......@@ -509,21 +482,13 @@ define(['require',
var that = this;
if (!multiple || multiple.length === 0) {
var modal = this.searchCollection.find(function(item) {
if (that.searchCollection.queryType == "DSL") {
var obj = item.toJSON();
} else {
var obj = item.get('entity');
}
var obj = model.toJSON();
if (obj.guid === guid) {
return true;
}
});
if (modal) {
if (that.searchCollection.queryType == "DSL") {
var obj = modal.toJSON();
} else {
var obj = modal.get('entity');
}
var obj = model.toJSON();
} else {
return [];
}
......
......@@ -55,8 +55,7 @@ define(['require',
var that = this;
require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) {
var value = {
'query': "`" + that.tag + "`",
'type': 'dsl'
'query': "`" + that.tag + "`"
};
that.RSearchResultLayoutView.show(new SearchResultLayoutView({
value: value,
......
......@@ -96,7 +96,7 @@ define(['require',
}
},
setValues: function(manual) {
if (Utils.getUrlState.isTagTab() || (Utils.getUrlState.isInitial() && !Globals.taxonomy)) {
if (Utils.getUrlState.isTagTab()) {
if (!this.tag) {
this.selectFirst = false;
this.ui.tagsParent.find('li').first().addClass('active');
......
......@@ -9,6 +9,12 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES:
ATLAS-1608 :Search UI improvement (kevalbhatt)
ATLAS-1630: basic search implementation (#2)
ATLAS-1630: basic search implementation using fulltext with support for filter by type & classification
ATLAS-1629: updated copyright date in NOTICE file
ATLAS-1627: fix for missed update to full-text index attribute on entity-update
ATLAS-1626: updated Atlas type-load to be resilient to incorrect constraints in the store (from earlier version env)
ATLAS-1628 Restrict user from entering text in datepicker input (kevalbhatt)
ATLAS-1538 Make AtlasLdapAuthenticationProvider like Ranger for OpenLdap type (nixonrodrigues via kevalbhatt)
ATLAS-1605 Edit Entity in UI : Update button is not enabled when updating attribute of type date (Kalyanikashikar via kevalbhatt)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment