summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/Api.py5
-rw-r--r--module/FileManager.py7
-rw-r--r--module/api/ApiComponent.py1
-rw-r--r--module/api/FileApi.py12
-rw-r--r--module/database/FileDatabase.py12
-rw-r--r--module/remote/apitypes.py4
-rw-r--r--module/remote/apitypes_debug.py2
-rw-r--r--module/remote/pyload.thrift2
-rw-r--r--module/web/static/js/views/filterView.js15
-rw-r--r--tests/other/test_filedatabase.py3
10 files changed, 44 insertions, 19 deletions
diff --git a/module/Api.py b/module/Api.py
index 6ef425d26..577c420c3 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -39,6 +39,7 @@ def RequirePerm(bits):
return _Dec
+# TODO: not needed anymore
# decorator to annotate user methods, these methods must have user=None kwarg.
class UserContext(object):
def __new__(cls, f, *args, **kwargs):
@@ -91,6 +92,10 @@ class Api(Iface):
def user(self):
return None #TODO return default user?
+ @property
+ def userHandle(self):
+ return self.user.primary if self.user is not None else None
+
@classmethod
def initComponents(cls):
# Allow extending the api
diff --git a/module/FileManager.py b/module/FileManager.py
index 1d8cdf328..74ff2ebeb 100644
--- a/module/FileManager.py
+++ b/module/FileManager.py
@@ -177,7 +177,7 @@ class FileManager:
return self.db.getFileInfo(fid)
@lock
- def getTree(self, pid, full, state):
+ def getTree(self, pid, full, state, search=None):
""" return a TreeCollection and fill the info data of containing packages.
optional filter only unfnished files
"""
@@ -187,7 +187,7 @@ class FileManager:
root = pid if not full else None
packs = self.db.getAllPackages(root)
- files = self.db.getAllFiles(package=root, state=state)
+ files = self.db.getAllFiles(package=root, state=state, search=search)
# updating from cache
for fid, f in self.files.iteritems():
@@ -320,9 +320,6 @@ class FileManager:
def scanDownloadFolder(self):
pass
- def searchFile(self, pattern):
- return self.db.getAllFiles(search=pattern)
-
@lock
@invalidate
def deletePackage(self, pid):
diff --git a/module/api/ApiComponent.py b/module/api/ApiComponent.py
index fadcf98da..c3b8c974b 100644
--- a/module/api/ApiComponent.py
+++ b/module/api/ApiComponent.py
@@ -18,5 +18,6 @@ class ApiComponent(Iface):
self.core = core
assert isinstance(user, User)
self.user = user
+ self.userHandle = 0
# No instantiating!
raise Exception() \ No newline at end of file
diff --git a/module/api/FileApi.py b/module/api/FileApi.py
index fa9d728cb..8f09f3cb7 100644
--- a/module/api/FileApi.py
+++ b/module/api/FileApi.py
@@ -2,9 +2,11 @@
# -*- coding: utf-8 -*-
from module.Api import Api, RequirePerm, Permission, DownloadState, PackageDoesNotExists, FileDoesNotExists
+from module.utils import uniqify
from ApiComponent import ApiComponent
+# TODO: user context
class FileApi(ApiComponent):
"""Everything related to available packages or files. Deleting, Modifying and so on."""
@@ -74,13 +76,13 @@ class FileApi(ApiComponent):
@RequirePerm(Permission.All)
def findFiles(self, pattern):
- pass
+ return self.core.files.getTree(-1, True, DownloadState.All, pattern)
@RequirePerm(Permission.All)
- def getAutocompletion(self, pattern):
- # TODO
-
- return ["static", "autocompletion", "demo"]
+ def searchSuggestions(self, pattern):
+ names = self.core.db.getMatchingFilenames(pattern, self.userHandle)
+ # TODO: stemming and reducing the names to provide better suggestions
+ return uniqify(names)
@RequirePerm(Permission.All)
def findPackages(self, tags):
diff --git a/module/database/FileDatabase.py b/module/database/FileDatabase.py
index 9d11ffe46..557d9c034 100644
--- a/module/database/FileDatabase.py
+++ b/module/database/FileDatabase.py
@@ -164,6 +164,18 @@ class FileMethods(DatabaseMethods):
return data
@queue
+ def getMatchingFilenames(self, pattern, owner=None):
+ """ Return matching file names for pattern, useful for search suggestions """
+ qry = 'SELECT name FROM files WHERE name LIKE ?'
+ args = ["%%%s%%" % pattern.strip("%")]
+ if owner:
+ qry += " AND owner=?"
+ args.append(owner)
+
+ self.c.execute(qry, args)
+ return [r[0] for r in self.c]
+
+ @queue
def getAllPackages(self, root=None, owner=None, tags=None):
""" Return dict with package information
diff --git a/module/remote/apitypes.py b/module/remote/apitypes.py
index 1f91403d5..bc53f5f7c 100644
--- a/module/remote/apitypes.py
+++ b/module/remote/apitypes.py
@@ -417,8 +417,6 @@ class Iface(object):
pass
def getAllUserData(self):
pass
- def getAutocompletion(self, pattern):
- pass
def getAvailablePlugins(self):
pass
def getCollector(self):
@@ -501,6 +499,8 @@ class Iface(object):
pass
def saveConfig(self, config):
pass
+ def searchSuggestions(self, pattern):
+ pass
def setConfigHandler(self, plugin, iid, value):
pass
def setConfigValue(self, section, option, value):
diff --git a/module/remote/apitypes_debug.py b/module/remote/apitypes_debug.py
index 3c4f67a49..974a68c29 100644
--- a/module/remote/apitypes_debug.py
+++ b/module/remote/apitypes_debug.py
@@ -77,7 +77,6 @@ methods = {
'getAddonHandler': (dict, basestring, list),
'getAllFiles': TreeCollection,
'getAllUserData': (dict, int, UserData),
- 'getAutocompletion': (list, basestring),
'getAvailablePlugins': (list, ConfigInfo),
'getCollector': (list, LinkStatus),
'getConfig': (dict, basestring, ConfigHolder),
@@ -119,6 +118,7 @@ methods = {
'restartFile': None,
'restartPackage': None,
'saveConfig': None,
+ 'searchSuggestions': (list, basestring),
'setConfigHandler': None,
'setConfigValue': None,
'setInteractionResult': None,
diff --git a/module/remote/pyload.thrift b/module/remote/pyload.thrift
index 7eadd54e6..c66ec20d6 100644
--- a/module/remote/pyload.thrift
+++ b/module/remote/pyload.thrift
@@ -450,8 +450,8 @@ service Pyload {
FileInfo getFileInfo(1: FileID fid) throws (1: FileDoesNotExists e),
TreeCollection findFiles(1: string pattern),
- list<string> getAutocompletion(1: string pattern),
TreeCollection findPackages(1: list<string> tags),
+ list<string> searchSuggestions(1: string pattern),
// Modify Files/Packages
diff --git a/module/web/static/js/views/filterView.js b/module/web/static/js/views/filterView.js
index ea0aff0d5..19501430a 100644
--- a/module/web/static/js/views/filterView.js
+++ b/module/web/static/js/views/filterView.js
@@ -29,7 +29,7 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],
$.fn.typeahead.Constructor.prototype.show = show;
this.$('.search-query').typeahead({
minLength: 2,
- source: this.getAutocompletion
+ source: this.getSuggestions
});
this.stateMenu = this.$('.dropdown-toggle .state');
@@ -43,10 +43,15 @@ define(['jquery', 'backbone', 'underscore', 'app', 'utils/apitypes'],
return this;
},
- getAutocompletion: function() {
- return ["static", "autocompletion", "demo", "with", "some", "keywords",
- "a very long proposal for autocompletion", "autobot",
- "a very long proposal for autocompletion second one"];
+ getSuggestions: function(query, callback) {
+ console.log(callback);
+ $.ajax('/api/searchSuggestions', {
+ method: 'POST',
+ data: {pattern: JSON.stringify(query)},
+ success: function(data) {
+ callback(data);
+ }
+ });
},
switch_filter: function(e) {
diff --git a/tests/other/test_filedatabase.py b/tests/other/test_filedatabase.py
index 314377db8..3a63b75d5 100644
--- a/tests/other/test_filedatabase.py
+++ b/tests/other/test_filedatabase.py
@@ -120,6 +120,9 @@ class TestDatabase(BenchmarkTest):
f = choice(files.values())
assert "1" in f.name
+ names = self.db.getMatchingFilenames("1")
+ for name in names:
+ assert "1" in name
def test_collector(self):
self.db.saveCollector(0, "data")