Commit 503c9dda authored by Nabin Hait's avatar Nabin Hait
Browse files

Merge branch 'develop'

parents eb6bd89c eb165fb7
develop v11.1.5 v11.1.4 v11.1.3 v11.1.2 v11.1.1 v11.1.0 v11.0.3 v11.0.3-beta.51 v11.0.3-beta.50 v11.0.3-beta.49 v11.0.3-beta.48 v11.0.3-beta.47 v11.0.3-beta.46 v11.0.3-beta.45 v11.0.3-beta.44 v11.0.3-beta.43 v11.0.3-beta.42 v11.0.3-beta.41 v11.0.3-beta.40 v11.0.3-beta.39 v11.0.3-beta.38 v11.0.3-beta.37 v11.0.3-beta.36 v11.0.3-beta.35 v11.0.3-beta.34 v11.0.3-beta.33 v11.0.3-beta.32 v11.0.3-beta.31 v11.0.3-beta.30 v11.0.3-beta.29 v11.0.3-beta.28 v11.0.3-beta.27 v11.0.3-beta.26 v11.0.3-beta.25 v11.0.3-beta.24 v11.0.3-beta.23 v11.0.3-beta.22 v11.0.3-beta.21 v11.0.3-beta.20 v11.0.3-beta.19 v11.0.3-beta.18 v11.0.3-beta.17 v11.0.3-beta.16 v11.0.3-beta.15 v11.0.3-beta.14 v11.0.3-beta.13 v11.0.3-beta.12 v11.0.3-beta.11 v11.0.3-beta.10 v11.0.3-beta.9 v11.0.3-beta.8 v11.0.3-beta.7 v11.0.3-beta.6 v11.0.3-beta.5 v11.0.3-beta.4 v11.0.3-beta.3 v11.0.3-beta.2 v11.0.3-beta.1 v11.0.2 v11.0.1 v11.0.0-beta v10.1.71 v10.1.70 v10.1.69 v10.1.68 v10.1.67 v10.1.66 v10.1.65 v10.1.64 v10.1.63 v10.1.62 v10.1.61 v10.1.60 v10.1.59 v10.1.58 v10.1.57 v10.1.56 v10.1.55 v10.1.54 v10.1.53 v10.1.52 v10.1.51 v10.1.50 v10.1.49 v10.1.49-beta.1 v10.1.48 v10.1.47 v10.1.46 v10.1.45 v10.1.44 v10.1.43 v10.1.42 v10.1.41 v10.1.40 v10.1.39 v10.1.38 v10.1.37 v10.1.36 v10.1.35 v10.1.34 v10.1.33 v10.1.32 v10.1.31 v10.1.30 v10.1.29 v10.1.28 v10.1.27 v10.1.26 v10.1.25 v10.1.24 v10.1.23 v10.1.22 v10.1.21 v10.1.20 v10.1.19 v10.1.18 v10.1.17 v10.1.16 v10.1.15 v10.1.14 v10.1.13 v10.1.12 v10.1.11 v10.1.10 v10.1.9 v10.1.8 v10.1.7 v10.1.6 v10.1.5 v10.1.4 v10.1.3 v10.1.2 v10.1.1 v10.1.0 v10.0.25 v10.0.24 v10.0.23 v10.0.22 v10.0.21 v10.0.20 v10.0.19 v10.0.18 v10.0.17 v10.0.16 v10.0.15 v10.0.14 v10.0.13 v10.0.12 v10.0.11 v10.0.10 v10.0.9 v10.0.8 v10.0.7 v10.0.6 v10.0.5 v10.0.4 v10.0.3 v10.0.2 v10.0.1 v10.0.0 v9.2.25 v9.2.24 v9.2.23 v9.2.22 v9.2.21 v9.2.20 v9.2.19 v9.2.18 v9.2.17 v9.2.16 v9.2.15 v9.2.14 v9.2.13 v9.2.12 v9.2.11 v9.2.10 v9.2.9 v9.2.8 v9.2.7 v9.2.6 v9.2.5 v9.2.4 v9.2.3 v9.2.2 v9.2.1 v9.2.0 v9.1.11 v9.1.10 v9.1.9 v9.1.8 v9.1.7 v9.1.6 v9.1.5 v9.1.4 v9.1.3 v9.1.2 v9.1.1 v9.1.0 v9.0.10 v9.0.9 v9.0.8 v9.0.7 v9.0.6 v9.0.5 v9.0.4 v9.0.3 v9.0.2 v9.0.1 v9.0.0 v8.10.9 v8.10.8 v8.10.7 v8.10.6 v8.10.5 v8.10.4 v8.10.3 v8.10.2 v8.10.1 v8.10.0 v8.9.4 v8.9.3 v8.9.2 v8.9.1 v8.9.0 v8.8.5 v8.8.4 v8.8.3 v8.8.2 v8.8.1 v8.8.0 v8.7.11 v8.7.10 v8.7.9 v8.7.8 v8.7.7 v8.7.6 v8.7.5 v8.7.4 v8.7.3 v8.7.2 v8.7.1 v8.7.0 v8.6.8 v8.6.7 v8.6.6 v8.6.5 v8.6.4 v8.6.3 v8.6.2 v8.6.1 v8.6.0 v8.5.8 v8.5.7 v8.5.6 v8.5.5 v8.5.4 v8.5.3 v8.5.2 v8.5.1 v8.5.0 v8.4.1 v8.4.0 v8.3.10 v8.3.9 v8.3.8 v8.3.7 v8.3.6 v8.3.5 v8.3.4 v8.3.3 v8.3.2 v8.3.1 v8.3.0 v8.2.7 v8.2.6 v8.2.5 v8.2.4 v8.2.3 v8.2.2 v8.2.1 v8.2.0 v8.1.4 v8.1.3 v8.1.2 v8.1.1 v8.1.0 v8.0.71 v8.0.70 v8.0.69 v8.0.68 v8.0.67 v8.0.66 v8.0.65 v8.0.64 v8.0.63 v8.0.62 v8.0.61 v8.0.60 v8.0.59 v8.0.58 v8.0.57 v8.0.56 v8.0.55 v8.0.54 v8.0.53 v8.0.52 v8.0.51 v8.0.50 v8.0.49 v8.0.48 v8.0.47 v8.0.46 v8.0.45 v8.0.44 v8.0.43 v8.0.42 v8.0.41 v8.0.40 v8.0.39 v8.0.38 v8.0.37 v8.0.36 v8.0.35 v8.0.34 v8.0.33 v8.0.32 v8.0.31 v8.0.30 v8.0.29 v8.0.28 v8.0.27 v8.0.26 v8.0.25 v8.0.24 v8.0.23 v8.0.22 v8.0.21 v8.0.20 v8.0.19 v8.0.18 v8.0.17 v8.0.16 v8.0.15 v8.0.14 v8.0.13 v8.0.12 v8.0.11 v8.0.10 v8.0.9 v8.0.8 v8.0.7 v8.0.6
No related merge requests found
Showing with 1205 additions and 1361 deletions
+1205 -1361
......@@ -13,7 +13,7 @@ import os, sys, importlib, inspect, json
from .exceptions import *
from .utils.jinja import get_jenv, get_template, render_template
__version__ = '8.0.5'
__version__ = '8.0.6'
__title__ = "Frappe Framework"
local = Local()
......
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "CustomScript.####",
......@@ -24,6 +25,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "DocType",
......@@ -55,6 +57,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Script Type",
......@@ -84,8 +87,9 @@
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Script",
"length": 0,
......@@ -115,6 +119,7 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sample",
......@@ -133,19 +138,19 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-glass",
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-29 14:40:24.037012",
"modified_by": "Administrator",
"modified": "2017-04-03 18:07:28.138437",
"modified_by": "faris@erpnext.com",
"module": "Custom",
"name": "Custom Script",
"owner": "Administrator",
......@@ -160,7 +165,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
......@@ -181,7 +185,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
......@@ -196,7 +199,8 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 1,
"track_seen": 0
}
\ No newline at end of file
}
......@@ -846,7 +846,7 @@
"currency_fraction": "Cent",
"currency_fraction_units": 100,
"currency_symbol": "\u20ac",
"number_format": "#,###.##",
"number_format": "# ###,##",
"timezones": [
"Europe/Paris"
]
......
......@@ -139,6 +139,7 @@
"public/js/frappe/ui/toolbar/search.js",
"public/js/frappe/ui/toolbar/search.html",
"public/js/frappe/ui/toolbar/search_header.html",
"public/js/frappe/ui/toolbar/search_utils.js",
"public/js/frappe/ui/toolbar/about.js",
"public/js/frappe/ui/toolbar/navbar.html",
"public/js/frappe/ui/toolbar/toolbar.js",
......@@ -213,7 +214,7 @@
],
"js/list.min.js": [
"public/js/frappe/ui/listing.html",
"public/js/frappe/ui/base_list.js",
"public/js/frappe/model/indicator.js",
......@@ -238,7 +239,7 @@
"public/js/frappe/list/list_item_row_head.html",
"public/js/frappe/list/list_item_subject.html",
"public/js/frappe/list/list_permission_footer.html",
"public/js/frappe/list/list_renderer.js",
"public/js/frappe/views/gantt/gantt_view.js",
"public/js/frappe/views/calendar/calendar.js",
......@@ -256,7 +257,7 @@
"public/js/frappe/views/inbox/inbox_no_result.html",
"public/js/frappe/views/inbox/inbox_view_item_row.html",
"public/js/frappe/views/inbox/inbox_view_item_main_head.html",
"public/js/frappe/views/kanban/kanban_board.html",
"public/js/frappe/views/kanban/kanban_column.html",
"public/js/frappe/views/kanban/kanban_card.html"
......
......@@ -677,13 +677,100 @@ fieldset[disabled] .form-control {
}
.search-dialog .modal-dialog {
width: 768px;
height: 500px;
}
.search-dialog .search-header {
display: flex;
align-items: center;
padding: 5px;
}
.search-dialog .modal-body {
padding: 0px 15px;
}
.search-dialog input.form-control,
.search-dialog .input-group-addon {
.search-dialog .empty-state {
color: #d4d9dd;
height: 500px;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.search-dialog .empty-state .status-icon {
font-size: 40px;
position: relative;
margin-bottom: 10px;
}
.search-dialog .empty-state p {
font-size: 15px;
display: block;
}
.search-dialog .empty-state .cover {
color: white;
font-size: 6px;
position: absolute;
}
@keyframes twinkle {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-o-keyframes twinkle {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-moz-keyframes twinkle {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes twinkle {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.search-dialog .twinkle-one {
-webkit-animation: twinkle 1.5s ease infinite;
-moz-animation: twinkle 1.5s ease infinite;
-o-animation: twinkle 1.5s ease infinite;
animation: twinkle 1.5s ease infinite;
}
.search-dialog .twinkle-two {
-webkit-animation: twinkle 1.5s ease infinite 0.5s;
-moz-animation: twinkle 1.5s ease infinite 0.5s;
-o-animation: twinkle 1.5s ease infinite 0.5s;
animation: twinkle 1.5s ease infinite 0.5s;
}
.search-dialog .twinkle-three {
-webkit-animation: twinkle 1.5s ease infinite 1s;
-moz-animation: twinkle 1.5s ease infinite 1s;
-o-animation: twinkle 1.5s ease infinite 1s;
animation: twinkle 1.5s ease infinite 1s;
}
.search-dialog input.form-control {
border: none;
border-left-style: none;
}
......@@ -691,9 +778,6 @@ fieldset[disabled] .form-control {
outline: none;
box-shadow: none;
}
.search-dialog .input-group-addon {
background-color: #FFF;
}
.search-dialog .layout-side-section,
.search-dialog .layout-main-section {
height: 500px;
......@@ -712,6 +796,7 @@ fieldset[disabled] .form-control {
align-items: center;
justify-content: space-between;
padding-left: 20px;
background-color: #ffffff;
}
.search-dialog .layout-side-section .nav li a i {
visibility: hidden;
......@@ -719,23 +804,9 @@ fieldset[disabled] .form-control {
.search-dialog .layout-side-section .nav .active i {
visibility: visible;
}
.search-dialog .results-area .search-intro-placeholder {
color: #d4d9dd;
height: inherit;
display: flex;
justify-content: center;
align-items: center;
}
.search-dialog .results-area .search-intro-placeholder span {
text-align: center;
}
.search-dialog .results-area .search-intro-placeholder span i {
font-size: 64px;
display: block;
}
.search-dialog .results-area .search-intro-placeholder span p {
font-size: 15px;
display: block;
.search-dialog .layout-side-section .nav .select a,
.search-dialog .layout-side-section .nav a:hover {
background-color: #f7fafc;
}
.search-dialog .results-area .single-link a {
color: #36414c;
......@@ -748,6 +819,9 @@ fieldset[disabled] .form-control {
font-family: 'Octicons';
content: '\f0a4';
}
.search-dialog .module-section .result {
margin-bottom: 5px;
}
.search-dialog .full-list .result {
margin-top: 15px;
}
......@@ -772,6 +846,27 @@ fieldset[disabled] .form-control {
.search-dialog .more-results {
display: none;
}
.search-dialog .result p {
margin-top: 5px;
margin-bottom: 5px;
}
.search-dialog .result .result-image {
display: inline-block;
margin-right: 10px;
height: 60px;
width: 60px;
background-color: #fafbfc;
}
.search-dialog .result .result-image .flex-text {
display: flex;
height: 60px;
align-items: center;
justify-content: center;
}
.search-dialog .result .result-image span {
font-size: 30px;
color: #d1d8dd;
}
@media (max-width: 767px) {
.search-dialog .modal-dialog {
width: auto;
......@@ -785,21 +880,12 @@ fieldset[disabled] .form-control {
margin: 0px;
border-top: none;
}
.search-dialog .layout-side-section .sidebar-menu {
margin: 30px 0px;
}
}
@media (min-width: 600px) {
.search-dialog .results-area .back-link {
display: none;
}
}
.result p {
margin-top: 0.2em;
}
.search-result {
margin-bottom: 24px;
}
.note-editor.note-frame .note-editing-area .note-editable {
color: #36414C;
}
......
......@@ -420,6 +420,7 @@
.list-item input[type=checkbox] {
margin: 0;
margin-right: 5px;
flex: 0 0 12px;
}
.list-item .liked-by,
.list-item .liked-by-filter-button {
......
......@@ -11,7 +11,7 @@
</i>
<span class="likes-count">{{ (_liked_by.length > 99 ? "99+" : _liked_by.length) || "" }}</span>
</span>
<a class="grey list-id {{ css_seen }}"
<a class="grey list-id {{ css_seen }} ellipsis"
data-name="{{ _name }}"
href="#Form/{{ _doctype_encoded }}/{{ _name_encoded }}"
title="{{ _full_title }}">{{ strip_html(_title) }}</a>
......
......@@ -447,9 +447,6 @@ frappe.views.ListRenderer = Class.extend({
data._title = strip_html(data[title_field] || data.name);
data._full_title = data._title;
if (data._title.length > 35) {
data._title = data._title.slice(0, 35) + '...';
}
data._workflow = null;
if (this.workflow_state_fieldname) {
......
......@@ -9,11 +9,6 @@ frappe.search.AwesomeBar = Class.extend({
var $input = $(element);
var input = $input.get(0);
this.search = new frappe.search.UnifiedSearch();
this.global = new frappe.search.GlobalSearch();
this.nav = new frappe.search.NavSearch();
this.help = new frappe.search.HelpSearch();
this.options = [];
this.global_results = [];
......@@ -23,32 +18,22 @@ frappe.search.AwesomeBar = Class.extend({
autoFirst: true,
list: [],
filter: function (text, term) {
this.get_item(text.value).boo = "foo";
return true;
},
data: function (item, input) {
var label = item.label + "%%%" + item.value + "%%%" +
(item.description || "") + "%%%" + (item.index || "")
+ "%%%" + (item.type || "") + "%%%" + (item.prefix || "");
return {
label: label,
label: (item.index || ""),
value: item.value
};
},
item: function(item, term) {
var d = item;
var parts = item.split("%%%"),
d = { label: parts[0], value: parts[1], description: parts[2],
type: parts[4], prefix: parts[5]};
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>";
}
var d = this.get_item(item.value);
var name = d.prefix ? __(d.prefix + ' ' + (d.label || d.value)) :
__(d.label || d.value);
var html = '<span>' + name + '</span>';
if(d.description && d.value!==d.description) {
html += '<br><span class="text-muted">' + __(d.description) + '</span>';
html += '<br><span class="text-muted ellipsis">' + __(d.description) + '</span>';
}
return $('<li></li>')
.data('item.autocomplete', d)
......@@ -56,9 +41,7 @@ frappe.search.AwesomeBar = Class.extend({
.get(0);
},
sort: function(a, b) {
var a_index = a.split("%%%")[3];
var b_index = b.split("%%%")[3];
return (a_index - b_index);
return (b.label - a.label);
}
});
......@@ -67,53 +50,29 @@ frappe.search.AwesomeBar = Class.extend({
var txt = value.trim().replace(/\s\s+/g, ' ');
var last_space = txt.lastIndexOf(' ');
me.global_results = [];
if(txt && txt.length > 2) {
me.global.get_awesome_bar_options(txt.toLowerCase(), me);
}
// if(txt && txt.length > 1) {
// me.global.get_awesome_bar_options(txt.toLowerCase(), me);
// }
var $this = $(this);
clearTimeout($this.data('timeout'));
$this.data('timeout', setTimeout(function(){
me.options = [];
if(txt && txt.length > 2) {
if(txt && txt.length > 1) {
if(last_space !== -1) {
me.set_specifics(txt.slice(0,last_space), txt.slice(last_space+1));
}
me.add_defaults(txt);
me.options = me.options.concat(me.build_options(txt));
me.build_defaults(txt);
me.options = me.options.concat(me.global_results);
} else {
me.options = me.options.concat(
me.deduplicate(frappe.search.utils.get_recent_pages(txt || "")));
}
me.make_calculator(txt);
me.add_recent(txt || "");
me.add_help();
// de-duplicate
var out = [], routes = [];
me.options.forEach(function(option) {
if(option.route) {
if(option.route[0] === "List" && option.route[2]) {
option.route.splice(2);
}
var str_route = (typeof option.route==='string') ?
option.route : option.route.join('/');
if(routes.indexOf(str_route)===-1) {
out.push(option);
routes.push(str_route);
} else {
var old = routes.indexOf(str_route);
if(out[old].index > option.index) {
out[old] = option;
}
}
} else {
out.push(option);
}
});
awesomplete.list = out;
awesomplete.list = me.options;
}, 100));
});
......@@ -153,20 +112,20 @@ frappe.search.AwesomeBar = Class.extend({
frappe.route();
}
}
$input.val("");
});
$input.on("awesomplete-selectcomplete", function(e) {
$input.val("");
});
this.setup_recent();
this.search.setup();
frappe.search.utils.setup_recent();
},
add_help: function() {
this.options.push({
label: __("Help on Search"),
value: "Help on Search",
index: 100,
index: -10,
default: "Help",
onclick: function() {
var txt = '<table class="table table-bordered">\
......@@ -186,142 +145,6 @@ frappe.search.AwesomeBar = Class.extend({
});
},
add_recent: function(txt) {
var me = this;
values = [];
$.each(me.recent, function(i, doctype) {
values.push([doctype[1], ['Form', doctype[0], doctype[1]]]);
});
values = values.reverse();
$.each(frappe.route_history, function(i, route) {
if(route[0]==='Form') {
values.push([route[2], route]);
}
else if(in_list(['List', 'Report', 'Tree', 'modules', 'query-report'], route[0])) {
if(route[1]) {
values.push([route[1], route]);
}
}
else if(route[0]) {
values.push([frappe.route_titles[route[0]] || route[0], route]);
}
});
this.find(values, txt, function(match) {
out = {
route: match[1]
}
if(match[1][0]==='Form') {
if(match[1][1] !== match[1][2]) {
out.label = __(match[1][1]) + " " + match[1][2].bold();
out.value = __(match[1][1]) + " " + match[1][2];
} else {
out.label = __(match[1][1]).bold();
out.value = __(match[1][1]);
}
} else if(in_list(['List', 'Report', 'Tree', 'modules', 'query-report'], match[1][0])) {
var type = match[1][0], label = type;
if(type==='modules') label = 'Module';
else if(type==='query-report') label = 'Report';
out.label = __(match[1][1]).bold() + " " + __(label);
out.value = __(match[1][1]) + " " + __(label);
} else {
out.label = match[0].bold();
out.value = match[0];
}
out.index = 80;
out.default = "Recent";
return out;
}, true);
},
find: function(list, txt, process, prepend) {
var me = this;
$.each(list, function(i, item) {
if($.isArray(item)) {
_item = item[0];
} else {
_item = item;
}
_item = __(_item || '').toLowerCase().replace(/-/g, " ");
if(txt===_item || _item.indexOf(txt) !== -1) {
var option = process(item);
if(option) {
if($.isPlainObject(option)) {
option = [option];
}
option.forEach(function(o) { o.match = item; });
if(prepend) {
me.options = option.concat(me.options);
} else {
me.options = me.options.concat(option);
}
}
}
});
},
setup_recent: function() {
this.recent = JSON.parse(frappe.boot.user.recent || "[]") || [];
},
fuzzy_search: function(_txt, _item) {
parsed_item = __(_item || '').replace(/-|_/g, " ");
item = parsed_item.toLowerCase();
txt = _txt.toLowerCase();
var ilen = item.length;
var tlen = txt.length;
var match_level = tlen/ilen;
var rendered_label = "";
var i, j, skips = 0, mismatches = 0;
if(tlen > ilen) {
return [];
}
if(parsed_item.indexOf(_txt) !== -1 && txt !== _txt) {
var regEx = new RegExp("("+ txt +")", "ig");
rendered_label = parsed_item.replace(regEx, '<b>$1</b>');
return [parsed_item, (ilen + 10), rendered_label];
}
if(item.indexOf(txt) !== -1) {
var regEx = new RegExp("("+ txt +")", "ig");
rendered_label = parsed_item.replace(regEx, '<b>$1</b>');
return [parsed_item, 20 + (ilen + 10), 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 = parsed_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 += parsed_item.charAt(j);
j++;
}
return [];
}
rendered_label += parsed_item.slice(j);
return [parsed_item, 40 + (ilen + 10), rendered_label];
},
set_specifics: function(txt, end_txt) {
var me = this;
var results = this.build_options(txt);
......@@ -332,19 +155,50 @@ frappe.search.AwesomeBar = Class.extend({
});
},
build_defaults: function(txt) {
add_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));
this.make_calculator(txt);
},
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)
var options = frappe.search.utils.get_creatables(txt).concat(
frappe.search.utils.get_search_in_list(txt),
frappe.search.utils.get_doctypes(txt),
frappe.search.utils.get_reports(txt),
frappe.search.utils.get_pages(txt),
frappe.search.utils.get_modules(txt),
frappe.search.utils.get_recent_pages(txt || "")
);
var out = this.deduplicate(options);
return out.sort(function(a, b) {
return b.index - a.index;
});
},
deduplicate: function(options) {
var out = [], routes = [];
options.forEach(function(option) {
if(option.route) {
if(option.route[0] === "List" && option.route[2]) {
option.route.splice(2);
}
var str_route = (typeof option.route==='string') ?
option.route : option.route.join('/');
if(routes.indexOf(str_route)===-1) {
out.push(option);
routes.push(str_route);
} else {
var old = routes.indexOf(str_route);
if(out[old].index > option.index) {
out[old] = option;
}
}
} else {
out.push(option);
}
});
return out;
},
set_global_results: function(global_results, txt){
......@@ -357,11 +211,10 @@ frappe.search.AwesomeBar = Class.extend({
label: __("Search for '" + txt.bold() + "'"),
value: __("Search for '" + txt + "'"),
match: txt,
index: 1,
index: 100,
default: "Search",
onclick: function() {
me.search.search_dialog.show();
me.search.setup_search(txt, [me.nav, me.global, me.help]);
frappe.searchdialog.search.init_search(txt, "global_search");
}
});
},
......@@ -378,10 +231,10 @@ frappe.search.AwesomeBar = Class.extend({
label: __('Find {0} in {1}', [txt.bold(), route[1].bold()]),
value: __('Find {0} in {1}', [txt, route[1]]),
route_options: options,
index: 2,
onclick: function() {
cur_list.refresh();
},
index: 90,
default: "Current",
match: txt
});
......@@ -401,7 +254,7 @@ frappe.search.AwesomeBar = Class.extend({
label: formatted_value,
value: __('{0} = {1}', [txt, val]),
match: val,
index: 3,
index: 80,
default: "Calculator",
onclick: function() {
msgprint(formatted_value, "Result");
......@@ -412,208 +265,4 @@ frappe.search.AwesomeBar = Class.extend({
}
}
},
make_search_in_list: function(txt) {
var me = this;
var out = [];
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)[0];
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: 4,
default: "In List",
route: ["List", item]
});
}
});
}
return out;
},
make_new_doc: function(txt) {
var me = this;
var out = [];
if(txt.split(" ")[0]==="new") {
frappe.boot.user.can_create.forEach(function (item) {
var result = me.fuzzy_search(txt.substr(4), item);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
out.push({
label: rendered_label,
value: __("New {0}", [target]),
index: index,
type: "New",
prefix: "New",
match: item,
onclick: function() { frappe.new_doc(item, true); }
});
}
});
}
return out;
},
get_doctypes: function(txt) {
var me = this;
var out = [];
var result, target, index, rendered_label;
var option = function(type, route, order) {
return {
label: rendered_label,
value: __(target + " " + type),
route: route,
index: index + order,
match: target,
type: type
}
};
frappe.boot.user.can_read.forEach(function (item) {
result = me.fuzzy_search(txt, item);
target = result[0];
index = result[1];
rendered_label = result[2];
if(target) {
// include 'making new' option
if(in_list(frappe.boot.user.can_create, item)) {
var match = item;
out.push({
label: rendered_label,
value: __("New {0}", [target]),
index: index + 0.4,
type: "New",
prefix: "New",
match: item,
onclick: function() { frappe.new_doc(match, true); }
});
}
if(in_list(frappe.boot.single_types, target)) {
out.push(option("", ["Form", target, target], 0));
} else if(in_list(frappe.boot.treeviews, target)) {
out.push(option("Tree", ["Tree", target], 0));
} else {
out.push(option("List", ["List", target], 0));
if(frappe.model.can_get_report(target)) {
out.push(option("Report", ["Report", target], 0.1));
}
if(frappe.boot.calendars.indexOf(target) !== -1) {
out.push(option("Calendar", ["List", target, "Calendar"], 0.2));
out.push(option("Gantt", ["List", target, "Gantt"], 0.3));
}
}
}
});
return out;
},
get_reports: function(txt) {
var me = this;
var out = [];
Object.keys(frappe.boot.user.all_reports).forEach(function(item) {
var result = me.fuzzy_search(txt, item);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
var report = frappe.boot.user.all_reports[item];
var route = [];
if(report.report_type == "Report Builder")
route = ["Report", report.ref_doctype, item];
else
route = ["query-report", item];
out.push({
label: rendered_label,
value: __("Report {0}" , [__(target)]),
match: txt,
index: index,
type: "Report",
prefix: "Report",
route: route
});
}
});
return out;
},
get_pages: function(txt) {
var me = this;
var out = [];
this.pages = {};
$.each(frappe.boot.page_info, function(name, p) {
me.pages[p.title] = p;
p.name = name;
});
Object.keys(this.pages).forEach(function(item) {
var result = me.fuzzy_search(txt, item);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
var page = me.pages[item];
out.push({
label: rendered_label,
value: __("Open {0}", [__(target)]),
match: txt,
index: index,
type: "Page",
prefix: "Open",
route: [page.route || page.name]
});
}
});
// calendar
var target = 'Calendar';
if(__('calendar').indexOf(txt.toLowerCase()) === 0) {
out.push({
label: __(target),
value: __("Open {0}", [__(target)]),
route: [target, 'Event'],
index: 5,
type: "Calendar",
prefix: "Open",
match: target
});
}
return out;
},
get_modules: function(txt) {
var me = this;
var out = [];
Object.keys(frappe.modules).forEach(function(item) {
var result = me.fuzzy_search(txt, item);
var target = result[0];
var index = result[1];
var rendered_label = result[2];
if(target) {
var module = frappe.modules[item];
if(module._doctype) return;
ret = {
label: rendered_label,
value: __("Open {0}", [__(target)]),
match: txt,
index: index,
type: "Module",
prefix: "Open"
}
if(module.link) {
ret.route = [module.link];
} else {
ret.route = ["Module", item];
}
out.push(ret);
}
});
return out;
},
});
<div class="row">
<div class="col-md-2 col-sm-2 hidden-xs layout-side-section search-sidebar">
</div>
<div class="col-md-10 col-sm-10 layout-main-section results-area">
</div>
</div>
</div>
<div class="row search-results">
<div class="col-md-2 col-sm-2 hidden-xs layout-side-section">
<ul class="module-sidebar-nav overlay-sidebar nav nav-pills nav-stacked search-sidebar"></ul>
</div>
<div class="col-md-10 col-sm-10 layout-main-section results-area"></div>
</div>
\ No newline at end of file
<div class="input-group has-feedback search-header" style="margin:5px -5px;">
<span class="input-group-addon">
<i class="octicon octicon-search"></i>
</span>
<input type="text" class="form-control search-input" placeholder="Search for ...">
<span class="input-group-addon"><a type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</a></span>
<div class="search-header">
<i class="octicon octicon-search"></i>
<input type="text" class="form-control search-input" style="padding: 15px">
<p class="loading-state hide" style="margin: 0px 20px; color:#d4d9dd">{%= __("Searching")%}&nbsp...</p>
<a type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</a>
</div>
\ No newline at end of file
frappe.provide('frappe.search');
frappe.search.utils = {
setup_recent: function() {
this.recent = JSON.parse(frappe.boot.user.recent || "[]") || [];
},
get_recent_pages: function(keywords) {
var me = this;
values = [], options = [];
function find(list, keywords, process) {
list.forEach(function(item, i) {
_item = ($.isArray(item)) ? item[0] : item;
_item = __(_item || '').toLowerCase().replace(/-/g, " ");
if(keywords===_item || _item.indexOf(keywords) !== -1) {
var option = process(item);
if(option) {
if($.isPlainObject(option)) {
option = [option];
}
option.forEach(function(o) { o.match = item; });
options = option.concat(options);
}
}
});
}
me.recent.forEach(function(doctype, i) {
values.push([doctype[1], ['Form', doctype[0], doctype[1]]]);
});
values = values.reverse();
frappe.route_history.forEach(function(route, i) {
if(route[0]==='Form') {
values.push([route[2], route]);
}
else if(in_list(['List', 'Report', 'Tree', 'modules', 'query-report'], route[0])) {
if(route[1]) {
values.push([route[1], route]);
}
}
else if(route[0]) {
values.push([frappe.route_titles[route[0]] || route[0], route]);
}
});
find(values, keywords, function(match) {
out = {
route: match[1]
}
if(match[1][0]==='Form') {
if(match[1][1] !== match[1][2]) {
out.label = __(match[1][1]) + " " + match[1][2].bold();
out.value = __(match[1][1]) + " " + match[1][2];
} else {
out.label = __(match[1][1]).bold();
out.value = __(match[1][1]);
}
} else if(in_list(['List', 'Report', 'Tree', 'modules', 'query-report'], match[1][0])) {
var type = match[1][0], label = type;
if(type==='modules') label = 'Module';
else if(type==='query-report') label = 'Report';
out.label = __(match[1][1]).bold() + " " + __(label);
out.value = __(match[1][1]) + " " + __(label);
} else {
out.label = match[0].bold();
out.value = match[0];
}
out.index = 80;
return out;
});
return options;
},
get_search_in_list: function(keywords) {
var me = this;
var out = [];
if(in_list(keywords.split(" "), "in") && (keywords.slice(-2) !== "in")) {
parts = keywords.split(" in ");
frappe.boot.user.can_read.forEach(function (item) {
if(frappe.boot.user.can_search.includes(item)) {
var level = me.fuzzy_search(parts[1], item);
if(level) {
out.push({
type: "In List",
prefix: "Find '" + __(parts[0]).bold() + "' in ",
label: __(me.bolden_match_part(item, parts[1])),
value: __('Find {0} in {1}', [__(parts[0]), __(item)]),
route_options: {"name": ["like", "%" + parts[0] + "%"]},
index: 1 + level,
route: ["List", item]
});
}
}
});
}
return out;
},
get_creatables: function(keywords) {
var me = this;
var out = [];
if(keywords.split(" ")[0]==="new") {
frappe.boot.user.can_create.forEach(function (item) {
var level = me.fuzzy_search(keywords.substr(4), item);
if(level) {
out.push({
type: "New",
prefix: "New ",
label: __(me.bolden_match_part(item, keywords.substr(4))),
value: __("New {0}", [item]),
index: 1 + level,
match: item,
onclick: function() { frappe.new_doc(item, true); }
});
}
});
}
return out;
},
get_doctypes: function(keywords) {
var me = this;
var out = [];
var level, target;
var option = function(type, route, order) {
return {
type: type,
label: __("{0}" + " " + type, [__(me.bolden_match_part(target, keywords))]),
value: __(target + " " + type),
index: level + order,
match: target,
route: route,
}
};
frappe.boot.user.can_read.forEach(function(item) {
if(frappe.boot.user.can_search.includes(item)) {
level = me.fuzzy_search(keywords, item);
if(level) {
target = item;
// include 'making new' option
if(in_list(frappe.boot.user.can_create, item)) {
var match = item;
out.push({
type: "New",
label: __("New {0}", [__(me.bolden_match_part(item, keywords))]),
value: __("New {0}", [__(item)]),
index: level + 0.01,
match: item,
onclick: function() { frappe.new_doc(match, true); }
});
}
if(in_list(frappe.boot.single_types, item)) {
out.push(option("", ["Form", item, item], 0.05));
} else if(in_list(frappe.boot.treeviews, item)) {
out.push(option("Tree", ["Tree", item], 0.05));
} else {
out.push(option("List", ["List", item], 0.05));
if(frappe.model.can_get_report(item)) {
out.push(option("Report", ["Report", item], 0.04));
}
if(frappe.boot.calendars.indexOf(item) !== -1) {
out.push(option("Calendar", ["List", item, "Calendar"], 0.03));
out.push(option("Gantt", ["List", item, "Gantt"], 0.02));
}
}
}
}
});
return out;
},
get_reports: function(keywords) {
var me = this;
var out = [];
Object.keys(frappe.boot.user.all_reports).forEach(function(item) {
var level = me.fuzzy_search(keywords, item);
if(level > 0) {
var report = frappe.boot.user.all_reports[item];
if(report.report_type == "Report Builder")
route = ["Report", report.ref_doctype, item];
else
route = ["query-report", item];
out.push({
type: "Report",
prefix: "Report ",
label: __(me.bolden_match_part(item, keywords)),
value: __("Report {0}" , [item]),
index: level,
route: route
});
}
});
return out;
},
get_pages: function(keywords) {
var me = this;
var out = [];
this.pages = {};
$.each(frappe.boot.page_info, function(name, p) {
me.pages[p.title] = p;
p.name = name;
});
Object.keys(this.pages).forEach(function(item) {
var level = me.fuzzy_search(keywords, item);
if(level) {
var page = me.pages[item];
out.push({
type: "Page",
prefix: "Open ",
label: __(me.bolden_match_part(item, keywords)),
value: __("Open {0}", [__(item)]),
match: item,
index: level,
route: [page.route || page.name]
});
}
});
var target = 'Calendar';
if(__('calendar').indexOf(keywords.toLowerCase()) === 0) {
out.push({
type: "Calendar",
prefix: "Open ",
label: __('Calendar'),
value: __("Open {0}", [__(target)]),
index: me.fuzzy_search(keywords, 'Calendar'),
match: target,
route: [target, 'Event'],
});
}
return out;
},
get_modules: function(keywords) {
var me = this;
var out = [];
Object.keys(frappe.modules).forEach(function(item) {
var level = me.fuzzy_search(keywords, item);
if(level > 0) {
var module = frappe.modules[item];
if(module._doctype) return;
ret = {
type: "Module",
prefix: "Open ",
label: __(me.bolden_match_part(item, keywords)),
value: __("Open {0}", [__(item)]),
index: level,
}
if(module.link) {
ret.route = [module.link];
} else {
ret.route = ["Module", item];
}
out.push(ret);
}
});
return out;
},
get_global_results: function (keywords, start, limit, doctype = "") {
var me = this;
function get_results_sets(data) {
var results_sets = [], result, set;
function get_existing_set (doctype) {
return results_sets.find(function(set) {
return set.title === doctype;
});
}
function make_description(content, doc_name) {
parts = content.split("|||");
content_length = 300;
fields = [];
current_length = 0;
var field_text = "";
for(var i = 0; i < parts.length; i++) {
part = parts[i];
if(part.toLowerCase().indexOf(keywords) !== -1) {
if(part.indexOf('&&&') !== -1) {
var colon_index = part.indexOf('&&&');
var field_value = part.slice(colon_index + 3);
} else {
var colon_index = part.indexOf(':');
var field_value = part.slice(colon_index + 1);
}
var field_name = part.slice(0, colon_index);
var remaining_length = content_length - current_length;
current_length += field_name.length + field_value.length + 2;
if(current_length < content_length) {
field_text = '<span class="field-name text-muted">' +
me.bolden_match_part(field_name, keywords) + ':' + '</span>' +
me.bolden_match_part(field_value, keywords);
if(fields.indexOf(field_text) === -1 && doc_name !== field_value) {
fields.push(field_text);
}
} else {
if(field_name.length < remaining_length){
remaining_length -= field_name.length;
field_text = '<span class="field-name text-muted">' +
me.bolden_match_part(field_name, keywords) + ':' + '</span>';
field_value = field_value.slice(0, remaining_length);
field_value = field_value.slice(0, field_value.lastIndexOf(' ')) + ' ...';
field_text += me.bolden_match_part(field_value, keywords);
fields.push(field_text);
} else {
fields.push('...');
}
break;
}
}
}
return fields.join(', ');
}
data.forEach(function(d) {
// more properties
result = {
label: d.name,
value: d.name,
description: make_description(d.content, d.name),
route: ['Form', d.doctype, d.name],
}
if(d.image || d.image === null){
result.image = d.image;
}
set = get_existing_set(d.doctype);
if(set) {
set.results.push(result);
} else {
set = {
title: d.doctype,
results: [result],
fetch_type: "Global"
}
results_sets.push(set);
}
});
return results_sets;
}
return new Promise(function(resolve, reject) {
frappe.call({
method: "frappe.utils.global_search.search",
args: {
text: keywords,
start: start,
limit: limit,
doctype: doctype
},
callback: function(r) {
if(r.message) {
resolve(get_results_sets(r.message));
} else {
resolve([]);
}
}
});
});
},
get_help_results: function(keywords) {
function get_results_set(data) {
var result;
var set = {
title: "Help",
fetch_type: "Help",
results: []
}
data.forEach(function(d) {
// more properties
result = {
label: d[0],
value: d[0],
description: d[1],
data_path: d[2],
onclick: function() {
}
}
set.results.push(result);
});
return [set];
}
return new Promise(function(resolve, reject) {
frappe.call({
method: "frappe.utils.help.get_help",
args: {
text: keywords
},
callback: function(r) {
if(r.message) {
resolve(get_results_set(r.message));
} else {
resolve([]);
}
}
});
});
},
get_nav_results: function(keywords) {
function sort_uniques(array) {
var routes = [], out = [];
array.forEach(function(d) {
if(d.route) {
if(d.route[0] === "List" && d.route[2]) {
d.route.splice(2);
}
var str_route = d.route.join('/');
if(routes.indexOf(str_route) === -1) {
routes.push(str_route);
out.push(d);
} else {
var old = routes.indexOf(str_route);
if(out[old].index > d.index) {
out[old] = d;
}
}
} else {
out.push(d);
}
});
return out.sort(function(a, b) {
return b.index - a.index;
});
}
var lists = [], setup = [];
var all_doctypes = sort_uniques(this.get_doctypes(keywords));
all_doctypes.forEach(function(d) {
if(d.type === "") {
setup.push(d);
} else {
lists.push(d);
}
});
var in_keyword = keywords.split(" in ")[0];
return [
{title: "Recents", fetch_type: "Nav", results: sort_uniques(this.get_recent_pages(keywords))},
{title: "Create a new ...", fetch_type: "Nav", results: sort_uniques(this.get_creatables(keywords))},
{title: "Find '" + in_keyword + "' in ... ", fetch_type: "Nav", results: sort_uniques(this.get_search_in_list(keywords))},
{title: "Lists", fetch_type: "Nav", results: lists},
{title: "Reports", fetch_type: "Nav", results: sort_uniques(this.get_reports(keywords))},
{title: "Administration", fetch_type: "Nav", results: sort_uniques(this.get_pages(keywords))},
{title: "Modules", fetch_type: "Nav", results: sort_uniques(this.get_modules(keywords))},
{title: "Setup", fetch_type: "Nav", results: setup},
]
},
fuzzy_search: function(keywords, _item) {
// Returns 10 for case-perfect contain, 0 for not found
// 9 for perfect contain,
// 0 - 6 for fuzzy contain
// **Specific use-case step**
item = __(_item || '').replace(/-/g, " ");
var ilen = item.length;
var klen = keywords.length;
var length_ratio = klen/ilen;
var max_skips = 3, max_mismatch_len = 2;
if (klen > ilen) { return 0; }
if(keywords === item || item.toLowerCase().indexOf(keywords) === 0) {
return 10 + length_ratio;
}
if (item.indexOf(keywords) !== -1 && keywords !== keywords.toLowerCase()) {
return 9 + length_ratio;
}
item = item.toLowerCase();
keywords = keywords.toLowerCase();
if (item.indexOf(keywords) !== -1) {
return 8 + length_ratio;
}
var skips = 0, mismatches = 0;
outer: for (var i = 0, j = 0; i < klen; i++) {
if(mismatches !== 0) skips++;
if(skips > max_skips) return 0;
var k_ch = keywords.charCodeAt(i);
mismatches = 0;
while (j < ilen) {
if (item.charCodeAt(j++) === k_ch) {
continue outer;
}
if(++mismatches > max_mismatch_len) return 0 ;
}
return 0;
}
// Since indexOf didn't pass, there will be atleast 1 skip
// hence no divide by zero, but just to be safe
if((skips + mismatches) > 0) {
return (5 + length_ratio)/(skips + mismatches);
} else {
return 0;
}
},
bolden_match_part: function(str, subseq) {
var rendered = "";
if(this.fuzzy_search(subseq, str) === 0) {
return str;
} else if(this.fuzzy_search(subseq, str) > 6) {
var regEx = new RegExp("("+ subseq +")", "ig");
return str.replace(regEx, '<b>$1</b>');
} else {
var str_orig = str;
var str = str.toLowerCase();
var str_len = str.length;
var subseq = subseq.toLowerCase();
outer: for(var i = 0, j = 0; i < subseq.length; i++) {
var sub_ch = subseq.charCodeAt(i);
while(j < str_len) {
if(str.charCodeAt(j) === sub_ch) {
var str_char = str_orig.charAt(j);
if(str_char === str_char.toLowerCase()) {
rendered += '<b>' + subseq.charAt(i) + '</b>';
} else {
rendered += '<b>' + subseq.charAt(i).toUpperCase() + '</b>';
}
j++;
continue outer;
}
rendered += str_orig.charAt(j);
j++;
}
return str_orig;
}
rendered += str_orig.slice(j);
return rendered;
}
},
unscrub_and_titlecase: function(str) {
return __(str || '').replace(/-|_/g, " ").replace(/\w*/g,
function(keywords){return keywords.charAt(0).toUpperCase() + keywords.substr(1).toLowerCase();});
},
}
\ No newline at end of file
......@@ -12,12 +12,11 @@ frappe.ui.toolbar.Toolbar = Class.extend({
this.setup_sidebar();
this.awesome_bar = new frappe.search.AwesomeBar();
this.awesome_bar.setup("#navbar-search");
this.awesome_bar.setup("#modal-search");
var awesome_bar = new frappe.search.AwesomeBar();
awesome_bar.setup("#navbar-search");
awesome_bar.setup("#modal-search");
this.search = this.awesome_bar.search;
this.help = this.awesome_bar.help;
this.setup_help();
$(document).on("notification-update", function() {
frappe.ui.notifications.update_notifications();
......@@ -25,8 +24,6 @@ frappe.ui.toolbar.Toolbar = Class.extend({
$('.dropdown-toggle').dropdown();
this.setup_help();
$(document).trigger('toolbar_setup');
// clear all custom menus on page change
......@@ -81,6 +78,12 @@ frappe.ui.toolbar.Toolbar = Class.extend({
},
setup_help: function () {
frappe.provide('frappe.help');
frappe.help.show_results = show_results;
this.search = new frappe.search.SearchDialog();
frappe.provide('frappe.searchdialog');
frappe.searchdialog.search = this.search;
$(".dropdown-help .dropdown-toggle").on("click", function () {
$(".dropdown-help input").focus();
......@@ -154,13 +157,9 @@ frappe.ui.toolbar.Toolbar = Class.extend({
var me = this;
function show_help_results(keywords) {
me.search.search_dialog.show();
me.search.setup_search(keywords, [me.help]);
me.search.init_search(keywords, "help");
}
frappe.provide('frappe.help');
frappe.help.show_results = show_results;
function show_results(e) {
//edit links
href = e.target.href;
......
......@@ -550,14 +550,85 @@ textarea.form-control {
.search-dialog {
.modal-dialog {
width: 768px;
height: 500px;
}
.search-header {
display: flex;
align-items: center;
padding: 5px;
}
.modal-body {
padding: 0px 15px;
}
.empty-state {
color: #d4d9dd;
height: 500px;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
.status-icon {
font-size: 40px;
position: relative;
margin-bottom: 10px;
}
p {
font-size: 15px;
display: block;
}
.cover {
color: white;
font-size: 6px;
position: absolute;
}
}
@keyframes twinkle {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
@-o-keyframes twinkle {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
@-moz-keyframes twinkle {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
@-webkit-keyframes twinkle {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
.twinkle-one {
-webkit-animation: twinkle 1.5s ease infinite;
-moz-animation: twinkle 1.5s ease infinite;
-o-animation: twinkle 1.5s ease infinite;
animation: twinkle 1.5s ease infinite;
}
.twinkle-two {
-webkit-animation: twinkle 1.5s ease infinite 0.5s;
-moz-animation: twinkle 1.5s ease infinite 0.5s;
-o-animation: twinkle 1.5s ease infinite 0.5s;
animation: twinkle 1.5s ease infinite 0.5s;
}
.twinkle-three {
-webkit-animation: twinkle 1.5s ease infinite 1s;
-moz-animation: twinkle 1.5s ease infinite 1s;
-o-animation: twinkle 1.5s ease infinite 1s;
animation: twinkle 1.5s ease infinite 1s;
}
input.form-control, .input-group-addon {
input.form-control {
border: none;
border-left-style:none;
}
......@@ -567,10 +638,6 @@ textarea.form-control {
box-shadow: none;
}
.input-group-addon{
background-color: #FFF;
}
.layout-side-section,
.layout-main-section {
height: 500px;
......@@ -593,6 +660,7 @@ textarea.form-control {
align-items: center;
justify-content: space-between;
padding-left: 20px;
background-color: #ffffff;
i {
visibility: hidden;
......@@ -602,36 +670,14 @@ textarea.form-control {
.active i {
visibility: visible;
}
}
}
.results-area {
.search-intro-placeholder {
color: #d4d9dd;
height: inherit;
display: flex;
justify-content: center;
align-items: center;
span {
text-align: center;
i {
font-size: 64px;
display: block;
}
p {
font-size: 15px;
display: block;
}
.select a, a:hover {
background-color: #f7fafc;
}
}
}
// a {
// color: #5E64FF;
// }
.results-area {
.single-link a {
color: #36414c;
}
......@@ -647,6 +693,10 @@ textarea.form-control {
font-family: 'Octicons';
content: '\f0a4';
}
.result {
margin-bottom: 5px;
}
}
.full-list {
......@@ -684,6 +734,34 @@ textarea.form-control {
display: none;
}
.result {
p {
margin-top: 5px;
margin-bottom: 5px;
}
.result-image {
display: inline-block;
margin-right: 10px;
height: 60px;
width: 60px;
background-color: #fafbfc;
.flex-text {
display: flex;
height: 60px;
align-items: center;
justify-content: center;
}
span {
font-size: 30px;
color: @text-extra-muted;
}
}
}
@media (max-width: @screen-xs) {
.modal-dialog {
width: auto;
......@@ -699,10 +777,6 @@ textarea.form-control {
margin: 0px;
border-top: none;
}
.layout-side-section .sidebar-menu {
margin: 30px 0px;
}
}
@media (min-width: 600px) {
......@@ -712,16 +786,6 @@ textarea.form-control {
}
}
.result {
p {
margin-top: 0.2em;
}
}
.search-result {
margin-bottom: 24px;
}
.note-editor.note-frame .note-editing-area .note-editable {
color: @text-color;
}
......
......@@ -514,6 +514,7 @@
input[type=checkbox] {
margin: 0;
margin-right: 5px;
flex: 0 0 12px;
}
.liked-by, .liked-by-filter-button {
......
......@@ -110,7 +110,7 @@ def delete_for_document(doc):
name = %s''', (doc.doctype, doc.name), as_dict=True)
@frappe.whitelist()
def search(text, start=0, limit=20):
def search(text, start=0, limit=20, doctype=""):
'''Search for given text in __global_search
:param text: phrase to be searched
:param start: start results at, default 0
......@@ -118,14 +118,31 @@ def search(text, start=0, limit=20):
:return: Array of result objects'''
text = "+" + text + "*"
results = frappe.db.sql('''
select
doctype, name, content
from
__global_search
where
match(content) against (%s IN BOOLEAN MODE)
limit {start}, {limit}'''.format(start=start, limit=limit), text, as_dict=True)
if not doctype:
results = frappe.db.sql('''
select
doctype, name, content
from
__global_search
where
match(content) against (%s IN BOOLEAN MODE)
limit {start}, {limit}'''.format(start=start, limit=limit), text+"*", as_dict=True)
else:
results = frappe.db.sql('''
select
doctype, name, content
from
__global_search
where
doctype = %s AND
match(content) against (%s IN BOOLEAN MODE)
limit {start}, {limit}'''.format(start=start, limit=limit), (doctype, text), as_dict=True)
for r in results:
if frappe.get_meta(r.doctype).image_field:
doc = frappe.get_doc(r.doctype, r.name)
r.image = doc.get(doc.meta.image_field)
return results
@frappe.whitelist(allow_guest=True)
......@@ -148,45 +165,3 @@ def web_search(text, start=0, limit=20):
limit {start}, {limit}'''.format(start=start, limit=limit),
text, as_dict=True)
return results
@frappe.whitelist()
def get_search_doctypes(text):
'''Search for all t
:param text: phrase to be searched
:return: Array of result objects'''
text = "+" + text + "*"
results = frappe.db.sql('''
select
doctype
from
__global_search
where
match(content) against (%s IN BOOLEAN MODE)
group by
doctype
order by
count(doctype) desc limit 0, 80''', text, as_dict=True)
return results
@frappe.whitelist()
def search_in_doctype(doctype, text, start, limit):
'''Search for given text in given doctype in __global_search
:param doctype: doctype to be searched in
:param text: phrase to be searched
:param start: start results at, default 0
:param limit: number of results to return, default 20
:return: Array of result objects'''
text = "+" + text + "*"
results = frappe.db.sql('''
select
doctype, name, content
from
__global_search
where
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
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