diff options
| author | Terry Truong <terry06890@gmail.com> | 2023-01-06 20:23:45 +1100 |
|---|---|---|
| committer | Terry Truong <terry06890@gmail.com> | 2023-01-06 20:23:45 +1100 |
| commit | d8c29e8dcc925b6013880f66e690fa6b006d9154 (patch) | |
| tree | 479cc362b33862cce89694671d7b1a24f3b8bdae /backend | |
| parent | 50fc47e6e387c3b278526ef773badf63913389d6 (diff) | |
Implement filtering by event categories
Filter events in display and search suggestions.
Make server queries allow specification of multiple categories.
Make settings modal avoid disabling all categories.
Diffstat (limited to 'backend')
| -rwxr-xr-x | backend/histplorer.py | 31 | ||||
| -rw-r--r-- | backend/tests/test_histplorer.py | 10 |
2 files changed, 21 insertions, 20 deletions
diff --git a/backend/histplorer.py b/backend/histplorer.py index 988b69d..a553f88 100755 --- a/backend/histplorer.py +++ b/backend/histplorer.py @@ -16,7 +16,8 @@ Expected HTTP query parameters: - event: With type=info, specifies the event title to get info for - input: With type=sugg, specifies a search string to suggest for - limit: With type=events or type=sugg, specifies the max number of results -- ctg: With type=events or type=sugg, specifies an event category to restrict results to +- ctgs: With type=events or type=sugg, specifies event categories to restrict results to + Interpreted as a period-separated list of category names (eg: person.place). An empty string is ignored. """ from typing import Iterable @@ -171,7 +172,7 @@ def handleEventsReq(params: dict[str, str], dbCur: sqlite3.Cursor) -> EventRespo print('INFO: Invalid scale value', file=sys.stderr) return None # Get event category - ctg = params['ctg'] if 'ctg' in params else None + ctgs = params['ctgs'].split('.') if 'ctgs' in params else None # Get incl value try: incl = int(params['incl']) if 'incl' in params else None @@ -188,7 +189,7 @@ def handleEventsReq(params: dict[str, str], dbCur: sqlite3.Cursor) -> EventRespo print(f'INFO: Invalid results limit {resultLimit}', file=sys.stderr) return None # - events = lookupEvents(start, end, scale, ctg, incl, resultLimit, dbCur) + events = lookupEvents(start, end, scale, ctgs, incl, resultLimit, dbCur) unitCounts = lookupUnitCounts(start, end, scale, dbCur) return EventResponse(events, unitCounts) def reqParamToHistDate(s: str): @@ -202,7 +203,7 @@ def reqParamToHistDate(s: str): return HistDate(None, int(m.group(1))) else: return HistDate(True, int(m.group(1)), int(m.group(2)), int(m.group(3))) -def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctg: str | None, +def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctgs: list[str] | None, incl: int | None, resultLimit: int, dbCur: sqlite3.Cursor) -> list[Event]: """ Looks for events within a date range, in given scale, restricted by event category, an optional particular inclusion, and a result limit """ @@ -232,9 +233,9 @@ def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctg: constraints.append('event_disp.unit < ?') params.append(endUnit) # Constrain by event category - if ctg is not None: - constraints.append('ctg = ?') - params.append(ctg) + if ctgs is not None: + constraints.append('ctg IN (' + ','.join('?' * len(ctgs)) + ')') + params.extend(ctgs) # Add constraints to query query2 = query if constraints: @@ -341,24 +342,24 @@ def handleSuggReq(params: dict[str, str], dbCur: sqlite3.Cursor): print(f'INFO: Invalid suggestion limit {resultLimit}', file=sys.stderr) return None # - ctg = params['ctg'] if 'ctg' in params else None - return lookupSuggs(searchStr, resultLimit, ctg, dbCur) -def lookupSuggs(searchStr: str, resultLimit: int, ctg: str | None, dbCur: sqlite3.Cursor) -> SuggResponse: + ctgs = params['ctgs'].split('.') if 'ctgs' in params else None + return lookupSuggs(searchStr, resultLimit, ctgs, dbCur) +def lookupSuggs(searchStr: str, resultLimit: int, ctgs: list[str] | None, dbCur: sqlite3.Cursor) -> SuggResponse: """ For a search string, returns a SuggResponse describing search suggestions """ tempLimit = resultLimit + 1 # For determining if 'more suggestions exist' query = 'SELECT title FROM events LEFT JOIN pop ON events.id = pop.id WHERE title LIKE ?' - if ctg is not None: - query += ' AND ctg = ?' - query += f' ORDER BY pop.pop DESC LIMIT + {tempLimit}' + if ctgs is not None: + query += ' AND ctg IN (' + ','.join('?' * len(ctgs)) + ')' + query += f' ORDER BY pop.pop DESC LIMIT {tempLimit}' suggs: list[str] = [] # Prefix search - params = [searchStr + '%'] + ([ctg] if ctg is not None else []) + params = [searchStr + '%'] + (ctgs if ctgs is not None else []) for (title,) in dbCur.execute(query, params): suggs.append(title) # If insufficient results, try substring search if len(suggs) < tempLimit: existing = set(suggs) - params = ['%' + searchStr + '%'] + ([ctg] if ctg is not None else []) + params = ['%' + searchStr + '%'] + (ctgs if ctgs is not None else []) for (title,) in dbCur.execute(query, params): if title not in existing: suggs.append(title) diff --git a/backend/tests/test_histplorer.py b/backend/tests/test_histplorer.py index fcaafb5..8f7e281 100644 --- a/backend/tests/test_histplorer.py +++ b/backend/tests/test_histplorer.py @@ -12,7 +12,7 @@ def initTestDb(dbFile: str) -> None: 'INSERT INTO events VALUES (?, ?, ?, ?, ?, ?, ?, ?)', { (1, 'event one', 1900, None, None, None, 0, 'event'), - (2, 'event two', 2452594, None, 2455369, None, 3, 'human'), # 2/11/2002 to 21/06/2010 + (2, 'event two', 2452594, None, 2455369, None, 3, 'person'), # 2/11/2002 to 21/06/2010 (3, 'event three', 2448175, 2451828, None, None, 1, 'discovery'), # 10/10/1990 til 10/10/2000 (4, 'event four', 991206, None, 1721706, None, 2, 'event'), # 10/10/-2000 to 10/10/1 (5, 'event five', 2000, None, 2001, None, 0, 'event'), @@ -116,7 +116,7 @@ class TestHandleReq(unittest.TestCase): 'discovery', 30, 0), ]) self.assertEqual(response.unitCounts, {1900: 2, 1990: 1, 2000: 1, 2001: 1}) - response = handleReq(self.dbFile, {'QUERY_STRING': 'type=events&range=.1999-11-27&scale=1&ctg=event'}) + response = handleReq(self.dbFile, {'QUERY_STRING': 'type=events&range=.1999-11-27&scale=1&ctgs=event'}) self.assertEqual(response.events, [ Event(4, 'event four', HistDate(False, -2000, 10, 10), None, HistDate(False, 1, 10, 10), None, 'event', 20, 1000), @@ -139,7 +139,7 @@ class TestHandleReq(unittest.TestCase): def test_sugg_req(self): response = handleReq(self.dbFile, {'QUERY_STRING': 'type=sugg&input=event t'}) self.assertEqual(response, SuggResponse(['event two', 'event three'], False)) - response = handleReq(self.dbFile, {'QUERY_STRING': 'type=sugg&input=o&ctg=event'}) - self.assertEqual(response, SuggResponse(['event four', 'event one'], False)) - response = handleReq(self.dbFile, {'QUERY_STRING': 'type=sugg&input=event&ctg=event&limit=1'}) + response = handleReq(self.dbFile, {'QUERY_STRING': 'type=sugg&input=o&ctgs=event.person'}) + self.assertEqual(response, SuggResponse(['event four', 'event two', 'event one'], False)) + response = handleReq(self.dbFile, {'QUERY_STRING': 'type=sugg&input=event&ctgs=event&limit=1'}) self.assertEqual(response, SuggResponse(['event four'], True)) |
