Ver a proveniência

Search fixes (#2746)

* GS in awesome bar, UI fixes: scroll nav,lists

* awesome bar specificity

* Add fuzzy search in awesome bar

* Add fuzzy specific boldening

* List subtype buttons

* Update global_search.py
version-14
Prateeksha Singh há 8 anos
committed by Rushabh Mehta
ascendente
cometimento
e9f2aadd38
8 ficheiros alterados com 415 adições e 171 eliminações
  1. +3
    -3
      frappe/core/doctype/communication/communication.json
  2. +3
    -2
      frappe/email/doctype/contact/contact.json
  3. +24
    -6
      frappe/public/css/desk.css
  4. +204
    -101
      frappe/public/js/frappe/ui/toolbar/awesome_bar.js
  5. +2
    -0
      frappe/public/js/frappe/ui/toolbar/search.html
  6. +139
    -50
      frappe/public/js/frappe/ui/toolbar/search.js
  7. +38
    -8
      frappe/public/less/desk.less
  8. +2
    -1
      frappe/utils/global_search.py

+ 3
- 3
frappe/core/doctype/communication/communication.json Ver ficheiro

@@ -408,7 +408,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Communication Type",
@@ -759,7 +759,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Reference Name",
@@ -1379,7 +1379,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-02-17 16:41:05.429760",
"modified": "2017-02-21 04:57:33.141998",
"modified_by": "Administrator",
"module": "Core",
"name": "Communication",


+ 3
- 2
frappe/email/doctype/contact/contact.json Ver ficheiro

@@ -81,7 +81,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Last Name",
@@ -554,7 +554,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-01-31 00:15:30.298287",
"modified": "2017-02-20 14:54:33.723052",
"modified_by": "Administrator",
"module": "Email",
"name": "Contact",
@@ -805,6 +805,7 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0

+ 24
- 6
frappe/public/css/desk.css Ver ficheiro

@@ -687,8 +687,18 @@ fieldset[disabled] .form-control {
padding: 0px;
overflow-y: auto;
}
.search-dialog .layout-side-section {
padding-left: 15px;
.search-dialog .layout-side-section .help-link {
padding-top: 20px;
text-transform: uppercase;
}
.search-dialog .layout-side-section .nav > li > a {
padding-left: 20px;
}
.search-dialog .results-area a {
color: #5E64FF;
}
.search-dialog .results-area .single-link a {
color: #36414c;
}
.search-dialog .module-section .back-link {
margin-bottom: 20px;
@@ -698,11 +708,19 @@ fieldset[disabled] .form-control {
font-family: 'Octicons';
content: '\f0a4';
}
.search-dialog .dual-section .result a {
color: black;
.search-dialog .full-list .result {
border-bottom: 1px solid #d1d8dd;
margin-top: 10px;
}
.search-dialog .full-list .result .result-subtype{
float: right;
margin-left: 10px;
}
.search-dialog .dual-section .result a b {
color: #4e6161;
.search-dialog .full-list .section-head {
margin-bottom: 25px;
}
.search-dialog .dual-section .result-subtype {
display: none;
}
.search-dialog .result-status {
margin-top: 30px;


+ 204
- 101
frappe/public/js/frappe/ui/toolbar/awesome_bar.js Ver ficheiro

@@ -12,17 +12,21 @@ frappe.search.AwesomeBar = Class.extend({
this.nav = new frappe.search.NavSearch();
this.help = new frappe.search.HelpSearch();

this.options = [];
this.global_results = [];

var awesomplete = new Awesomplete(input, {
minChars: 0,
maxItems: 99,
autoFirst: true,
list: [],
filter: function (text, term) {
return true;
filter: function (text, term) {
return true;
},
data: function (item, input) {
var label = item.label + "%%%" + item.value + "%%%" +
(item.description || "") + "%%%" + (item.index || "");
var label = item.label + "%%%" + item.value + "%%%" +
(item.description || "") + "%%%" + (item.index || "")
+ "%%%" + (item.type || "") + "%%%" + (item.prefix || "");
return {
label: label,
value: item.value
@@ -31,9 +35,16 @@ frappe.search.AwesomeBar = Class.extend({
item: function(item, term) {
var d = item;
var parts = item.split("%%%"),
d = { label: parts[0], value: parts[1], description: parts[2] };
d = { label: parts[0], value: parts[1], description: parts[2],
type: parts[4], prefix: parts[5]};

var html = "<span>" + __(d.label || d.value) + "</span>";
if(d.prefix) {
var html = "<span>" + __((d.prefix + ' ' + d.label)) + "</span>";
} else if(d.type) {
var html = "<span>" + __((d.label + ' ' + d.type)) + "</span>";
} else {
var html = "<span>" + __(d.label || d.value) + "</span>";
}
if(d.description && d.value!==d.description) {
html += '<br><span class="text-muted">' + __(d.description) + '</span>';
}
@@ -42,29 +53,37 @@ frappe.search.AwesomeBar = Class.extend({
.html('<a style="font-weight:normal"><p>' + html + '</p></a>')
.get(0);
},
sort: function(a, b) {
sort: function(a, b) {
var a_index = a.split("%%%")[3];
var b_index = b.split("%%%")[3];
return (a_index - b_index);
return (a_index - b_index);
}
});

$input.on("input", function(e) {
var value = e.target.value;
var txt = value.trim().replace(/\s\s+/g, ' ');
var last_space = txt.lastIndexOf(' ');

if(txt && txt.length > 2) {
me.global.get_awesome_bar_options(txt.toLowerCase(), me);
}

var $this = $(this);
clearTimeout($this.data('timeout'));

$this.data('timeout', setTimeout(function(){
var value = e.target.value;
var txt = strip(value);
me.options = [];
if(txt) {
var keywords = strip(txt.toLowerCase());
me.build_options(keywords);
if(me.options.length < 2) {
me.global.get_awesome_bar_options(keywords, me);
if(txt && txt.length > 2) {
if(last_space !== -1) {
me.set_specifics(txt.slice(0,last_space), txt.slice(last_space+1));
}
me.options = me.options.concat(me.build_options(txt));
me.build_defaults(txt);
me.options = me.options.concat(me.global_results);
}

me.make_calculator(txt);
me.add_recent(txt || "");
me.add_help();

@@ -112,6 +131,7 @@ frappe.search.AwesomeBar = Class.extend({
}

if(item.onclick) {
// frappe.new_doc(item.match, true);
item.onclick(item.match);
} else {
var previous_hash = window.location.hash;
@@ -135,7 +155,8 @@ frappe.search.AwesomeBar = Class.extend({
this.options.push({
label: __("Help on Search"),
value: "Help on Search",
index: 20,
index: 50,
default: "Help",
onclick: function() {
var txt = '<table class="table table-bordered">\
<tr><td style="width: 50%">'+__("Make a new record")+'</td><td>'+
@@ -194,7 +215,8 @@ frappe.search.AwesomeBar = Class.extend({
out.label = match[0].bold();
out.value = match[0];
}
out.index = 10
out.index = 29;
out.default = "Recent";
return out;
}, true);
},
@@ -231,45 +253,106 @@ frappe.search.AwesomeBar = Class.extend({
setup_recent: function() {
this.recent = JSON.parse(frappe.boot.user.recent || "[]") || [];
},
is_present: function(txt, item) {
($.isArray(item)) ? _item = item[0] : _item = item;
_item = __(_item || '').toLowerCase().replace(/-/g, " ");
if(txt===_item || _item.indexOf(txt) !== -1) {
return item;

fuzzy_search: function(txt, _item, index) {
item = __(_item || '').toLowerCase().replace(/-/g, " ");

txt = txt.toLowerCase();

var ilen = item.length;
var tlen = txt.length;
var match_level1 = 0.5;
var match_level2 = 0.8;
var index = ((tlen/ilen) > match_level1) ? 24 : index;
var rendered_label = "";
var i, j, skips = 0, mismatches = 0;

if (tlen > ilen) {
return [];
}
if (item.indexOf(txt) !== -1) {
// prefer single words
index = (item.indexOf(' ') === -1) ? index-1 : index;
index = ((tlen/ilen) > match_level2) ? 21 : index;

var regEx = new RegExp("("+ txt +")", "ig");
rendered_label = _item.replace(regEx, '<b>$1</b>');

return [_item, index, rendered_label];
}
outer: for (i = 0, j = 0; i < tlen; i++) {
var t_ch = txt.charCodeAt(i);
if(mismatches !== 0) skips++;
if(skips > 3) return [];
mismatches = 0;
while (j < ilen) {
var i_ch = item.charCodeAt(j);
if (i_ch === t_ch) {
var item_char = _item.charAt(j);
if(item_char === item_char.toLowerCase()){
rendered_label += '<b>' + txt.charAt(i) + '</b>';
} else {
rendered_label += '<b>' + txt.charAt(i).toUpperCase() + '</b>';
}
j++;
continue outer;
}
mismatches++;
if(mismatches > 2) return [];
rendered_label += _item.charAt(j);
j++;
}
return [];
}
rendered_label += _item.slice(j);
return [_item, index + 10, rendered_label];
},

set_specifics: function(txt, end_txt) {
var me = this;
var results = this.build_options(txt);
results.forEach(function(r) {
if((r.type).toLowerCase().indexOf(end_txt.toLowerCase()) === 0) {
if(r.index < 25) {
r.index = 21;
}
me.options.push(r);
}
});
},

build_defaults: function(txt) {
this.make_global_search(txt);
this.make_search_in_current(txt);
this.options = this.options.concat(this.make_search_in_list(txt));
},

set_global_results: function(global_results){
this.options = this.options.concat(global_results);
build_options: function(txt) {
return this.make_new_doc(txt).concat(
this.get_doctypes(txt),
this.get_reports(txt),
this.get_pages(txt),
this.get_modules(txt)
);
},

build_options: function(txt) {
this.options =
this.make_global_search(txt).concat(
this.make_search_in_current(txt),
this.make_calculator(txt),
this.make_new_doc(txt),
this.make_search_in_list(txt),
this.get_doctypes(txt),
this.get_reports(txt),
this.get_pages(txt),
this.get_modules(txt)
);
set_global_results: function(global_results, txt){
this.global_results = this.global_results.concat(global_results);
},

make_global_search: function(txt) {
var me = this;
return [{
this.options.push({
label: __("Search for '" + txt.bold() + "'"),
value: __("Search for '" + txt + "'"),
match: txt,
index: 5,
index: 22,
default: "Search",
onclick: function() {
me.search.search_dialog.show();
me.search.setup_search(txt, [me.global, me.nav, me.help]);
}
}];
});
},

make_search_in_current: function(txt) {
@@ -280,17 +363,18 @@ frappe.search.AwesomeBar = Class.extend({
var search_field = meta.title_field || "name";
var options = {};
options[search_field] = ["like", "%" + txt + "%"];
return [{
this.options.push({
label: __('Find {0} in {1}', [txt.bold(), route[1].bold()]),
value: __('Find {0} in {1}', [txt, route[1]]),
route_options: options,
index: 10,
index: 23,
onclick: function() {
cur_list.refresh();
},
default: "Current",
match: txt
}];
} else { return []; }
});
}
},

make_calculator: function(txt) {
@@ -302,34 +386,37 @@ frappe.search.AwesomeBar = Class.extend({
try {
var val = eval(txt);
var formatted_value = __('{0} = {1}', [txt, (val + '').bold()]);
return [{
this.options.push({
label: formatted_value,
value: __('{0} = {1}', [txt, val]),
match: val,
index: 10,
index: 24,
default: "Calculator",
onclick: function() {
msgprint(formatted_value, "Result");
}
}];
});
} catch(e) {
// pass
}
} else { return []; }
}
},

make_new_doc: function(txt) {
make_search_in_list: function(txt) {
var me = this;
var out = [];
if(txt.split(" ")[0]==="new") {
frappe.boot.user.can_create.forEach(function (item) {
var target = me.is_present(txt.substr(4), item);
if(in_list(txt.split(" "), "in") && (txt.slice(-2) !== "in")) {
parts = txt.split(" in ");
frappe.boot.user.can_read.forEach(function (item) {
var target = me.fuzzy_search(parts[1], item, 21)[0];
if(target) {
out.push({
label: __("New {0}", [target.bold()]),
value: __("New {0}", [target]),
index: 10,
match: target,
onclick: function() { frappe.new_doc(target, true); }
label: __('Find {0} in {1}', [__(parts[0]).bold(), __(target).bold()]),
value: __('Find {0} in {1}', [__(parts[0]), __(target)]),
route_options: {"name": ["like", "%" + parts[0] + "%"]},
index: 21,
default: "In List",
route: ["List", target]
});
}
});
@@ -337,20 +424,23 @@ frappe.search.AwesomeBar = Class.extend({
return out;
},

make_search_in_list: function(txt) {
make_new_doc: function(txt) {
var me = this;
var out = [];
if(in_list(txt.split(" "), "in")) {
parts = txt.split(" in ");
frappe.boot.user.can_read.forEach(function (item) {
target = me.is_present(parts[1], item);
if(txt.split(" ")[0]==="new") {
frappe.boot.user.can_create.forEach(function (item) {
var result = me.fuzzy_search(txt.substr(4), item, 21);
var target = result[0];
var rendered_label = result[2];
if(target) {
out.push({
label: __('Find {0} in {1}', [__(parts[0]).bold(), __(target).bold()]),
value: __('Find {0} in {1}', [__(parts[0]), __(target)]),
route_options: {"name": ["like", "%" + parts[0] + "%"]},
index: 10,
route: ["List", target]
label: rendered_label,
value: __("New {0}", [target]),
index: 21,
type: "New",
prefix: "New",
match: target,
onclick: function() { frappe.new_doc(target, true); }
});
}
});
@@ -358,36 +448,38 @@ frappe.search.AwesomeBar = Class.extend({
return out;
},

get_doctypes: function(txt) {
get_doctypes: function(txt) {
var me = this;
var out = [];

var target, index;
var result, target, index, rendered_label;
var option = function(type, route) {
return {
label: __("{0} " + type, [__(target).bold()]),
label: rendered_label,
value: __(target),
route: route,
index: index,
match: target
match: target,
type: type
}
};
frappe.boot.user.can_read.forEach(function (item) {
target = me.is_present(txt, item);
result = me.fuzzy_search(txt, item, 25);
target = result[0];
index = result[1];
rendered_label = result[2];
if(target) {
var match_ratio = txt.length / item.length;
index = (match_ratio > 0.7) ? 10 : 12;

// include 'making new' option
if(in_list(frappe.boot.user.can_create, target)) {
out.push({
label: __("New {0}", [target.bold()]),
value: __("New {0}", [target]),
match: target,
index: 12,
onclick: function() { frappe.new_doc(target, true); }
});
}
// include 'making new' option (not working)
// if(in_list(frappe.boot.user.can_create, target)) {
// out.push({
// label: rendered_label,
// value: __("New {0}", [target]),
// index: index,
// type: "New",
// prefix: "New",
// onclick: function() { frappe.new_doc(target, true); }
// });
// }
if(in_list(frappe.boot.single_types, target)) {
out.push(option("", ["Form", target, target]));

@@ -395,7 +487,7 @@ frappe.search.AwesomeBar = Class.extend({
out.push(option("Tree", ["Tree", target]));

} else {
out.push(option("List", ["List", target]));
out.push(option("List", ["List", target]));
if(frappe.model.can_get_report(target)) {
out.push(option("Report", ["Report", target]));
}
@@ -414,11 +506,12 @@ frappe.search.AwesomeBar = Class.extend({
var me = this;
var out = [];
Object.keys(frappe.boot.user.all_reports).forEach(function(item) {
var target = me.is_present(txt, item);
var result = me.fuzzy_search(txt, item, 26);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
var report = frappe.boot.user.all_reports[target];
var match_ratio = txt.length / item.length;
var index = (match_ratio > 0.7) ? 10 : 13;
var route = [];
if(report.report_type == "Report Builder")
route = ["Report", report.ref_doctype, target];
@@ -426,10 +519,12 @@ frappe.search.AwesomeBar = Class.extend({
route = ["query-report", target];

out.push({
label: __("Report {0}", [__(target).bold()]),
label: rendered_label,
value: __("Report {0}" , [__(target)]),
match: txt,
index: index,
type: "Report",
prefix: "Report",
route: route
});
}
@@ -446,16 +541,19 @@ frappe.search.AwesomeBar = Class.extend({
p.name = name;
});
Object.keys(this.pages).forEach(function(item) {
var target = me.is_present(txt, item);
var result = me.fuzzy_search(txt, item, 27);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
var match_ratio = txt.length / item.length;
var index = (match_ratio > 0.7) ? 10 : 14;
var page = me.pages[target];
out.push({
label: __("Open {0}", [__(target).bold()]),
label: rendered_label,
value: __("Open {0}", [__(target)]),
match: txt,
index: index,
type: "Page",
prefix: "Open",
route: [page.route || page.name]
});
}
@@ -464,10 +562,12 @@ frappe.search.AwesomeBar = Class.extend({
var target = 'Calendar';
if(__('calendar').indexOf(txt.toLowerCase()) === 0) {
out.push({
label: __("Open {0}", [__(target).bold()]),
label: rendered_label,
value: __("Open {0}", [__(target)]),
route: [target, 'Event'],
index: 14,
index: 27,
type: "Calendar",
prefix: "Open",
match: target
});
}
@@ -478,17 +578,20 @@ frappe.search.AwesomeBar = Class.extend({
var me = this;
var out = [];
Object.keys(frappe.modules).forEach(function(item) {
var target = me.is_present(txt, item);
var result = me.fuzzy_search(txt, item, 28);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
var match_ratio = txt.length / item.length;
var index = (match_ratio > 0.7) ? 10 : 15;
var module = frappe.modules[target];
if(module._doctype) return;
ret = {
label: __("Open {0}", [__(target).bold()]),
label: rendered_label,
value: __("Open {0}", [__(target)]),
match: txt,
index: index
index: index,
type: "Module",
prefix: "Open"
}
if(module.link) {
ret.route = [module.link];


+ 2
- 0
frappe/public/js/frappe/ui/toolbar/search.html Ver ficheiro

@@ -1,5 +1,7 @@
<div class="row">
<div class="col-md-2 col-sm-2 hidden-xs layout-side-section search-sidebar">
<ul class="module-sidebar-nav overlay-sidebar nav nav-pills nav-stacked search-sidelist">
</ul>
</div>
<div class="col-md-10 col-sm-10 layout-main-section results-area">
</div>


+ 139
- 50
frappe/public/js/frappe/ui/toolbar/search.js Ver ficheiro

@@ -12,7 +12,7 @@ frappe.search.UnifiedSearch = Class.extend({
this.search_modal.addClass('search-dialog');

this.input = this.search_modal.find(".search-input");
this.sidebar = this.search_modal.find(".search-sidebar");
this.sidelist = this.search_modal.find(".search-sidelist");
this.results_area = this.search_modal.find(".results-area");
},

@@ -32,19 +32,19 @@ frappe.search.UnifiedSearch = Class.extend({
$this.data('timeout', setTimeout(function(){
var keywords = me.input.val();
me.reset();
if(keywords.length > 1) {
if(keywords.length > 2) {
me.build_results(keywords);
} else {
me.current_type = '';
}
}, 250));
}, 600));
});
this.build_results(keywords);
setTimeout(function() { me.input.select(); }, 500);
},

reset: function() {
this.sidebar.empty();
this.sidelist.empty();
this.results_area.empty();
},

@@ -59,7 +59,9 @@ frappe.search.UnifiedSearch = Class.extend({
render_results: function(results_obj, keywords){
var me = this;
if(this.current === 0) { this.reset() }
this.sidebar.append(results_obj.sidelist);
results_obj.sidelist.forEach(function(list_item) {
me.sidelist.append(list_item);
})
this.results_area.find('.results-status').remove();
results_obj.sections.forEach(function(section) {
me.summary.append(section);
@@ -70,18 +72,35 @@ frappe.search.UnifiedSearch = Class.extend({

bind_events: function() {
var me = this;
this.sidebar.find('.list-link').on('click', function() {
me.set_sidebar_link_action($(this));
this.results_area.on('scroll', function() {
if(me.results_area.find('.all-results-link').length !== 0) {
return;
}
var r = me.results_area.find('.module-section')[1];
me.results_area.find('.module-section').each(function() {
if(($(this).position().top < 120) && ($(this).position().top + $(this).height() > 120)) {
var types = $(this).attr('data-type').split(',');
me.sidelist.find('.list-link').removeClass('active');
types.forEach(function(type) {
me.sidelist.find('*[data-category="'+ type +'"]').addClass('active');
});
}
});
});
this.sidelist.find('.list-link').on('click', function() {
me.set_sidelist_link_action($(this));
});
this.results_area.find('.section-more').on('click', function() {
var type = $(this).attr('data-category');
me.sidebar.find('*[data-category="'+ type +'"]').trigger('click');
me.sidelist.find('*[data-category="'+ type +'"]').trigger('click');
});
},

set_sidebar_link_action: function(link) {
this.sidebar.find(".list-link a").removeClass("disabled");
link.find('a').addClass("disabled");
set_sidelist_link_action: function(link) {
this.sidelist.find(".list-link").removeClass("active");
this.sidelist.find(".list-link i").addClass("hide");
link.addClass("active");
link.find("i").removeClass("hide");
var type = link.attr('data-category');
this.results_area.empty().html(this.full_lists[type]);

@@ -101,6 +120,9 @@ frappe.search.UnifiedSearch = Class.extend({

show_summary: function() {
this.current_type = '';
this.sidelist.find(".list-link i").addClass("hide");
this.sidelist.find(".list-link").removeClass("active");
this.sidelist.find(".list-link").first().addClass("active");
this.results_area.empty().html(this.summary);
this.bind_events();
},
@@ -125,7 +147,7 @@ frappe.search.UnifiedSearch = Class.extend({
var no_of_results = this.results_area.find('.result').length;
var no_of_results_cue = $('<p class="results-status text-muted small">'+
no_of_results +' results found</p>');
this.results_area.find(".result:last").append(no_of_results_cue);
this.results_area.find(".more-results:last").append(no_of_results_cue);
}
this.results_area.find('.more-results.last').slideDown(200, function() {
var height = me.results_area.find('.module-body').height() - 750;
@@ -144,20 +166,20 @@ frappe.search.UnifiedSearch = Class.extend({
// More searches to go
this.search_objects[this.current].build_results_object(this, keywords);
} else {
// If there's only one link in sidebar, there's no summary (show its full list)
if(this.sidebar.find('.list-link').length === 1) {
// If there's only one link in sidelist, there's no summary (show its full list)
if(this.sidelist.find('.list-link').length === 1) {
this.bind_events();
this.sidebar.find('.list-link').trigger('click');
this.sidelist.find('.list-link').trigger('click');
this.results_area.find('.all-results-link').hide();

} else if (this.sidebar.find('.list-link').length === 0) {
} else if (this.sidelist.find('.list-link').length === 0) {
this.results_area.html('<p class="results-status text-muted" style="text-align: center;">'+
'No results found for: '+ "'"+ keywords +"'" +'</p>');
} else {
var list_types = this.get_all_list_types();
if(list_types.indexOf(this.current_type) >= 0) {
this.bind_events();
this.sidebar.find('*[data-category="'+ this.current_type +'"]').trigger('click');
this.sidelist.find('*[data-category="'+ this.current_type +'"]').trigger('click');
} else {
this.show_summary();
}
@@ -167,7 +189,7 @@ frappe.search.UnifiedSearch = Class.extend({

get_all_list_types: function() {
var types = [];
this.sidebar.find('.list-link').each(function() {
this.sidelist.find('.list-link').each(function() {
types.push($(this).attr('data-category'));
});
return types;
@@ -214,18 +236,16 @@ frappe.search.GlobalSearch = Class.extend({

make_sidelist: function() {
var me = this;
var sidelist = $('<ul class="list-unstyled sidebar-menu nav-list"></ul>');
sidelist.append('<li class="h6">'+ me.search_type +'</li>');
var sidelist = [];
this.types.forEach(function(type) {
sidelist.append(me.make_sidelist_item(type));
sidelist.push(me.make_sidelist_item(type));
});
sidelist.append('<li class="divider"></li>');
return sidelist;
},

make_sidelist_item: function(type) {
var sidelist_item = '<li class="list-link" data-search="{0}"' +
'data-category="{1}"><a>{1}</a></li>';
var sidelist_item = '<li class="strong module-sidebar-item list-link" data-search="{0}"' +
'data-category="{1}"><a><span>{1}</span><i class="fa fa-chevron-right pull-right hide"></a></li>';
return $(__(sidelist_item, [this.search_type, type]));
},

@@ -319,7 +339,7 @@ frappe.search.GlobalSearch = Class.extend({

make_section: function(type, results) {
var me = this;
var results_section = $('<div class="row module-section '+type+'-section">'+
var results_section = $('<div class="row module-section" data-type="'+type+'">'+
'<div class="col-sm-12 module-section-column">' +
'<div class="h4 section-head">'+type+'</div>' +
'<div class="section-body"></div>'+
@@ -329,27 +349,53 @@ frappe.search.GlobalSearch = Class.extend({
results_col.append(me.make_result_item(type, result));
});
if(results.length > this.section_length) {
results_col.append('<a class="small section-more" data-category="'
+ type + '">More...</a>');
results_col.append('<button class="btn btn-default btn-xs text-muted section-more" data-category="'
+ type + '" style="margin-top:10px">More...</button>');

}
return results_section;
},

make_result_subtypes_property: function(results) {
var compressed_results = [];
var labels = [];
results.forEach(function(r) {
if(labels.indexOf(r.label) === -1) {
labels.push(r.label);
}
});
labels.forEach(function(l) {
var item_group = {
title: l,
subtypes: []
};
results.forEach(function(r) {
if (r.label === l) {
item_group.subtypes.push(r);
}
});
compressed_results.push(item_group);
});
return compressed_results;
},

make_full_list: function(type, results, more) {
var me = this;
var results_list = $(' <div class="module-body"><div class="row module-section '+
var results_list = $(' <div class="module-body"><div class="row module-section full-list '+
type+'-section">'+'<div class="col-sm-12 module-section-column">' +
'<div class="back-link"><a class="all-results-link small"> All Results</a></div>' +
'<div class="h4 section-head">'+type+'</div>' +
'<div class="section-body"></div>'+
'</div></div></div>');
'<div class="section-body"></div></div></div></div>');
if(type === "Lists") {
results = this.make_result_subtypes_property(results);
}
var results_col = results_list.find('.module-section-column');
results.forEach(function(result) {
results_col.append(me.make_result_item(type, result));
});
if(more) {
results_col.append('<a class="small list-more" data-search="'+ this.search_type +'" data-category="'
+ type + '">More...</a>');
results_col.append('<button class="btn btn-default btn-xs text-muted list-more" data-search="'+
this.search_type +'" data-category="'+ type + '" style="margin-top:10px"> More...</button>');
}
return results_list;
},
@@ -386,7 +432,6 @@ frappe.search.GlobalSearch = Class.extend({
},

get_awesome_bar_options: function(keywords, ref) {

var me = this;
var doctypes = [];
var current = 0;
@@ -426,7 +471,7 @@ frappe.search.GlobalSearch = Class.extend({
if(current < doctypes.length) {
get_results();
} else {
ref.set_global_results(results);
ref.set_global_results(results, keywords);
}
}
}
@@ -434,13 +479,13 @@ frappe.search.GlobalSearch = Class.extend({
};

var make_option = function(data) {
console.log("GS search", me.get_finds(data.content, keywords).slice(0,86) + '...');
return {
label: __("{0}: {1}", [__(data.doctype).bold(), data.name]),
value: __("{0}: {1}", [__(data.doctype), data.name]),
route: ["Form", data.doctype, data.name],
match: data.doctype,
index: 5,
index: 41,
default: "Global",
description: me.get_finds(data.content, keywords).slice(0,86) + '...'
}
};
@@ -455,7 +500,6 @@ frappe.search.NavSearch = frappe.search.GlobalSearch.extend({
init: function() {
this.search_type = 'Navigation';
},

set_types: function() {
var me = this;
this.section_length = 4;
@@ -520,9 +564,47 @@ frappe.search.NavSearch = frappe.search.GlobalSearch.extend({
},

make_result_item: function(type, result) {
var link_html = '<div class="result '+ type +'-result single-link">' +
'<a href="{0}" class="module-section-link small">{1}</a>' +
'<p class="small"></p></div>';
if(!result.subtypes) {
var link_html = '<div class="result '+ type +'-result single-link">' +
'<a href="{0}" class="module-section-link small">{1}</a>' +
'<p class="small"></p></div>';
return this.make_result_link(type, result, link_html);

} else {
var result_div = $('<div class="result '+ type +'-result single-link"></div>');
var button_html = '<button class="btn btn-default btn-xs text-muted result-subtype"'+
'>{0}</button>'
result.subtypes.forEach(function(s) {
if(["Gantt", "Report", "Calendar"].indexOf(s.type) !== -1) {
var button = $(__(button_html, [s.type]));
button.on('click', function() {
if(s.route_options) {
frappe.route_options = s.route_options;
}
frappe.set_route(s.route);
return false;
});
result_div.append(button);
} else {
title_link_html = '<a href="{0}" class="module-section-link small">{1}</a>';
var link = $(__(title_link_html, ['#', result.title + ' ' + s.type]));
link.on('click', function() {
if(s.route_options) {
frappe.route_options = s.route_options;
}
frappe.set_route(s.route);
return false;
});
result_div.append(link);
}
})
result_div.append($('<p class="small"></p>'));
return result_div;
}

},

make_result_link: function(type, result, link_html) {
if(!result.onclick) {
var link = $(__(link_html, ['#', result.label]));
link.on('click', function() {
@@ -545,9 +627,14 @@ frappe.search.NavSearch = frappe.search.GlobalSearch.extend({

make_dual_sections: function() {
this.dual_sections = [];
var section_html = '<div class="row module-section dual-section"></div>';
for(var i = 0; i < this.sections.length; i++) {
var results_section = $(section_html);
var types;
if(i+1 < this.types.length) {
types = this.types[i] + ',' + this.types[i+1];
} else {
types = this.types[i];
}
var results_section = $('<div class="row module-section dual-section" data-type="'+ types +'"></div>');
for(var j = 0; j < 2 && i < this.sections.length; j++, i++){
results_section.append(this.sections[i]);
}
@@ -574,12 +661,15 @@ frappe.search.NavSearch = frappe.search.GlobalSearch.extend({
'<div class="h4 section-head">'+type+'</div>' +
'<div class="section-body"></div>'+
'</div>');
if(type === "Lists") {
results = this.make_result_subtypes_property(results);
}
results.slice(0, this.section_length).forEach(function(result) {
results_column.append(me.make_result_item(type, result));
});
if(results.length > this.section_length) {
results_column.append('<a class="small section-more" data-category="'
+ type + '">More...</a>');
results_column.append('<button class="btn btn-default btn-xs text-muted section-more" data-category="'
+ type + '" style="margin-top:10px">More...</button>');
}
return results_column;
}
@@ -597,12 +687,11 @@ frappe.search.HelpSearch = frappe.search.GlobalSearch.extend({
},

make_sidelist: function() {
var sidelist = $('<ul class="list-unstyled sidebar-menu nav-list"></ul>');
var sidelist_item = '<li class="h6 list-link" data-search="'+ this.search_type + '"' +
'data-category="'+ this.search_type + '"><a style="font-size: 11px;">'+
this.search_type +'</a></li>';
sidelist.append(sidelist_item);
sidelist.append('<li class="divider"></li>');
var sidelist = [];
var sidelist_item = '<li class="strong module-sidebar-item list-link help-link" '+
'data-search="'+ this.search_type + '" data-category="'+ this.search_type + '"><a><span>'+
this.search_type +'</span><i class="fa fa-chevron-right pull-right hide"></a></li>';
sidelist.push(sidelist_item);
return sidelist;
},



+ 38
- 8
frappe/public/less/desk.less Ver ficheiro

@@ -563,12 +563,26 @@ textarea.form-control {
}

.layout-side-section {
padding-left: 15px;
.help-link {
padding-top: 20px;
text-transform: uppercase;
}

.nav > li > a {
padding-left: 20px;
}
}

.results-area {
a {
color: #5E64FF;
}

.single-link a {
color: #36414c;
}
}

// .results-area a {
// color: #5E64FF;
// }
.module-section {
.back-link {
margin-bottom: 20px;
@@ -580,13 +594,29 @@ textarea.form-control {
content: '\f0a4';
}
}
.dual-section .result a {
color: black;

.full-list {
.result {
border-bottom: 1px solid #d1d8dd;
margin-top: 10px;

.result-subtype{
float: right;
margin-left: 10px;
}
}

.section-head {
margin-bottom: 25px;
}
}

.dual-section .result a b{
color: #4e6161;
.dual-section {
.result-subtype{
display: none;
}
}

.result-status {
margin-top: 30px;
text-align: center;


+ 2
- 1
frappe/utils/global_search.py Ver ficheiro

@@ -148,4 +148,5 @@ def search_in_doctype(doctype, text, start, limit):
doctype = %s AND
match(content) against (%s IN BOOLEAN MODE)
limit {start}, {limit}'''.format(start=start, limit=limit), (doctype, text), as_dict=True)
return results

return results

Carregando…
Cancelar
Guardar