From 96805eeb9edbbdde2277d155090c955cfa664506 Mon Sep 17 00:00:00 2001 From: Terry Truong Date: Sat, 14 Jan 2023 16:10:31 +1100 Subject: Allow showing events without images Add setting for showing such events Fix searches not always avoiding filtered categories --- backend/histplorer.py | 16 ++++++++-------- src/components/InfoModal.vue | 4 ++-- src/components/SearchModal.vue | 14 +++++++++++--- src/components/SettingsModal.vue | 4 ++++ src/components/TimeLine.vue | 5 ++++- src/lib.ts | 10 +++++----- src/store.ts | 2 ++ 7 files changed, 36 insertions(+), 19 deletions(-) diff --git a/backend/histplorer.py b/backend/histplorer.py index bf0d51e..f1decc8 100755 --- a/backend/histplorer.py +++ b/backend/histplorer.py @@ -45,7 +45,7 @@ class Event: end: HistDate | None, endUpper: HistDate | None, ctg: str, - imgId: int, + imgId: int | None, pop: int): self.id = id self.title = title @@ -92,7 +92,7 @@ class ImgInfo: return str(self.__dict__) class EventInfo: """ Used when responding to type=info requests """ - def __init__(self, event: Event, desc: str | None, wikiId: int, imgInfo: ImgInfo): + def __init__(self, event: Event, desc: str | None, wikiId: int, imgInfo: ImgInfo | None): self.event = event self.desc = desc self.wikiId = wikiId @@ -211,8 +211,8 @@ def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctgs: 'SELECT events.id, title, start, start_upper, end, end_upper, fmt, ctg, images.id, pop.pop FROM events' \ ' INNER JOIN event_disp ON events.id = event_disp.id' \ ' INNER JOIN pop ON events.id = pop.id' \ - ' INNER JOIN event_imgs ON events.id = event_imgs.id' \ - ' INNER JOIN images ON event_imgs.img_id = images.id' + ' LEFT JOIN event_imgs ON events.id = event_imgs.id' \ + ' LEFT JOIN images ON event_imgs.img_id = images.id' constraints = ['event_disp.scale = ?'] params: list[str | int] = [scale] # Constrain by start/end @@ -256,7 +256,7 @@ def lookupEvents(start: HistDate | None, end: HistDate | None, scale: int, ctgs: # return results def eventEntryToResults( - row: tuple[int, str, int, int | None, int | None, int | None, int, str, int, int]) -> Event: + row: tuple[int, str, int, int | None, int | None, int | None, int, str, int | None, int]) -> Event: eventId, title, start, startUpper, end, endUpper, fmt, ctg, imageId, pop = row """ Helper for converting an 'events' db entry into an Event object """ # Convert dates @@ -299,15 +299,15 @@ def lookupEventInfo(eventTitle: str, dbCur: sqlite3.Cursor) -> EventInfo | None: ' descs.desc, descs.wiki_id, ' \ ' images.url, images.license, images.artist, images.credit FROM events' \ ' INNER JOIN pop ON events.id = pop.id' \ - ' INNER JOIN event_imgs ON events.id = event_imgs.id' \ - ' INNER JOIN images ON event_imgs.img_id = images.id' \ + ' LEFT JOIN event_imgs ON events.id = event_imgs.id' \ + ' LEFT JOIN images ON event_imgs.img_id = images.id' \ ' LEFT JOIN descs ON events.id = descs.id' \ ' WHERE events.title = ? COLLATE NOCASE' row = dbCur.execute(query, (eventTitle,)).fetchone() if row is not None: event = eventEntryToResults(row[:10]) desc, wikiId, url, license, artist, credit = row[10:] - return EventInfo(event, desc, wikiId, ImgInfo(url, license, artist, credit)) + return EventInfo(event, desc, wikiId, None if url is None else ImgInfo(url, license, artist, credit)) else: return None diff --git a/src/components/InfoModal.vue b/src/components/InfoModal.vue index f709676..cd067e1 100644 --- a/src/components/InfoModal.vue +++ b/src/components/InfoModal.vue @@ -16,7 +16,7 @@
-
+
@@ -153,7 +153,7 @@ const imgStyles = computed(() => { return { width: '200px', height: '200px', - backgroundImage: `url(${getImagePath(event.value.imgId)})`, + backgroundImage: event.value.imgId == null ? 'none' : `url(${getImagePath(event.value.imgId)})`, backgroundColor: store.color.bgDark, backgroundSize: 'cover', borderRadius: store.borderRadius + 'px', diff --git a/src/components/SearchModal.vue b/src/components/SearchModal.vue index 0ed2888..0673f59 100644 --- a/src/components/SearchModal.vue +++ b/src/components/SearchModal.vue @@ -157,11 +157,16 @@ async function resolveSearch(eventTitle: string){ } // Check if the event data is already here if (props.titleToEvent.has(eventTitle)){ - if (visibleCtgs != null && !visibleCtgs.includes(props.titleToEvent.get(eventTitle).ctg)){ + let event = props.titleToEvent.get(eventTitle)!; + if (visibleCtgs != null && !visibleCtgs.includes(event.ctg)){ console.log('INFO: Ignoring search for known event due to category filter'); return; } - emit('search', props.titleToEvent.get(eventTitle)); + if (store.reqImgs && event.imgId == null){ + console.log('INFO: Ignoring search for known event due to image-only display'); + return; + } + emit('search', event); return; } // Query server for event @@ -169,11 +174,14 @@ async function resolveSearch(eventTitle: string){ let responseObj: EventInfoJson | null = await queryServer(urlParams); if (responseObj != null){ let eventInfo = jsonToEventInfo(responseObj); - // Check if event category is disabled if (visibleCtgs != null && !visibleCtgs.includes(eventInfo.event.ctg)){ console.log('INFO: Ignoring search result due to category filter'); return; } + if (store.reqImgs && eventInfo.event.imgId == null){ + console.log('INFO: Ignoring search result due to image-only display'); + return; + } emit('search', eventInfo.event); } else { // Trigger failure animation diff --git a/src/components/SettingsModal.vue b/src/components/SettingsModal.vue index 21ac7b8..d9caa34 100644 --- a/src/components/SettingsModal.vue +++ b/src/components/SettingsModal.vue @@ -26,6 +26,10 @@

Display

+
+ +
diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 8aeb883..bab6e5e 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -448,6 +448,9 @@ const idToEvent = computed(() => { // Maps visible event IDs to HistEvents if ((store.ctgs as {[ctg: string]: boolean})[event.ctg] == false){ continue; } + if (store.reqImgs && event.imgId == null){ + continue; + } map.set(event.id, event); } return map; @@ -1288,7 +1291,7 @@ function eventImgStyles(eventId: number){ return { width: store.eventImgSz + 'px', height: store.eventImgSz + 'px', - backgroundImage: `url(${getImagePath(event.imgId)})`, + backgroundImage: event.imgId == null ? 'none' : `url(${getImagePath(event.imgId)})`, backgroundColor: store.color.bgDark, backgroundSize: 'cover', borderColor: color, diff --git a/src/lib.ts b/src/lib.ts index 53ce401..6a9f553 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -315,8 +315,8 @@ export class EventInfo { event: HistEvent; desc: string | null; wikiId: number; - imgInfo: ImgInfo; - constructor(event: HistEvent, desc: string, wikiId: number, imgInfo: ImgInfo){ + imgInfo: ImgInfo | null; + constructor(event: HistEvent, desc: string, wikiId: number, imgInfo: ImgInfo | null){ this.event = event; this.desc = desc; this.wikiId = wikiId; @@ -459,7 +459,7 @@ export type EventInfoJson = { event: HistEventJson, desc: string, wikiId: number, - imgInfo: ImgInfoJson, + imgInfo: ImgInfoJson | null, } export type ImgInfoJson = { url: string, @@ -490,8 +490,8 @@ export function jsonToHistEvent(json: HistEventJson): HistEvent { export function jsonToEventInfo(json: EventInfoJson): EventInfo { return new EventInfo(jsonToHistEvent(json.event), json.desc, json.wikiId, jsonToImgInfo(json.imgInfo)); } -export function jsonToImgInfo(json: ImgInfoJson): ImgInfo { - return new ImgInfo(json.url, json.license, json.artist, json.credit); +export function jsonToImgInfo(json: ImgInfoJson | null): ImgInfo | null { + return json == null ? null : new ImgInfo(json.url, json.license, json.artist, json.credit); } // For dates in a timeline diff --git a/src/store.ts b/src/store.ts index a366894..3778649 100644 --- a/src/store.ts +++ b/src/store.ts @@ -30,6 +30,7 @@ export type StoreState = { dragInertia: number, // Multiplied by final-drag-speed (pixels-per-sec) to get extra scroll distance disableShortcuts: boolean, // Other feature-specific + reqImgs: boolean, // Only show events with images showEventCounts: boolean, searchSuggLimit: number, ctgs: { // Specifies event categories, and which ones should be visible @@ -104,6 +105,7 @@ function getDefaultState(): StoreState { dragInertia: 0.1, disableShortcuts: false, // Other feature-specific + reqImgs: true, showEventCounts: true, searchSuggLimit: 10, ctgs: { -- cgit v1.2.3