Explorar el Código

[autocomplete] Now prefetching using typeahead webnotes/erpnext#861

version-14
Rushabh Mehta hace 11 años
padre
commit
115e185131
Se han modificado 15 ficheros con 1296 adiciones y 78 borrados
  1. +2
    -2
      core/doctype/communication/communication.js
  2. +2
    -0
      public/build.json
  3. +12
    -30
      public/css/typeahead.css
  4. +1142
    -0
      public/js/lib/typeahead.js
  5. +0
    -7
      public/js/lib/typeahead.min.js
  6. +1
    -1
      public/js/wn/app.js
  7. +13
    -1
      public/js/wn/assets.js
  8. +92
    -16
      public/js/wn/form/control.js
  9. +3
    -1
      public/js/wn/form/link_selector.js
  10. +1
    -0
      public/js/wn/form/script_manager.js
  11. +14
    -1
      public/js/wn/misc/utils.js
  12. +1
    -6
      webnotes/app.py
  13. +1
    -1
      webnotes/auth.py
  14. +11
    -11
      webnotes/widgets/search.py
  15. +1
    -1
      website/templates/includes/login.js

+ 2
- 2
core/doctype/communication/communication.js Ver fichero

@@ -12,10 +12,10 @@ cur_frm.cscript.onload = function(doc) {
};
cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
return{ query:"controllers.queries.customer_query" } }
return { query:"controllers.queries.customer_query" } }

cur_frm.fields_dict.supplier.get_query = function(doc,cdt,cdn) {
return{ query:"controllers.queries.supplier_query" } }
return { query:"controllers.queries.supplier_query" } }
if(doc.content)
doc.content = wn.utils.remove_script_and_style(doc.content);


+ 2
- 0
public/build.json Ver fichero

@@ -31,6 +31,7 @@
"lib/public/css/common.css",
"lib/public/css/tree_grid.css",
"lib/public/css/nprogress.css",
"lib/public/css/typeahead.css",
]
},
@@ -41,6 +42,7 @@
"lib/public/js/lib/jquery/jquery.hotkeys.js",
"lib/public/js/lib/center_image.js",
"lib/public/js/lib/bootstrap.min.js",
"lib/public/js/lib/typeahead.js",
"lib/public/js/lib/nprogress.js",
"lib/public/js/wn/provide.js",


+ 12
- 30
public/css/typeahead.css Ver fichero

@@ -1,40 +1,16 @@
.typeahead,
.tt-query,
.tt-hint {
width: 100%;
height: 46px;
padding: 8px 12px;
font-size: 24px;
line-height: 30px;
border: 2px solid #ccc;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
outline: none;
}

.typeahead {
background-color: #fff;
}

.typeahead:focus {
border: 2px solid #0097cf;
}

.tt-query {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}

.tt-hint {
color: #999
color: #999;
}

.tt-dropdown-menu {
width: 422px;
margin-top: 12px;
padding: 8px 0;
width: 100%;
margin-top: 3px;
padding: 3px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.2);
@@ -48,14 +24,20 @@

.tt-suggestion {
padding: 3px 20px;
font-size: 18px;
line-height: 24px;
}

.tt-suggestion.tt-is-under-cursor {
color: #fff;
background-color: #0097cf;
}

.tt-suggestion.tt-is-under-cursor .text-muted {
color: #ddd;
}

.input-group input.tt-query {
border-top-left-radius: 4px !important;
border-bottom-left-radius: 4px !important;
}

.tt-suggestion p {


+ 1142
- 0
public/js/lib/typeahead.js
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 0
- 7
public/js/lib/typeahead.min.js
La diferencia del archivo ha sido suprimido porque es demasiado grande
Ver fichero


+ 1
- 1
public/js/wn/app.js Ver fichero

@@ -19,7 +19,7 @@ wn.Application = Class.extend({
init: function() {
this.load_startup();
},
load_startup: function() {
var me = this;
if(window.app) {


+ 13
- 1
public/js/wn/assets.js Ver fichero

@@ -28,9 +28,21 @@ wn.assets = {
// if version is different then clear localstorage
if(window._version_number != localStorage.getItem("_version_number")) {
localStorage.clear();
localStorage.setItem("_version_number", window._version_number);
console.log("Cleared App Cache.");
}

if(localStorage._last_load) {
var not_updated_since = new Date() - new Date(localStorage._last_load);
if(not_updated_since < 10000 || not_updated_since > 86400000) {
localStorage.clear();
console.log("Cleared localstorage");
}
} else {
localStorage.clear();
console.log("Cleared localstorage");
}
localStorage._last_load = new Date();
localStorage._version_number = window._version_number;
},
// check if the asset exists in


+ 92
- 16
public/js/wn/form/control.js Ver fichero

@@ -608,19 +608,9 @@ wn.ui.form.ControlLink = wn.ui.form.ControlData.extend({
this.has_input = true;
//this.bind_change_event();
var me = this;
this.$input.on("blur", function() {
if(me.selected) {
me.selected = false;
return;
}
if(me.doctype && me.docname) {
var value = me.get_value();
if(value!==me.last_value) {
me.parse_validate_and_set_in_model(value);
}
}});
this.setup_buttons();
this.setup_autocomplete();
this.setup_typeahead();
//this.setup_autocomplete();
},
setup_buttons: function() {
var me = this;
@@ -630,7 +620,7 @@ wn.ui.form.ControlLink = wn.ui.form.ControlData.extend({
new wn.ui.form.LinkSelector({
doctype: me.df.options,
target: me,
txt: me.$input.val()
txt: me.get_value()
});
});

@@ -653,17 +643,102 @@ wn.ui.form.ControlLink = wn.ui.form.ControlData.extend({
this.$input_area.find(".btn-new").remove();
}
},
setup_autocomplete: function() {
setup_typeahead: function() {
var me = this;
var method = "webnotes.widgets.search.search_link";
var args = {};
this.set_custom_query(args);

// custom query
if(args.query) {
method = args.query
}

var _change = function() {
var val = me.get_value();
if(me.frm && me.frm.doc) {
me.selected = true;
me.parse_validate_and_set_in_model(val);
} else {
me.$input.trigger("change");
}
}

// filter based on arguments
var filter_fn = function(r) {
if(r.exc) console.log(r.exc);
var filter_args = {};
me.set_custom_query(filter_args)
if(filter_args.filters) {
return wn.utils.filter_dict(r.results, filter_args.filters);
} else {
return r.results;
}
}
// default query args
var query_args = {
cmd: method,
txt: "%",
page_len: "9999",
doctype: me.df.options,
}
// append filter keys (needed for client-side filtering)
if(args.filters) {
query_args.search_fields = ["name"].concat(keys(args.filters));
}
this.$input.typeahead("destroy").typeahead({
name: me.df.parent + ":" + me.df.fieldname,
prefetch: {
url: "server.py?" + wn.utils.get_url_from_dict(query_args),
filter: filter_fn,
},
remote: {
url: "server.py?" + wn.utils.get_url_from_dict($.extend(query_args, {"txt": null})) + "&txt=%QUERY",
filter: filter_fn,
},
template: function(d) {
if(keys(d).length > 1) {
d.info = $.map(d, function(val, key) { return key==="name" ? null : val }).join(", ");
return repl("<p>%(value)s<br><span class='text-muted'>%(info)s</span></p>", d);
} else {
return d.value;
}
}
}).on("typeahead:selected", function(d) {
_change();
}).on("typeahead:autocompleted", function(d) {
_change();
});
this.set_input = function(val) {
me.$input.typeahead("setQuery", val || "");
}
},
setup_autocomplete: function() {
this.$input.on("blur", function() {
if(me.selected) {
me.selected = false;
return;
}
if(me.doctype && me.docname) {
var value = me.get_value();
if(value!==me.last_value) {
me.parse_validate_and_set_in_model(value);
}
}});

this.$input.autocomplete({
source: function(request, response) {
var args = {
'txt': request.term,
'doctype': me.df.options,
};

me.set_custom_query(args);

return wn.call({
type: "GET",
method:'webnotes.widgets.search.search_link',
@@ -690,6 +765,7 @@ wn.ui.form.ControlLink = wn.ui.form.ControlData.extend({
}
}
}).data('uiAutocomplete')._renderItem = function(ul, item) {
if(!item.label) item.label = item.value;
return $('<li></li>')
.data('item.autocomplete', item)
.append(repl('<a><span style="font-weight: bold;">%(label)s</span><br>\


+ 3
- 1
public/js/wn/form/link_selector.js Ver fichero

@@ -22,7 +22,7 @@ wn.ui.form.LinkSelector = Class.extend({
"fields": [
{
fieldtype: "Data", fieldname: "txt", label: "Beginning with",
description: "You can use wildcard %"
description: "You can use wildcard %",
},
{
fieldtype: "Select", fieldname: "search_field", label: "Search With"
@@ -55,6 +55,8 @@ wn.ui.form.LinkSelector = Class.extend({
} else {
this.dialog.fields_dict.search_field.$wrapper.toggle(false);
}
if(this.txt)
this.dialog.fields_dict.txt.set_input(this.txt);
this.dialog.fields_dict.search.$input.on("click", function() {
me.search(this);
});


+ 1
- 0
public/js/wn/form/script_manager.js Ver fichero

@@ -63,6 +63,7 @@ wn.ui.form.ScriptManager = Class.extend({
'options': df.options,
'fetch': fetch
},
no_spinner: true,
callback: function(r) {
if(r.message=='Ok') {
if(r.fetch_values)


+ 14
- 1
public/js/wn/misc/utils.js Ver fichero

@@ -42,6 +42,14 @@ wn.utils = {
} else if(filters[key][0]=="not in") {
if(filters[key][1].indexOf(d[key])!=-1)
return;
} else if(filters[key][0]=="<") {
if (!(d[key] < filters[key])) return;
} else if(filters[key][0]=="<=") {
if (!(d[key] <= filters[key])) return;
} else if(filters[key][0]==">") {
if (!(d[key] > filters[key])) return;
} else if(filters[key][0]==">=") {
if (!(d[key] >= filters[key])) return;
}
} else {
if(d[key]!=filters[key]) return;
@@ -105,7 +113,12 @@ wn.utils = {
return args;
},
get_url_from_dict: function(args) {
return encodeURIComponent($.map(args, function(val, key) { return key+"="+val; }).join("&") || "");
return $.map(args, function(val, key) {
if(val!==null)
return encodeURIComponent(key)+"="+encodeURIComponent(val);
else
return null;
}).join("&") || "";
},
disable_export_btn: function(btn) {
if(!wn.user.is_report_manager()) {


+ 1
- 6
webnotes/app.py Ver fichero

@@ -18,11 +18,6 @@ import webnotes.webutils

local_manager = LocalManager([webnotes.local])

class MyResponse(Response):
def set_cookie(self, *args, **kwargs):
print args, kwargs
super(Response, self).set_cookie(*args, **kwargs)

@Request.application
def application(request):
webnotes.local.request = request
@@ -32,7 +27,7 @@ def application(request):
webnotes.local.form_dict = webnotes._dict({ k:v[0] if isinstance(v, (list, tuple)) else v \
for k, v in (request.form or request.args).iteritems() })
webnotes.local._response = MyResponse()
webnotes.local._response = Response()

try:
webnotes.http_request = webnotes.auth.HTTPRequest()


+ 1
- 1
webnotes/auth.py Ver fichero

@@ -57,7 +57,7 @@ class HTTPRequest:
import translate
lang_list = translate.get_lang_dict()
lang_list = lang_list and lang_list.values() or []
if not lang:
return
if ";" in lang: # not considering weightage


+ 11
- 11
webnotes/widgets/search.py Ver fichero

@@ -16,9 +16,10 @@ except ImportError:

# this is called by the Link Field
@webnotes.whitelist()
def search_link(doctype, txt, query=None, filters=None):
search_widget(doctype, txt, query, page_len=20, filters=filters)
webnotes.response['results'] = build_for_autosuggest(webnotes.response["values"])
def search_link(doctype, txt, query=None, filters=None, page_len=20, searchfield="name"):
search_widget(doctype, txt, query, searchfield=searchfield, page_len=page_len, filters=filters)
webnotes.response['results'] = build_for_autosuggest(webnotes.response["values"], searchfield)
del webnotes.response["values"]

# this is called by the search box
@webnotes.whitelist()
@@ -77,16 +78,15 @@ def get_std_fields_list(meta, key):

return ['`tab%s`.`%s`' % (meta[0].name, f.strip()) for f in sflist]

def build_for_autosuggest(res):
def build_for_autosuggest(res, searchfield):
searchfield = [s.strip() for s in searchfield.split(",")]
results = []
for r in res:
info = ''
if len(r) > 1:
info = ', '.join([cstr(t) for t in r[1:]])
if len(info) > 50:
info = "<span title=\"%s\">%s...</span>" % (info, info[:50])

results.append({'label':r[0], 'value':r[0], 'info':info})
out = {}
for i, s in enumerate(searchfield):
if s=="name": s="value"
out[s] = r[i]
results.append(out)
return results

def scrub_custom_query(query, key, txt):


+ 1
- 1
website/templates/includes/login.js Ver fichero

@@ -123,7 +123,7 @@ login.show_forgot_password = function() {
}

login.set_message = function(message, color) {
wn.msgprint(html);
wn.msgprint(message);
return;
$('#login_message').html(message).toggle(true);
}

Cargando…
Cancelar
Guardar