From a48f039e89c0f7b3b329674931b454f80a1b9db3 Mon Sep 17 00:00:00 2001 From: j Date: Sat, 4 Oct 2014 20:57:09 +0200 Subject: [PATCH] add autocomplete api --- config.json | 1 + oml/item/api.py | 55 +++++++++++++++++++++++++++++++++++++--- oml/item/models.py | 6 ++--- oml/json_pickler.py | 12 ++++----- static/js/findElement.js | 4 +-- 5 files changed, 62 insertions(+), 16 deletions(-) diff --git a/config.json b/config.json index af99bb0..9619847 100644 --- a/config.json +++ b/config.json @@ -12,6 +12,7 @@ "title": "Title", "type": "string", "autocomplete": true, + "autocompleteSort": [{"key": "title", "operator": "+"}], "columnRequired": true, "columnWidth": 256, "find": true, diff --git a/oml/item/api.py b/oml/item/api.py index fe60d4e..b8b8649 100644 --- a/oml/item/api.py +++ b/oml/item/api.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 - - import json import hashlib from sqlalchemy.orm import load_only +from sqlalchemy import func from oxtornado import actions from utils import cleanup_id @@ -148,8 +147,56 @@ def remove(data): actions.register(remove, cache=False) def autocomplete(data): - return {} -actions.register(remove, cache=False) + ''' + takes { + key: string, + value: string, + operator: string // '=', '==', '^', '$' + query: object // item query to limit results + range: [int, int] + } + returns { + items: [string, ...] //array of matching values + } + ''' + response = {} + response['items'] = [] + if not 'range' in data: + data['range'] = [0, 10] + op = data.get('operator', '=') + + key = utils.get_by_id(settings.config['itemKeys'], data['key']) + order_by = key.get('autocompleteSort', False) + add_itemsort = False + if order_by: + for o in order_by: + if o['operator'] != '-': o['operator'] = '' + order_by = ['%(operator)ssort.%(key)s' % o for o in order_by] + add_itemsort = True + else: + order_by = ['-items'] + + items = query.parse({'query': data.get('query', {})})['qs'].options(load_only('id')) + qs = state.db.session.query(models.Find.value, func.count(models.Find.value).label('items')) + qs = qs.filter(models.Find.item_id.in_(items)) + if data['value']: + value = data['value'].lower() + qs = qs.filter(models.Find.key.is_(data['key'])) + if op == '=': + qs = qs.filter(models.Find.findvalue.contains(value)) + elif op == '==': + qs = qs.filter(models.Find.findvalue.is_(value)) + elif op == '^': + qs = qs.filter(models.Find.findvalue.startswith(value)) + elif op == '$': + qs = qs.filter(models.Find.findvalue.endswith(value)) + qs = qs.group_by(models.Find.value) + if add_itemsort: + qs = qs.join(models.Item).join(models.Sort) + qs = qs.order_by(*order_by) + response['items'] = [r.value for r in qs[data['range'][0]:data['range'][1]]] + return response +actions.register(autocomplete) def findMetadata(data): ''' diff --git a/oml/item/models.py b/oml/item/models.py index 732bc7e..b58fca6 100644 --- a/oml/item/models.py +++ b/oml/item/models.py @@ -1,12 +1,9 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 - - from datetime import datetime -from io import StringIO, BytesIO +from io import BytesIO import base64 import hashlib -import json import os import re import shutil @@ -148,6 +145,7 @@ class Item(db.Model): value = list(value.values()) if isinstance(value, list): value = ''.join(value) + value = ox.get_sort_title(value) value = utils.sort_title(value).lower() else: if isinstance(value, list): diff --git a/oml/json_pickler.py b/oml/json_pickler.py index d4eb112..1eabaaf 100644 --- a/oml/json_pickler.py +++ b/oml/json_pickler.py @@ -1,11 +1,11 @@ import json -def loads(*args, **kargs): - #print('loads', args, kargs) +def loads(*args, **kwargs): + #print('loads', args, kwargs) if isinstance(args[0], bytes): args = (args[0].decode('utf-8'),) + args[1:] - return json.loads(*args, **kargs) + return json.loads(*args, **kwargs) -def dumps(*args, **kargs): - #print('dumps', args, kargs) - return json.dumps(*args, **kargs).encode() +def dumps(*args, **kwargs): + #print('dumps', args, kwargs) + return json.dumps(*args, **kwargs).encode() diff --git a/static/js/findElement.js b/static/js/findElement.js index 8c4b2da..0b6d105 100644 --- a/static/js/findElement.js +++ b/static/js/findElement.js @@ -131,7 +131,7 @@ oml.ui.findElement = function() { function getAutocomplete() { var key = !that ? ui._findState.key - : that.value()[ui._list ? 1 : 0], + : that.value()[1], findKey = Ox.getObjectById(oml.config.findKeys, key); return findKey && findKey.autocomplete ? function(value, callback) { oml.api.autocomplete({ @@ -220,4 +220,4 @@ oml.ui.findElement = function() { return that; -}; \ No newline at end of file +};