From 48bb9dea38124ffbb3833b5828ee300e6772a225 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Tue, 27 Feb 2024 13:34:35 +0800 Subject: [PATCH 01/45] Update datagovsg-search.js --- assets/js/datagovsg-search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/datagovsg-search.js b/assets/js/datagovsg-search.js index b7d22c14..c208940e 100644 --- a/assets/js/datagovsg-search.js +++ b/assets/js/datagovsg-search.js @@ -82,7 +82,7 @@ function databaseSearch(searchTerm, index, callback) { if (isDgsV2) { // Datagov-v2 search - query for dataset metadata first to retrieve column info request = $.ajax({ - url: `https://api-production.data.gov.sg/v2/public/api/datasets/${resourceId}/metadata`, + url: `https://api-staging.data.gov.sg/v2/public/api/datasets/${resourceId}/metadata`, dataType: 'json' }).then((resp) => { const respData = Object.values(resp.data.columnMetadata.metaMapping) @@ -96,7 +96,7 @@ function databaseSearch(searchTerm, index, callback) { data.q = JSON.stringify({[formattedSearchField]: searchTerm}) } return $.ajax({ - url: 'https://data.gov.sg/api/action/datastore_search', + url: 'https://35q3y4991j.execute-api.ap-southeast-1.amazonaws.com/api/action/datastore_search', data: data, dataType: 'json', success: callback @@ -106,7 +106,7 @@ function databaseSearch(searchTerm, index, callback) { } else { data.q = searchTerm request = $.ajax({ - url: 'https://data.gov.sg/api/action/datastore_search', + url: 'https://35q3y4991j.execute-api.ap-southeast-1.amazonaws.com/api/action/datastore_search', data: data, dataType: 'json', success: callback From df885969208128014b77b1558b256c5052c5e5c8 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Tue, 27 Feb 2024 13:41:33 +0800 Subject: [PATCH 02/45] Update algolia-search.js --- assets/js/algolia-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 1c52d194..ad249691 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -4,7 +4,7 @@ const searchClient = algoliasearch( ); const search = instantsearch({ - indexName: "ogp_egazettes_index", + indexName: "staging_ogp_egazettes_index", searchClient, }); From 67387cba4f9f56e3d2090f98a97a6c2c4ddcefc6 Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:11:58 +0800 Subject: [PATCH 03/45] feat(egazette): add filtering --- _includes/main_scripts.html | 1 + _layouts/egazette-search.html | 60 +++++++++++++++++++++-------------- assets/js/algolia-search.js | 34 ++++++++++++++++++-- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/_includes/main_scripts.html b/_includes/main_scripts.html index 9d6cf3f6..67a51589 100644 --- a/_includes/main_scripts.html +++ b/_includes/main_scripts.html @@ -82,6 +82,7 @@ +
test
{%- endif -%} {%- include chatbot-scripts.html -%} diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index fc871911..477e5ed5 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -39,34 +39,48 @@

{{- page.title -}}

-
-
-
-
Search results
-
-
+
+
+
Select category
+
+
Select sub-category test changes
+
+
Select date
+
+
Select number
+
+ +
+
+
+
+
Search results
+
+
+
-
-
- -
-
-
-
-
- -

- +
+
+ +
+
+
+
+
+ +

+ +
+
+
-
-
+
-
-
-
- +
+
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index ad249691..f8bc7932 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -13,12 +13,42 @@ search.addWidgets([ instantsearch.widgets.searchBox({ container: "#searchbox", autofocus: true, - placeholder: "Start typing to search" + placeholder: "Start typing to search", }), instantsearch.widgets.poweredBy({ container: "#poweredby", - theme: 'dark', + theme: "dark", }), + instantsearch.widgets.refinementList({ + container: "#refinement-list-category", + attribute: "category", + }), + instantsearch.widgets.refinementList({ + container: "#refinement-list-subcategory", + attribute: "subCategory", + }), + instantsearch.widgets.refinementList({ + container: "#refinement-list-date", + attribute: "publishDate", + + transformItems(items) { + return items.map((item) => ({ + ...item, + highlighted: item.highlighted.slice(0, 10), + label: item.label.slice(0, 10), + })); + }, + }), + instantsearch.widgets.refinementList({ + container: "#refinement-list-number", + attribute: "notificationNum", + }), + // instantsearch.widgets.currentRefinements({ + // container: "#current-refinements", + // }), + // instantsearch.widgets.clearRefinements({ + // container: "#clear-refinements", + // }), instantsearch.widgets.hits({ container: "#hits", templates: { From 81a00d4e89ec355f645752c07349ecaa28c8e3e4 Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:06:19 +0800 Subject: [PATCH 04/45] feat(egazette): add filtering --- _includes/main_scripts.html | 1 - _layouts/egazette-search.html | 79 ++++++++++++++++++++--------------- assets/css/algolia.css | 17 +++++++- assets/js/algolia-search.js | 70 ++++++++++++++++++++----------- 4 files changed, 106 insertions(+), 61 deletions(-) diff --git a/_includes/main_scripts.html b/_includes/main_scripts.html index 67a51589..9d6cf3f6 100644 --- a/_includes/main_scripts.html +++ b/_includes/main_scripts.html @@ -82,7 +82,6 @@ -
test
{%- endif -%} {%- include chatbot-scripts.html -%} diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 477e5ed5..38cc0a55 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -39,48 +39,59 @@

{{- page.title -}}

-
-
-
Select category
-
-
Select sub-category test changes
-
-
Select date
-
-
Select number
-
- -
-
-
-
-
Search results
-
-
-
+
+
+
+
+
Select category
+
+ +
Select sub-category
+
+ +
Select day
+
+ +
Select month
+
+ +
Select year
+
+ +
Select number
+
+
-
-
- -
+ +
+
+
+

Search results

+
+
+
+
+
+
+
-
-
-
- -

- +
+
+ +
+
+
+
+
-
-
-
+
-
+
diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 3c8c853f..54186654 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -40,4 +40,19 @@ .ais-PoweredBy a { display: flex; align-items: center; -} \ No newline at end of file +} + +.ais-CurrentRefinements-delete { + height: auto; +} + +/* copying over from ais-ClearRefinements-item */ +.ais-ClearRefinements-button { + width: auto; + height: auto; + margin-top: 0.5rem; +} + +.ais-ClearRefinements-button[disabled] { + display: none; +} diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index f8bc7932..71138be8 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -15,6 +15,29 @@ search.addWidgets([ autofocus: true, placeholder: "Start typing to search", }), + instantsearch.widgets.stats({ + container: "#stats", + templates: { + text(data, { html }) { + let content = ""; + + if (data.hasManyResults) { + if (data.nbHits > 1000) { + content += `More than 1000 results found`; + } else { + content += `${data.nbHits} results found`; + } + } else if (data.hasOneResult) { + content += `1 result found`; + } else { + content += `no result found`; + } + + return html`

${content}

`; + }, + }, + }), + instantsearch.widgets.poweredBy({ container: "#poweredby", theme: "dark", @@ -28,27 +51,23 @@ search.addWidgets([ attribute: "subCategory", }), instantsearch.widgets.refinementList({ - container: "#refinement-list-date", - attribute: "publishDate", - - transformItems(items) { - return items.map((item) => ({ - ...item, - highlighted: item.highlighted.slice(0, 10), - label: item.label.slice(0, 10), - })); - }, + container: "#refinement-list-year", + attribute: "publishYear", + searchable: true, }), instantsearch.widgets.refinementList({ container: "#refinement-list-number", attribute: "notificationNum", }), - // instantsearch.widgets.currentRefinements({ - // container: "#current-refinements", - // }), - // instantsearch.widgets.clearRefinements({ - // container: "#clear-refinements", - // }), + instantsearch.widgets.currentRefinements({ + container: "#current-refinements", + cssClasses: { + delete: "currentRefinementsIsomer", + }, + }), + instantsearch.widgets.clearRefinements({ + container: "#clear-refinements", + }), instantsearch.widgets.hits({ container: "#hits", templates: { @@ -87,15 +106,16 @@ search.addWidgets([

Publish date: ${new Date( hit.publishTimestamp ).toLocaleDateString("fr-CA")}

- ${hit.text - ? `

Content: ${instantsearch.snippet( - { - attribute: "text", - highlightedTagName: "mark", - hit, - } - )}

` - : "" + ${ + hit.text + ? `

Content: ${instantsearch.snippet( + { + attribute: "text", + highlightedTagName: "mark", + hit, + } + )}

` + : "" }

From f97ac09df1ce5e2c90d570d6c7852044d27505e8 Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Wed, 3 Apr 2024 18:03:31 +0800 Subject: [PATCH 05/45] 03 27 feat egazette add filtering (#400) * feat(egazette): add filtering * test * fix(index): correct index name --- _layouts/egazette-search.html | 9 --------- assets/js/algolia-search.js | 8 +++++++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 38cc0a55..9974b0b0 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -48,20 +48,11 @@

Select category
Select sub-category
- -
Select day
-
- -
Select month
-
-
Select year
Select number
-
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 71138be8..4a0c09ea 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -3,8 +3,14 @@ const searchClient = algoliasearch( "0ba2c5f100ff5fd004415e4abbcf9b9c" ); +const PROD_URL = "https://www.egazette.gov.sg"; +const isProd = window.location.origin === PROD_URL; +const algoliaIndexName = isProd + ? "ogp_egazettes_index" + : "staging_ogp_egazettes_index"; + const search = instantsearch({ - indexName: "staging_ogp_egazettes_index", + indexName: algoliaIndexName, searchClient, }); From ee5079570c9498737e772a8459e37fa8c2c8fddd Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Thu, 4 Apr 2024 00:04:07 +0800 Subject: [PATCH 06/45] 03 27 feat egazette add filtering (#401) * feat(egazette): add filtering * test * fix(index): correct index name * fix(year-search): not functional * test * test * test * test * test * test --- _layouts/egazette-search.html | 3 --- assets/css/algolia.css | 4 ++++ assets/js/algolia-search.js | 6 +----- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 9974b0b0..a09555f1 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -50,9 +50,6 @@
Select sub-category
Select year
- -
Select number
-
diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 54186654..7afc6be0 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -56,3 +56,7 @@ .ais-ClearRefinements-button[disabled] { display: none; } + +.ais-RefinementList-item--selected .ais-RefinementList-checkbox { + background-image: url("https://raw.githubusercontent.com/atisawd/boxicons/master/svg/regular/bx-check.svg"); +} diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 4a0c09ea..d1468b6c 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -59,11 +59,6 @@ search.addWidgets([ instantsearch.widgets.refinementList({ container: "#refinement-list-year", attribute: "publishYear", - searchable: true, - }), - instantsearch.widgets.refinementList({ - container: "#refinement-list-number", - attribute: "notificationNum", }), instantsearch.widgets.currentRefinements({ container: "#current-refinements", @@ -74,6 +69,7 @@ search.addWidgets([ instantsearch.widgets.clearRefinements({ container: "#clear-refinements", }), + instantsearch.widgets.hits({ container: "#hits", templates: { From b0c86b061183e3f81ea69e5912e915de278e0155 Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Thu, 4 Apr 2024 12:51:42 +0800 Subject: [PATCH 07/45] fix(category): show pinned category --- assets/js/algolia-search.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index d1468b6c..711513f5 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -51,6 +51,7 @@ search.addWidgets([ instantsearch.widgets.refinementList({ container: "#refinement-list-category", attribute: "category", + limit: 20, }), instantsearch.widgets.refinementList({ container: "#refinement-list-subcategory", From b99344ba317912d3b4545ba8d780c334ebd8c217 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Tue, 16 Apr 2024 12:55:11 +0800 Subject: [PATCH 08/45] chore: change sidebar from select to filter by --- _layouts/egazette-search.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index a09555f1..ab31fb6c 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -43,12 +43,12 @@

{{- page.title -}}

-
Select category
+
Filter by category
-
Select sub-category
+
Filter by sub-category
-
Select year
+
Filter by year
From 2255af33c723ca7f0903d2131c5c68503d02c76d Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 17 Apr 2024 15:43:52 +0800 Subject: [PATCH 09/45] feat: add sorted by most recent --- _layouts/egazette-search.html | 6 +++--- assets/js/algolia-search.js | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index ab31fb6c..575594d2 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -55,13 +55,13 @@
Filter by year
-

Search results

-
-
+
+
Sorted by
+
most recent
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 711513f5..e84927d4 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -126,16 +126,6 @@ search.addWidgets([ }, }, }), - instantsearch.widgets.hitsPerPage({ - container: "#hits-per-page", - items: [ - { value: 10, label: "10 per page", default: true }, - { value: 20, label: "20 per page" }, - { value: 30, label: "30 per page" }, - { value: 40, label: "40 per page" }, - { value: 50, label: "50 per page" }, - ], - }), instantsearch.widgets.pagination({ container: "#pagination", showFirst: true, @@ -167,3 +157,15 @@ search.start(); // searchbox.addEventListener("keyup", () => { // console.log(searchbox.value); // }); + +const toggleSortedVisibility = () => { + const component = document.querySelector('#sorted-by'); + if (searchInput.value.trim() === '') { + component.style.display = 'block'; + } else { + component.style.display = 'none'; + } +} + +const searchInput = document.querySelector('.ais-SearchBox-input'); +searchInput.addEventListener('input', toggleSortedVisibility) \ No newline at end of file From cef30ed58285ce54209a54f764d8cb1056430f51 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 17 Apr 2024 16:32:11 +0800 Subject: [PATCH 10/45] feat: change search page layout --- _layouts/egazette-search.html | 35 +++++++++++------------------------ assets/css/algolia.css | 18 +++++++++++++++++- assets/js/algolia-search.js | 12 ++++++------ 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 575594d2..cffdf68d 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -2,30 +2,17 @@ layout: skeleton --- -
-
-
-
-

{%- include header-breadcrumb.html -%}

-
-
-
-
-
-
-

{{- page.title -}}

-
-
+
+
+
{{- page.title -}}
-
-
-
-
+
-
Filter by category
+
Refine your search
+
+
Filter by category
-
Filter by sub-category
+
Filter by sub-category
-
Filter by year
+
Filter by year
@@ -60,8 +48,7 @@
Filter by year
-
Sorted by
-
most recent
+
Sorted by most recent
diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 7afc6be0..5f91f4d4 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -4,7 +4,7 @@ .ais-SearchBox-input { outline: none; border: none; - font-size: 1.5rem; + font-size: 1rem; box-shadow: none; } } @@ -60,3 +60,19 @@ .ais-RefinementList-item--selected .ais-RefinementList-checkbox { background-image: url("https://raw.githubusercontent.com/atisawd/boxicons/master/svg/regular/bx-check.svg"); } + +.algolia-searchbar { + border-radius: 4px; + border: 1px solid var(--color-divider-medium, #D0D0D0); + background: var(--color-utility-ui-bg, #FFF); +} +.algolia-searchbar:hover { + border-radius: 4px; + border: 1px solid var(--color-divider-medium, #D0D0D0); + background: var(--color-utility-ui-bg, #FFF); +} +.algolia-search-divider { + margin-top: 0.5rem; + margin-bottom: 0.5rem; + height: 1px; +} \ No newline at end of file diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index e84927d4..b1bbc16e 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -36,7 +36,7 @@ search.addWidgets([ } else if (data.hasOneResult) { content += `1 result found`; } else { - content += `no result found`; + content += `No results found`; } return html`

${content}

`; @@ -46,7 +46,7 @@ search.addWidgets([ instantsearch.widgets.poweredBy({ container: "#poweredby", - theme: "dark", + theme: "light", }), instantsearch.widgets.refinementList({ container: "#refinement-list-category", @@ -84,7 +84,7 @@ search.addWidgets([ highlightedTagName: "mark", hit, })} -

Category: ${instantsearch.highlight( +

Category: ${instantsearch.highlight( { attribute: "category", highlightedTagName: "mark", @@ -99,19 +99,19 @@ search.addWidgets([ })}` : "" }

-

Notification number: ${instantsearch.highlight( +

Notification number: ${instantsearch.highlight( { attribute: "notificationNum", highlightedTagName: "mark", hit, } )}

-

Publish date: ${new Date( +

Publish date: ${new Date( hit.publishTimestamp ).toLocaleDateString("fr-CA")}

${ hit.text - ? `

Content: ${instantsearch.snippet( + ? `

Content: ${instantsearch.snippet( { attribute: "text", highlightedTagName: "mark", From 272577d0cb4aa4f7aaa78adf6e9ffa8f6be22fe1 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 17 Apr 2024 17:46:49 +0800 Subject: [PATCH 11/45] fix: minor copy changes --- _layouts/egazette-search.html | 2 +- assets/js/algolia-search.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index cffdf68d..4bf3ee79 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -24,7 +24,7 @@

{{- page.title -}}
-
+
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index b1bbc16e..9cf4812f 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -161,9 +161,9 @@ search.start(); const toggleSortedVisibility = () => { const component = document.querySelector('#sorted-by'); if (searchInput.value.trim() === '') { - component.style.display = 'block'; + component.textContent = 'Sorted by most recent'; } else { - component.style.display = 'none'; + component.textContent = 'Sorted by relevancy'; } } From 59627d94f0591bc7d2c06b15c12c6b7a8d3b4d09 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 22 Apr 2024 18:02:43 +0800 Subject: [PATCH 12/45] feat: add algolia search routing --- assets/js/algolia-search.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 9cf4812f..3a6ea49f 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -9,9 +9,20 @@ const algoliaIndexName = isProd ? "ogp_egazettes_index" : "staging_ogp_egazettes_index"; + +const queryParams = new URLSearchParams(window.location.search); +const parsedParams = {}; +for (const [key, value] of queryParams.entries()) { + if (key === "query") continue + const valuesSelected = value.split(",") + parsedParams[key] = valuesSelected; +} +const queryTerm = queryParams.get("query") + const search = instantsearch({ indexName: algoliaIndexName, searchClient, + routing: true }); // Note: Publish date is formatted as YYYY-MM-DD @@ -70,6 +81,11 @@ search.addWidgets([ instantsearch.widgets.clearRefinements({ container: "#clear-refinements", }), + // This needs to be after the refinement list has been declared + instantsearch.widgets.configure({ + query: queryTerm || "" , + disjunctiveFacetsRefinements: parsedParams, + }), instantsearch.widgets.hits({ container: "#hits", From 46f47dbb781b66eafce2e7b40e35132cbd42ba68 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 22 Apr 2024 18:02:57 +0800 Subject: [PATCH 13/45] feat: add search landing layout --- _includes/main_scripts.html | 6 ++ _layouts/egazette-search-landing.html | 36 ++++++++++++ assets/css/algolia.css | 24 ++++++++ assets/js/algolia-search-landing.js | 81 +++++++++++++++++++++++++++ misc/egazette-search-landing.md | 6 ++ 5 files changed, 153 insertions(+) create mode 100644 _layouts/egazette-search-landing.html create mode 100644 assets/js/algolia-search-landing.js create mode 100644 misc/egazette-search-landing.md diff --git a/_includes/main_scripts.html b/_includes/main_scripts.html index 9d6cf3f6..cc6cecd3 100644 --- a/_includes/main_scripts.html +++ b/_includes/main_scripts.html @@ -84,6 +84,12 @@ {%- endif -%} +{%- if page.layout == 'egazette-search-landing' -%} + + + +{%- endif -%} + {%- include chatbot-scripts.html -%} diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html new file mode 100644 index 00000000..85d8d5fb --- /dev/null +++ b/_layouts/egazette-search-landing.html @@ -0,0 +1,36 @@ +--- +layout: skeleton +--- + +
+
+
+
+

{{- page.title -}}

+
+
+
+
+ +
+
+
+
+ + +

You can search by keyword, title, or notification number

+
+
+
+
Category
+
+
+
Year
+
+ +
+
+ +
+
+ \ No newline at end of file diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 5f91f4d4..e7a6b723 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -75,4 +75,28 @@ margin-top: 0.5rem; margin-bottom: 0.5rem; height: 1px; +} +.algolia-search-query-container { + display: flex; + flex-direction: column; +} +.algolia-search-category-container { + display: flex; + flex-direction: column; + gap: 1rem; +} +#algolia-search-box-landing { + border: 1px solid; + border-radius: 4px; + border-color: var(--color-divider-medium, #D0D0D0); +} +.algolia-search-category-items-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 0.75rem 1.25rem; +} +.algolia-search-category-item { + display: flex; + gap: 0.5rem; + align-items: center; } \ No newline at end of file diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js new file mode 100644 index 00000000..d669d570 --- /dev/null +++ b/assets/js/algolia-search-landing.js @@ -0,0 +1,81 @@ +const searchClient = algoliasearch( + "1V7DZGZJKK", + "0ba2c5f100ff5fd004415e4abbcf9b9c" +); + +const PROD_URL = "https://www.egazette.gov.sg"; +const isProd = window.location.origin === PROD_URL; +const algoliaIndexName = isProd + ? "ogp_egazettes_index" + : "staging_ogp_egazettes_index"; + +const searchIndex = searchClient.initIndex(algoliaIndexName); + +const searchCategories = ["category", "publishYear"] // TODO: add agency + +async function fetchCategoryEntries(categoryName) { + try { + const { facetHits } = await searchIndex.searchForFacetValues(categoryName, "", { maxFacetHits: 100, sortFacetValuesBy: "alpha" } ); + const categories = facetHits.map(hit => hit.value); + return categories; + } catch (error) { + console.error('Error fetching categories and entries:', error); + return {}; + } +} + +// Function to populate options for each category +async function populateOptions() { + await Promise.all(searchCategories.map(async (category) => { + const categoryContent = await fetchCategoryEntries(category) + const categoryFieldset = document.getElementById(category); + categoryContent.forEach(categoryItem => { + const itemWrapper = document.createElement('div'); + itemWrapper.classList.add("algolia-search-category-item") + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.name = categoryItem; + checkbox.value = categoryItem; + checkbox.id = `${categoryItem}_${categoryItem}`; + const label = document.createElement('label'); + label.htmlFor = checkbox.id; + label.textContent = categoryItem; + categoryFieldset.appendChild(itemWrapper) + itemWrapper.appendChild(checkbox); + itemWrapper.appendChild(label); + // itemWrapper.appendChild(document.createElement('br')); + }) + })); +} + +populateOptions(); + +document.getElementById("submitButton").addEventListener("click", function() { + let selectedCategories = {}; + const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked'); + checkboxes.forEach(checkbox => { + const category = checkbox.parentNode.parentNode.id; + const entry = checkbox.value; + if (!selectedCategories[category]) { + selectedCategories[category] = []; + } + selectedCategories[category].push(entry); + }); + + // Construct URL with query params + const categoryFormElement = document.querySelector("#categoryForm"); + const searchPageUrl = categoryFormElement.dataset.url + let url = searchPageUrl.endsWith("/") ? `${searchPageUrl}?` : `${searchPageUrl}/?` + + // Search term + const queryInput = document.getElementById("algolia-search-box-landing") + url += `query=${queryInput.value ? queryInput.value : ""}` + + // Category filters + for (const [category, values] of Object.entries(selectedCategories)) { + url += `&${category}=${values.map(entry => encodeURIComponent(entry)).join(",")}` + } + + // Redirect to results page + window.location.href = url; +}); \ No newline at end of file diff --git a/misc/egazette-search-landing.md b/misc/egazette-search-landing.md new file mode 100644 index 00000000..f5704a9b --- /dev/null +++ b/misc/egazette-search-landing.md @@ -0,0 +1,6 @@ +--- +layout: egazette-search-landing +title: Search e-Gazettes +permalink: /egazette-search-landing/ +searchUrl: /egazette-search/ +--- From c261c59f08ce7407e007154dc9062a47c25214b9 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 22 Apr 2024 21:33:07 +0800 Subject: [PATCH 14/45] fix: make categories queries sequential --- assets/js/algolia-search-landing.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index d669d570..cc16158d 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -26,7 +26,7 @@ async function fetchCategoryEntries(categoryName) { // Function to populate options for each category async function populateOptions() { - await Promise.all(searchCategories.map(async (category) => { + for (const category of searchCategories) { const categoryContent = await fetchCategoryEntries(category) const categoryFieldset = document.getElementById(category); categoryContent.forEach(categoryItem => { @@ -45,7 +45,7 @@ async function populateOptions() { itemWrapper.appendChild(label); // itemWrapper.appendChild(document.createElement('br')); }) - })); + } } populateOptions(); From 6c11a56661946e23edd7a147479eb9fd7415f6b8 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 29 Apr 2024 11:04:16 +0800 Subject: [PATCH 15/45] fix: url to state mapping --- assets/js/algolia-search-landing.js | 6 ++-- assets/js/algolia-search.js | 45 +++++++++++++++++++---------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index cc16158d..05c4004b 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -69,11 +69,13 @@ document.getElementById("submitButton").addEventListener("click", function() { // Search term const queryInput = document.getElementById("algolia-search-box-landing") - url += `query=${queryInput.value ? queryInput.value : ""}` + url += `q=${queryInput.value ? queryInput.value : ""}` // Category filters for (const [category, values] of Object.entries(selectedCategories)) { - url += `&${category}=${values.map(entry => encodeURIComponent(entry)).join(",")}` + values.map((entry, index) => { + url += `&${category}%5B${index}%5D=${encodeURIComponent(entry)}` + }) } // Redirect to results page diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 3a6ea49f..afcdbf7f 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -10,19 +10,36 @@ const algoliaIndexName = isProd : "staging_ogp_egazettes_index"; -const queryParams = new URLSearchParams(window.location.search); -const parsedParams = {}; -for (const [key, value] of queryParams.entries()) { - if (key === "query") continue - const valuesSelected = value.split(",") - parsedParams[key] = valuesSelected; -} -const queryTerm = queryParams.get("query") - const search = instantsearch({ indexName: algoliaIndexName, searchClient, - routing: true + routing: { + stateMapping: { + stateToRoute(uiState) { + const indexUiState = uiState[algoliaIndexName]; + return { + q: indexUiState.query, + category: indexUiState.refinementList && indexUiState.refinementList.category, + subCategory: + indexUiState.refinementList && indexUiState.refinementList.subCategory, + publishYear: indexUiState.refinementList && indexUiState.refinementList.publishYear, + } + }, + routeToState(routeState) { + return { + [algoliaIndexName]: { + query: routeState.q, + refinementList: { + category: routeState.category, + subCategory: + routeState.subCategory, + publishYear: routeState.publishYear, + }, + }, + }; + }, + }, + } }); // Note: Publish date is formatted as YYYY-MM-DD @@ -81,11 +98,6 @@ search.addWidgets([ instantsearch.widgets.clearRefinements({ container: "#clear-refinements", }), - // This needs to be after the refinement list has been declared - instantsearch.widgets.configure({ - query: queryTerm || "" , - disjunctiveFacetsRefinements: parsedParams, - }), instantsearch.widgets.hits({ container: "#hits", @@ -184,4 +196,5 @@ const toggleSortedVisibility = () => { } const searchInput = document.querySelector('.ais-SearchBox-input'); -searchInput.addEventListener('input', toggleSortedVisibility) \ No newline at end of file +searchInput.addEventListener('input', toggleSortedVisibility) +toggleSortedVisibility() \ No newline at end of file From 810b0850ff1ef1bcf3d59468be28d8f9cba62cd4 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 29 Apr 2024 11:04:31 +0800 Subject: [PATCH 16/45] fix: copy update for no results found --- assets/js/algolia-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index afcdbf7f..cfeb4379 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -64,7 +64,7 @@ search.addWidgets([ } else if (data.hasOneResult) { content += `1 result found`; } else { - content += `No results found`; + content += `No results found for ${data.query}`; } return html`

${content}

`; From c2f7cf09d2173554063a1531e62660e864beeaa6 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 29 Apr 2024 11:18:37 +0800 Subject: [PATCH 17/45] fix: enter key handler --- assets/js/algolia-search-landing.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index 05c4004b..c4d42ede 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -43,14 +43,13 @@ async function populateOptions() { categoryFieldset.appendChild(itemWrapper) itemWrapper.appendChild(checkbox); itemWrapper.appendChild(label); - // itemWrapper.appendChild(document.createElement('br')); }) } } populateOptions(); -document.getElementById("submitButton").addEventListener("click", function() { +function processSearch() { let selectedCategories = {}; const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked'); checkboxes.forEach(checkbox => { @@ -80,4 +79,12 @@ document.getElementById("submitButton").addEventListener("click", function() { // Redirect to results page window.location.href = url; +} + +document.getElementById("submitButton").addEventListener("click", processSearch); +document.getElementById("algolia-search-box-landing").addEventListener("keydown", function(event) { + if (event.key === "Enter") { + event.preventDefault(); // Prevent the default form submission behavior + processSearch(); + } }); \ No newline at end of file From 55737823890e39beafe538fe5eddacb5df770fa7 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 9 May 2024 09:28:46 +0800 Subject: [PATCH 18/45] feat: revamp landing page --- _layouts/egazette-search-landing.html | 66 +++++++++++++------- _sass/theme/_text-styles.scss | 8 +++ assets/css/algolia.css | 40 ++++++++++-- assets/js/algolia-search-landing.js | 90 +++++++++++++++++++++------ 4 files changed, 159 insertions(+), 45 deletions(-) diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html index 85d8d5fb..2dd57b1f 100644 --- a/_layouts/egazette-search-landing.html +++ b/_layouts/egazette-search-landing.html @@ -1,36 +1,60 @@ --- layout: skeleton --- - -
-
-
-
-

{{- page.title -}}

-
+
+
+

{{- page.title -}}

+
+

Find a Gazette by keyword

+ + Browse all Gazettes + +
-
- -
-
+
- - -

You can search by keyword, title, or notification number

+ +
+
Year
+
+ +

~

+ +
-
Category
-
+
Category
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
-
Year
-
-
-
- \ No newline at end of file + \ No newline at end of file diff --git a/_sass/theme/_text-styles.scss b/_sass/theme/_text-styles.scss index 82fc5f4d..d434597a 100644 --- a/_sass/theme/_text-styles.scss +++ b/_sass/theme/_text-styles.scss @@ -61,6 +61,14 @@ line-height: 2rem; /* 123.077% */ } +.subhead-1 { + font-size: 1.25rem; + font-style: normal; + font-weight: 500; + line-height: 1.5rem; /* 150% */ + letter-spacing: -0.006rem; +} + .subtitle-1 { color: $content-base; diff --git a/assets/css/algolia.css b/assets/css/algolia.css index e7a6b723..80843728 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -84,19 +84,51 @@ display: flex; flex-direction: column; gap: 1rem; + + .date-input { + width: 10rem; + } +} +.algolia-landing-date-container { + gap: 0.75rem; } -#algolia-search-box-landing { +#algolia-search-box-landing, #input-start-date, #input-end-date { border: 1px solid; border-radius: 4px; border-color: var(--color-divider-medium, #D0D0D0); } .algolia-search-category-items-container { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 0.75rem 1.25rem; + display: flex; + justify-content: space-between; } .algolia-search-category-item { display: flex; gap: 0.5rem; align-items: center; +} +.algolia-search-landing-footer { + display: flex; + justify-content: flex-end; + gap: 0.75rem; + padding: 1.5rem 3rem; + position: sticky; + bottom: 0; + border-top: 1px solid #CECECE; + background: #FFFFFF; +} +.algolia-search-landing-container { + background: #FCFCFC; +} +.algolia-search-landing-subtitle-container { + justify-content: space-between; + display:flex; + + .link-button-text { + text-transform: none; + } + + .algolia-search-landing-subtitle { + color: #666C7A; + font-size: 1.125rem; + } } \ No newline at end of file diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index c4d42ede..6c54b962 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -11,7 +11,10 @@ const algoliaIndexName = isProd const searchIndex = searchClient.initIndex(algoliaIndexName); -const searchCategories = ["category", "publishYear"] // TODO: add agency +const searchCategories = [] // TODO: add agency +const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Others", "Revocation", "Tenders", "Termination of Service", "Vacation of Service"] +const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Revised Acts", "Subsidiary Legislation Supplement", "Revised Subsidiary Legislation"] +const otherSupplementsSubcategories = ["Government Gazette Supplement", "Industrial Relations Supplement", "Trade Marks Supplement", "Treaties Supplement"] async function fetchCategoryEntries(categoryName) { try { @@ -24,27 +27,38 @@ async function fetchCategoryEntries(categoryName) { } } +function createCheckboxes(container, categories, searchCategoryName) { + categories.forEach(categoryItem => { + const itemWrapper = document.createElement('div'); + itemWrapper.classList.add("algolia-search-category-item") + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.name = categoryItem; + checkbox.value = categoryItem; + checkbox.id = `${categoryItem}_${categoryItem}`; + checkbox.dataset.category = searchCategoryName + const label = document.createElement('label'); + label.htmlFor = checkbox.id; + label.textContent = categoryItem; + container.appendChild(itemWrapper) + itemWrapper.appendChild(checkbox); + itemWrapper.appendChild(label); + }) +} + // Function to populate options for each category async function populateOptions() { for (const category of searchCategories) { const categoryContent = await fetchCategoryEntries(category) const categoryFieldset = document.getElementById(category); - categoryContent.forEach(categoryItem => { - const itemWrapper = document.createElement('div'); - itemWrapper.classList.add("algolia-search-category-item") - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.name = categoryItem; - checkbox.value = categoryItem; - checkbox.id = `${categoryItem}_${categoryItem}`; - const label = document.createElement('label'); - label.htmlFor = checkbox.id; - label.textContent = categoryItem; - categoryFieldset.appendChild(itemWrapper) - itemWrapper.appendChild(checkbox); - itemWrapper.appendChild(label); - }) + createCheckboxes(categoryFieldset, categoryContent, category) } + const governmentGazetteContainerElement = document.getElementById("government-gazette"); + const legislativeSupplementsContainerElement = document.getElementById("legislative-supplements"); + const otherSupplementsContainerElement = document.getElementById("other-supplements"); + createCheckboxes(governmentGazetteContainerElement, governmentGazetteSubcategories, "subCategory") + createCheckboxes(legislativeSupplementsContainerElement, legislativeSupplementsSubcategories, "subCategory") + createCheckboxes(otherSupplementsContainerElement, otherSupplementsSubcategories, "subCategory") } populateOptions(); @@ -53,14 +67,22 @@ function processSearch() { let selectedCategories = {}; const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked'); checkboxes.forEach(checkbox => { - const category = checkbox.parentNode.parentNode.id; + const category = checkbox.dataset.category; const entry = checkbox.value; if (!selectedCategories[category]) { selectedCategories[category] = []; } selectedCategories[category].push(entry); }); - + + const startDateInput = document.getElementById("input-start-date").value + const endDateInput = document.getElementById("input-end-date").value + if (startDateInput && endDateInput) { + selectedCategories.publishYear = [] + for (let i = parseInt(startDateInput); i <= parseInt(endDateInput); i++) { + selectedCategories.publishYear.push(i) + } + } // Construct URL with query params const categoryFormElement = document.querySelector("#categoryForm"); const searchPageUrl = categoryFormElement.dataset.url @@ -76,15 +98,43 @@ function processSearch() { url += `&${category}%5B${index}%5D=${encodeURIComponent(entry)}` }) } - + // Redirect to results page window.location.href = url; } +function clearFilters() { + const checkboxes = document.querySelectorAll('input[type="checkbox"]'); + checkboxes.forEach(function(checkbox) { + checkbox.checked = false; + }); + const textInput = document.querySelectorAll('input[type="text"]'); + textInput.forEach(function(textInput) { + textInput.value = ""; + }); +} + +function generateCheckChildren(parentCheckbox, category) { + return () => { + const categoryContainerElement = document.getElementById(category); + const childCheckboxes = categoryContainerElement.querySelectorAll('input[type="checkbox"]'); + childCheckboxes.forEach((checkbox) => { + checkbox.checked = parentCheckbox.checked + }) + } +} + +const governmentCheckbox = document.getElementById('category-government'); +const legislativeCheckbox = document.getElementById('category-legislative'); +const otherCheckbox = document.getElementById('category-other'); +document.getElementById("clearFiltersButton").addEventListener("click", clearFilters) document.getElementById("submitButton").addEventListener("click", processSearch); document.getElementById("algolia-search-box-landing").addEventListener("keydown", function(event) { if (event.key === "Enter") { event.preventDefault(); // Prevent the default form submission behavior processSearch(); } -}); \ No newline at end of file +}); +governmentCheckbox.addEventListener('click', generateCheckChildren(governmentCheckbox, "government-gazette")) +legislativeCheckbox.addEventListener('click', generateCheckChildren(legislativeCheckbox, "legislative-supplements")) +otherCheckbox.addEventListener('click', generateCheckChildren(otherCheckbox, "other-supplements")) \ No newline at end of file From e813aa3dbfcae9ea7efff20ae23fb3d1118067f2 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 9 May 2024 09:50:13 +0800 Subject: [PATCH 19/45] feat: change search page layout --- _layouts/egazette-search.html | 47 +++++++++++++++------------------ assets/js/algolia-search.js | 4 --- misc/egazette-search-landing.md | 2 +- misc/egazette-search.md | 2 +- 4 files changed, 23 insertions(+), 32 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 4bf3ee79..c75d0000 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -3,41 +3,36 @@ ---
-
-
{{- page.title -}}
+
+
+

{{- page.title -}}

+
-
-
- -
-
-
-
-
-
-
-
Refine your search
+
Search
+ +
Filter by

-
Filter by category
+
Category
+
-
Filter by sub-category
+
Sub-category
-
Filter by year
+
+ +
Year
+
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index cfeb4379..e98c519d 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -72,10 +72,6 @@ search.addWidgets([ }, }), - instantsearch.widgets.poweredBy({ - container: "#poweredby", - theme: "light", - }), instantsearch.widgets.refinementList({ container: "#refinement-list-category", attribute: "category", diff --git a/misc/egazette-search-landing.md b/misc/egazette-search-landing.md index f5704a9b..6fddc17c 100644 --- a/misc/egazette-search-landing.md +++ b/misc/egazette-search-landing.md @@ -1,6 +1,6 @@ --- layout: egazette-search-landing -title: Search e-Gazettes +title: E-Gazette Search permalink: /egazette-search-landing/ searchUrl: /egazette-search/ --- diff --git a/misc/egazette-search.md b/misc/egazette-search.md index b9423606..68c0e7bd 100755 --- a/misc/egazette-search.md +++ b/misc/egazette-search.md @@ -1,6 +1,6 @@ --- layout: egazette-search -title: Search e-Gazettes +title: Singapore e-Gazette permalink: /egazette-search/ breadcrumb: Search e-Gazettes --- From 142a1a3d618452a07d858c419397f5d9527a0fd8 Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Tue, 14 May 2024 11:23:02 +0800 Subject: [PATCH 20/45] test --- assets/js/algolia-search.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index e98c519d..fd182300 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -9,7 +9,6 @@ const algoliaIndexName = isProd ? "ogp_egazettes_index" : "staging_ogp_egazettes_index"; - const search = instantsearch({ indexName: algoliaIndexName, searchClient, @@ -19,11 +18,15 @@ const search = instantsearch({ const indexUiState = uiState[algoliaIndexName]; return { q: indexUiState.query, - category: indexUiState.refinementList && indexUiState.refinementList.category, + category: + indexUiState.refinementList && indexUiState.refinementList.category, subCategory: - indexUiState.refinementList && indexUiState.refinementList.subCategory, - publishYear: indexUiState.refinementList && indexUiState.refinementList.publishYear, - } + indexUiState.refinementList && + indexUiState.refinementList.subCategory, + publishYear: + indexUiState.refinementList && + indexUiState.refinementList.publishYear, + }; }, routeToState(routeState) { return { @@ -31,15 +34,14 @@ const search = instantsearch({ query: routeState.q, refinementList: { category: routeState.category, - subCategory: - routeState.subCategory, + subCategory: routeState.subCategory, publishYear: routeState.publishYear, }, }, }; }, }, - } + }, }); // Note: Publish date is formatted as YYYY-MM-DD @@ -75,6 +77,9 @@ search.addWidgets([ instantsearch.widgets.refinementList({ container: "#refinement-list-category", attribute: "category", + templates: { + count: `display: none;`, + }, limit: 20, }), instantsearch.widgets.refinementList({ @@ -183,14 +188,14 @@ search.start(); // }); const toggleSortedVisibility = () => { - const component = document.querySelector('#sorted-by'); - if (searchInput.value.trim() === '') { - component.textContent = 'Sorted by most recent'; + const component = document.querySelector("#sorted-by"); + if (searchInput.value.trim() === "") { + component.textContent = "Sorted by most recent"; } else { - component.textContent = 'Sorted by relevancy'; + component.textContent = "Sorted by relevancy"; } -} +}; -const searchInput = document.querySelector('.ais-SearchBox-input'); -searchInput.addEventListener('input', toggleSortedVisibility) -toggleSortedVisibility() \ No newline at end of file +const searchInput = document.querySelector(".ais-SearchBox-input"); +searchInput.addEventListener("input", toggleSortedVisibility); +toggleSortedVisibility(); From 9008550a70820c2d109541874baf19f5eee1c8eb Mon Sep 17 00:00:00 2001 From: Kishore <42832651+kishore03109@users.noreply.github.com> Date: Tue, 14 May 2024 11:40:22 +0800 Subject: [PATCH 21/45] test --- assets/css/algolia.css | 30 ++++++++++++++++++------------ assets/js/algolia-search.js | 3 --- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 80843728..118de780 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -63,13 +63,13 @@ .algolia-searchbar { border-radius: 4px; - border: 1px solid var(--color-divider-medium, #D0D0D0); - background: var(--color-utility-ui-bg, #FFF); + border: 1px solid var(--color-divider-medium, #d0d0d0); + background: var(--color-utility-ui-bg, #fff); } .algolia-searchbar:hover { border-radius: 4px; - border: 1px solid var(--color-divider-medium, #D0D0D0); - background: var(--color-utility-ui-bg, #FFF); + border: 1px solid var(--color-divider-medium, #d0d0d0); + background: var(--color-utility-ui-bg, #fff); } .algolia-search-divider { margin-top: 0.5rem; @@ -92,10 +92,12 @@ .algolia-landing-date-container { gap: 0.75rem; } -#algolia-search-box-landing, #input-start-date, #input-end-date { +#algolia-search-box-landing, +#input-start-date, +#input-end-date { border: 1px solid; border-radius: 4px; - border-color: var(--color-divider-medium, #D0D0D0); + border-color: var(--color-divider-medium, #d0d0d0); } .algolia-search-category-items-container { display: flex; @@ -113,22 +115,26 @@ padding: 1.5rem 3rem; position: sticky; bottom: 0; - border-top: 1px solid #CECECE; - background: #FFFFFF; + border-top: 1px solid #cecece; + background: #ffffff; } .algolia-search-landing-container { - background: #FCFCFC; + background: #fcfcfc; } .algolia-search-landing-subtitle-container { justify-content: space-between; - display:flex; + display: flex; .link-button-text { text-transform: none; } .algolia-search-landing-subtitle { - color: #666C7A; + color: #666c7a; font-size: 1.125rem; } -} \ No newline at end of file +} + +.ais-RefinementList-count { + display: none; +} diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index fd182300..739d2a10 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -77,9 +77,6 @@ search.addWidgets([ instantsearch.widgets.refinementList({ container: "#refinement-list-category", attribute: "category", - templates: { - count: `display: none;`, - }, limit: 20, }), instantsearch.widgets.refinementList({ From 6ff8a41fb086ae448b02a2c1ef1547cc665e487c Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 15 May 2024 21:57:37 +0800 Subject: [PATCH 22/45] feat: change filtering behaviour --- assets/js/algolia-search-landing.js | 12 +++++++++ assets/js/algolia-search.js | 41 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index 6c54b962..6edefb7a 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -15,6 +15,11 @@ const searchCategories = [] // TODO: add agency const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Others", "Revocation", "Tenders", "Termination of Service", "Vacation of Service"] const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Revised Acts", "Subsidiary Legislation Supplement", "Revised Subsidiary Legislation"] const otherSupplementsSubcategories = ["Government Gazette Supplement", "Industrial Relations Supplement", "Trade Marks Supplement", "Treaties Supplement"] +const subcategoryMapping = {} +governmentGazetteSubcategories.forEach(subcat => subcategoryMapping[subcat] = "Government Gazette") +legislativeSupplementsSubcategories.forEach(subcat => subcategoryMapping[subcat] = "Legislative Supplements") +otherSupplementsSubcategories.forEach(subcat => subcategoryMapping[subcat] = "Other Supplements") +const gazetteCategories = ["Government Gazette", "Legislative Supplements", "Other Supplements"] async function fetchCategoryEntries(categoryName) { try { @@ -74,6 +79,13 @@ function processSearch() { } selectedCategories[category].push(entry); }); + if (!selectedCategories.category) selectedCategories.category = [] + selectedCategories.subCategory.forEach(selectedSubcategory => { + const parentCat = subcategoryMapping[selectedSubcategory] + if (!(parentCat in selectedCategories["category"])) { + selectedCategories["category"].push(parentCat) + } + }) const startDateInput = document.getElementById("input-start-date").value const endDateInput = document.getElementById("input-end-date").value diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 739d2a10..f0b5bc0d 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -9,6 +9,27 @@ const algoliaIndexName = isProd ? "ogp_egazettes_index" : "staging_ogp_egazettes_index"; +const categories = ["Government Gazette", "Legislative Supplements", "Other Supplements"] +const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Others", "Revocation", "Tenders", "Termination of Service", "Vacation of Service"] +const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Revised Acts", "Subsidiary Legislation Supplement", "Revised Subsidiary Legislation"] +const otherSupplementsSubcategories = ["Government Gazette Supplement", "Industrial Relations Supplement", "Trade Marks Supplement", "Treaties Supplement"] + +const categoryMapping = { + "Government Gazette": governmentGazetteSubcategories, + "Legislative Supplements": legislativeSupplementsSubcategories, + "Other Supplements": otherSupplementsSubcategories +} + +function getSubcategories(selectedCategories) { + let filteredValues = []; + + selectedCategories.forEach(value => { + filteredValues = filteredValues.concat(categoryMapping[value]) + }); + + return filteredValues; +} + const search = instantsearch({ indexName: algoliaIndexName, searchClient, @@ -78,10 +99,30 @@ search.addWidgets([ container: "#refinement-list-category", attribute: "category", limit: 20, + transformItems(items) { + const currentItemsMap = new Map(items.map(item => [item.label, item])); + + // Map all possible values to their corresponding item or a default item with count 0 + const orderedItems = categories.map(value => + currentItemsMap.get(value) || { highlighted:value, value, label: value, count: 0, isRefined: false } + ); + + return orderedItems; + } }), instantsearch.widgets.refinementList({ container: "#refinement-list-subcategory", attribute: "subCategory", + transformItems(items, { results }) { + const currentItemsMap = new Map(items.map(item => [item.label, item])); + + const selectedCategories = results._state.disjunctiveFacetsRefinements.category; + const availableSubcategories = getSubcategories(selectedCategories) + const orderedItems = availableSubcategories.map(value => + currentItemsMap.get(value) || { highlighted:value, value, label: value, count: 0, isRefined: false } + ); + return orderedItems; + } }), instantsearch.widgets.refinementList({ container: "#refinement-list-year", From dd960f0ed60e50f75954b36804c386ce731b14f7 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 16 May 2024 09:32:30 +0800 Subject: [PATCH 23/45] fix: landing page when no category is selected --- assets/js/algolia-search-landing.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index 6edefb7a..b83292ba 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -79,13 +79,15 @@ function processSearch() { } selectedCategories[category].push(entry); }); - if (!selectedCategories.category) selectedCategories.category = [] - selectedCategories.subCategory.forEach(selectedSubcategory => { - const parentCat = subcategoryMapping[selectedSubcategory] - if (!(parentCat in selectedCategories["category"])) { - selectedCategories["category"].push(parentCat) - } - }) + if (selectedCategories.subCategory) { + if (!selectedCategories.category) selectedCategories.category = [] + selectedCategories.subCategory.forEach(selectedSubcategory => { + const parentCat = subcategoryMapping[selectedSubcategory] + if (!(parentCat in selectedCategories["category"])) { + selectedCategories["category"].push(parentCat) + } + }) + } const startDateInput = document.getElementById("input-start-date").value const endDateInput = document.getElementById("input-end-date").value From 0cfd42d7daa83e87301b9cd556e3590151b5a5ec Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 16 May 2024 11:28:26 +0800 Subject: [PATCH 24/45] partial fix for disappearing categories --- assets/css/algolia.css | 4 ++++ assets/js/algolia-search.js | 23 +++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 118de780..af59ce74 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -138,3 +138,7 @@ .ais-RefinementList-count { display: none; } + +.algolia-search-item-disabled { + color: #cdcdc7; +} \ No newline at end of file diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index f0b5bc0d..26c71c62 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -101,6 +101,7 @@ search.addWidgets([ limit: 20, transformItems(items) { const currentItemsMap = new Map(items.map(item => [item.label, item])); + console.log(currentItemsMap) // Map all possible values to their corresponding item or a default item with count 0 const orderedItems = categories.map(value => @@ -113,13 +114,23 @@ search.addWidgets([ instantsearch.widgets.refinementList({ container: "#refinement-list-subcategory", attribute: "subCategory", + limit: 100, transformItems(items, { results }) { const currentItemsMap = new Map(items.map(item => [item.label, item])); + console.log(currentItemsMap) const selectedCategories = results._state.disjunctiveFacetsRefinements.category; const availableSubcategories = getSubcategories(selectedCategories) - const orderedItems = availableSubcategories.map(value => - currentItemsMap.get(value) || { highlighted:value, value, label: value, count: 0, isRefined: false } + const orderedItems = availableSubcategories.map(value => { + const res = currentItemsMap.get(value) + if (!res) { + return { highlighted: `${value} (No results)`, value, label: value, count: 0, isRefined: false } + } + if (res.count === 0) { + return { ...res, highlighted: `${value} (No results)`} + } + return res + } ); return orderedItems; } @@ -220,6 +231,14 @@ search.addWidgets([ search.start(); +search.on('render', () => { + document.querySelectorAll('#refinement-list-subcategory .ais-RefinementList-item').forEach(item => { + const count = parseInt(item.querySelector('.ais-RefinementList-count').textContent, 10); + if (count === 0) { + item.classList.add('algolia-search-item-disabled'); + } + }); +}); // const searchbox = document.getElementById("searchbox"); // searchbox.addEventListener("keyup", () => { // console.log(searchbox.value); From 1ff09c45ab1c098b9cadd531855eb1c2ae2d3324 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 16 May 2024 13:00:59 +0800 Subject: [PATCH 25/45] fix: partial fix for search --- assets/js/algolia-search.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 26c71c62..f0c5c5c6 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -100,13 +100,22 @@ search.addWidgets([ attribute: "category", limit: 20, transformItems(items) { + const currentCategoryRefinements = search.renderState[algoliaIndexName].currentRefinements.items.filter(item => item.attribute === "category") + let selectedCategories = [] + if (currentCategoryRefinements.length > 0) { + selectedCategories = currentCategoryRefinements[0].refinements.map(item => item.label) + } const currentItemsMap = new Map(items.map(item => [item.label, item])); - console.log(currentItemsMap) // Map all possible values to their corresponding item or a default item with count 0 - const orderedItems = categories.map(value => - currentItemsMap.get(value) || { highlighted:value, value, label: value, count: 0, isRefined: false } - ); + const orderedItems = categories.map(value => { + if (currentItemsMap.has(value)) { + return currentItemsMap.get(value) + } else if (selectedCategories.includes(value)) { + return { highlighted:value, value, label: value, count: 0, isRefined: true } + } + return { highlighted:value, value, label: value, count: 0, isRefined: false } + }); return orderedItems; } @@ -117,7 +126,6 @@ search.addWidgets([ limit: 100, transformItems(items, { results }) { const currentItemsMap = new Map(items.map(item => [item.label, item])); - console.log(currentItemsMap) const selectedCategories = results._state.disjunctiveFacetsRefinements.category; const availableSubcategories = getSubcategories(selectedCategories) From dc7eb650b40175b12b1cec2928a445b1bee08504 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 16 May 2024 17:20:26 +0800 Subject: [PATCH 26/45] fix: subcategories filter --- assets/js/algolia-search.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index f0c5c5c6..3d2d918c 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -125,21 +125,24 @@ search.addWidgets([ attribute: "subCategory", limit: 100, transformItems(items, { results }) { + const currentSubcategoryRefinements = search.renderState[algoliaIndexName].currentRefinements.items.filter(item => item.attribute === "subCategory") + let selectedSubcategories = [] + if (currentSubcategoryRefinements.length > 0) { + selectedSubcategories = currentSubcategoryRefinements[0].refinements.map(item => item.label) + } const currentItemsMap = new Map(items.map(item => [item.label, item])); const selectedCategories = results._state.disjunctiveFacetsRefinements.category; const availableSubcategories = getSubcategories(selectedCategories) const orderedItems = availableSubcategories.map(value => { const res = currentItemsMap.get(value) - if (!res) { - return { highlighted: `${value} (No results)`, value, label: value, count: 0, isRefined: false } - } - if (res.count === 0) { - return { ...res, highlighted: `${value} (No results)`} + if (currentItemsMap.has(value)) { + return { ...res, highlighted: `${res.count === 0 ? `${value} (No results)` : value}`} + } else if (selectedSubcategories.includes(value)) { + return { highlighted: `${value} (No results)`, value, label: value, count: 0, isRefined: true } } - return res - } - ); + return { highlighted: `${value} (No results)`, value, label: value, count: 0, isRefined: false } + }); return orderedItems; } }), From 374ec1a0f3843986e171e78f9878fb75fdeb877d Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 16 May 2024 18:00:41 +0800 Subject: [PATCH 27/45] feat: make sub-cat disappear if no category selected --- _layouts/egazette-search.html | 26 +++++++++++++++----------- assets/js/algolia-search.js | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index c75d0000..622ab6c7 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -22,17 +22,21 @@
Search
Filter by

-
Category
-
-
- -
Sub-category
-
-
- -
Year
-
-
+
+
Category
+
+
+
+
+
Sub-category
+
+
+
+
+
Year
+
+
+
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 3d2d918c..2b67976f 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -30,6 +30,20 @@ function getSubcategories(selectedCategories) { return filteredValues; } +const createToggleVisibilityWidget = (containerSelector, attribute) => ({ + init({ helper }) { + this.container = document.querySelector(containerSelector); + this.attribute = attribute; + this.helper = helper; + this.render(); + }, + render(_renderOptions) { + const hasResults = search.renderState[algoliaIndexName].currentRefinements.items.filter(item => item.attribute === "category").length > 0 + + this.container.style.display = hasResults ? 'block' : 'none'; + }, +}); + const search = instantsearch({ indexName: algoliaIndexName, searchClient, @@ -221,6 +235,9 @@ search.addWidgets([ showLast: true, }), ]); +search.addWidget( + createToggleVisibilityWidget('#refinement-list-subcategory-container', 'subcategory') +); // TODO: Loading spinner // search.on("render", () => { From 0b4ed91d97fa98269eee628fc4df2a022c8640a4 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Tue, 30 Jul 2024 14:45:47 +0800 Subject: [PATCH 28/45] fix: user test copy changes --- _layouts/egazette-search-landing.html | 3 ++- assets/js/algolia-search-landing.js | 6 +++--- assets/js/algolia-search.js | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html index 2dd57b1f..33fa674f 100644 --- a/_layouts/egazette-search-landing.html +++ b/_layouts/egazette-search-landing.html @@ -26,7 +26,8 @@

{{- page.title -}}

-
Category
+
Category
+
This is the best representation of subcategories available to classify the gazettes
diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index b83292ba..98348a2f 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -6,14 +6,14 @@ const searchClient = algoliasearch( const PROD_URL = "https://www.egazette.gov.sg"; const isProd = window.location.origin === PROD_URL; const algoliaIndexName = isProd - ? "ogp_egazettes_index" + ? "prod_ogp_egazettes_index" : "staging_ogp_egazettes_index"; const searchIndex = searchClient.initIndex(algoliaIndexName); const searchCategories = [] // TODO: add agency -const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Others", "Revocation", "Tenders", "Termination of Service", "Vacation of Service"] -const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Revised Acts", "Subsidiary Legislation Supplement", "Revised Subsidiary Legislation"] +const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Revocation", "Tenders", "Termination of Service", "Vacation of Service", "Others"] +const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Subsidiary Legislation Supplement", "Revised Acts", "Revised Subsidiary Legislation"] const otherSupplementsSubcategories = ["Government Gazette Supplement", "Industrial Relations Supplement", "Trade Marks Supplement", "Treaties Supplement"] const subcategoryMapping = {} governmentGazetteSubcategories.forEach(subcat => subcategoryMapping[subcat] = "Government Gazette") diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 2b67976f..2ebd5866 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -6,12 +6,12 @@ const searchClient = algoliasearch( const PROD_URL = "https://www.egazette.gov.sg"; const isProd = window.location.origin === PROD_URL; const algoliaIndexName = isProd - ? "ogp_egazettes_index" + ? "prod_ogp_egazettes_index" : "staging_ogp_egazettes_index"; const categories = ["Government Gazette", "Legislative Supplements", "Other Supplements"] -const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Others", "Revocation", "Tenders", "Termination of Service", "Vacation of Service"] -const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Revised Acts", "Subsidiary Legislation Supplement", "Revised Subsidiary Legislation"] +const governmentGazetteSubcategories = ["Advertisements", "Appointments", "Audited Reports", "Cessation of Service", "Corrigendum", "Death", "Dismissals", "Leave", "Bankruptcy Act Notice", "Companies Act Notice", "Notices under the Constitution", "Notices under other Acts", "Revocation", "Tenders", "Termination of Service", "Vacation of Service", "Others"] +const legislativeSupplementsSubcategories = ["Bills Supplement", "Acts Supplement", "Subsidiary Legislation Supplement", "Revised Acts", "Revised Subsidiary Legislation"] const otherSupplementsSubcategories = ["Government Gazette Supplement", "Industrial Relations Supplement", "Trade Marks Supplement", "Treaties Supplement"] const categoryMapping = { @@ -182,7 +182,7 @@ search.addWidgets([
${instantsearch.highlight({ + } target="_blank" type="application/pdf">${instantsearch.highlight({ attribute: "title", highlightedTagName: "mark", hit, From 49361db6329188a5e729a2f80f8c47343cdf5280 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Tue, 30 Jul 2024 18:29:40 +0800 Subject: [PATCH 29/45] feat: modify year to be range of values --- assets/js/algolia-search.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 2ebd5866..f032ef79 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -160,9 +160,14 @@ search.addWidgets([ return orderedItems; } }), - instantsearch.widgets.refinementList({ - container: "#refinement-list-year", - attribute: "publishYear", + instantsearch.widgets.rangeInput({ + container: '#refinement-list-year', + attribute: 'publishYear', + min: 1998, + templates: { + separatorText: 'to', + submitText: 'Go', + }, }), instantsearch.widgets.currentRefinements({ container: "#current-refinements", @@ -239,6 +244,7 @@ search.addWidget( createToggleVisibilityWidget('#refinement-list-subcategory-container', 'subcategory') ); + // TODO: Loading spinner // search.on("render", () => { // const container = document.getElementById("#loading-spinner"); From 6f83d48847c0e21e8a331b4ec495ec53622a53ea Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 31 Jul 2024 14:37:26 +0800 Subject: [PATCH 30/45] fix: search page and query params --- assets/js/algolia-search-landing.js | 11 +++++------ assets/js/algolia-search.js | 15 +++++++++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index 98348a2f..ab49f44d 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -91,12 +91,7 @@ function processSearch() { const startDateInput = document.getElementById("input-start-date").value const endDateInput = document.getElementById("input-end-date").value - if (startDateInput && endDateInput) { - selectedCategories.publishYear = [] - for (let i = parseInt(startDateInput); i <= parseInt(endDateInput); i++) { - selectedCategories.publishYear.push(i) - } - } + // Construct URL with query params const categoryFormElement = document.querySelector("#categoryForm"); const searchPageUrl = categoryFormElement.dataset.url @@ -113,6 +108,10 @@ function processSearch() { }) } + // Date range filters + if (startDateInput) url += `&minYear=${startDateInput}` + if (endDateInput) url += `&maxYear=${endDateInput}` + // Redirect to results page window.location.href = url; } diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index f032ef79..9533813c 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -51,6 +51,10 @@ const search = instantsearch({ stateMapping: { stateToRoute(uiState) { const indexUiState = uiState[algoliaIndexName]; + const yearData = indexUiState.range?.publishYear ? indexUiState.range.publishYear.split(":") : undefined + const minYear = (yearData && yearData[0]) ? yearData[0] : undefined + const maxYear = (yearData && yearData[1]) ? yearData[1] : undefined + console.log(minYear,maxYear) return { q: indexUiState.query, category: @@ -58,19 +62,22 @@ const search = instantsearch({ subCategory: indexUiState.refinementList && indexUiState.refinementList.subCategory, - publishYear: - indexUiState.refinementList && - indexUiState.refinementList.publishYear, + minYear, + maxYear, }; }, routeToState(routeState) { + const hasPublishYear = routeState.minYear || routeState.maxYear + const publishYear = hasPublishYear ? `${routeState.minYear || ""}: ${routeState.maxYear || ""}` : "" return { [algoliaIndexName]: { query: routeState.q, refinementList: { category: routeState.category, subCategory: routeState.subCategory, - publishYear: routeState.publishYear, + }, + range: { + publishYear }, }, }; From 3721dc58793cde763369a7ed18a123012feb8b03 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 5 Aug 2024 17:00:20 +0800 Subject: [PATCH 31/45] fix: csp issue --- assets/js/algolia-search.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 9533813c..51156a73 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -171,10 +171,6 @@ search.addWidgets([ container: '#refinement-list-year', attribute: 'publishYear', min: 1998, - templates: { - separatorText: 'to', - submitText: 'Go', - }, }), instantsearch.widgets.currentRefinements({ container: "#current-refinements", From 0541abb11a6c117e0f0bea8e346c5fa67fa952ca Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 5 Aug 2024 17:37:34 +0800 Subject: [PATCH 32/45] chore: fix landing page css for mobile --- assets/css/algolia.css | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/assets/css/algolia.css b/assets/css/algolia.css index af59ce74..5bc18bd9 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -100,8 +100,14 @@ border-color: var(--color-divider-medium, #d0d0d0); } .algolia-search-category-items-container { - display: flex; justify-content: space-between; + display: flex; +} +@media screen and (max-width: 769px) { + .algolia-search-category-items-container { + flex-direction: column; + gap: 1rem; + } } .algolia-search-category-item { display: flex; @@ -135,6 +141,14 @@ } } +@media screen and (max-width: 769px) { + .algolia-search-landing-subtitle-container { + flex-direction: column; + gap: 1rem; + align-items: start; + } +} + .ais-RefinementList-count { display: none; } From 6a370a78507d68faaf995bb81d1fe91d408b8294 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Mon, 5 Aug 2024 17:48:04 +0800 Subject: [PATCH 33/45] fix: date dash --- _layouts/egazette-search-landing.html | 2 +- assets/css/algolia.css | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html index 33fa674f..efdb04fe 100644 --- a/_layouts/egazette-search-landing.html +++ b/_layouts/egazette-search-landing.html @@ -22,7 +22,7 @@

{{- page.title -}}

Year
-

~

+

~

diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 5bc18bd9..c4922390 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -92,6 +92,17 @@ .algolia-landing-date-container { gap: 0.75rem; } +@media screen and (max-width: 769px) { + .algolia-landing-date-container { + flex-direction: column; + gap: 0; + width: 10rem; + + .date-dash { + align-self: center; + } + } +} #algolia-search-box-landing, #input-start-date, #input-end-date { From 7feeb117ad7809d431866851af3656f3a32da662 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 7 Aug 2024 14:10:22 +0800 Subject: [PATCH 34/45] fix: more misc changes --- _layouts/egazette-search-landing.html | 2 +- assets/js/algolia-search.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html index efdb04fe..9f1e5119 100644 --- a/_layouts/egazette-search-landing.html +++ b/_layouts/egazette-search-landing.html @@ -27,7 +27,7 @@

{{- page.title -}}

Category
-
This is the best representation of subcategories available to classify the gazettes
+
Please refer to the FAQ on the sub-categories below
diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 51156a73..26bc3c1e 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -210,14 +210,14 @@ search.addWidgets([ })}` : "" }

-

Notification number: ${instantsearch.highlight( +

Number: ${instantsearch.highlight( { attribute: "notificationNum", highlightedTagName: "mark", hit, } )}

-

Publish date: ${new Date( +

Date of publication: ${new Date( hit.publishTimestamp ).toLocaleDateString("fr-CA")}

${ From d9303c8ae056a637a79abfcd6c6f99551e5bad6a Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 14 Aug 2024 13:46:27 +0800 Subject: [PATCH 35/45] fix: use datagov production urls --- assets/js/datagovsg-search.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/datagovsg-search.js b/assets/js/datagovsg-search.js index c208940e..b7d22c14 100644 --- a/assets/js/datagovsg-search.js +++ b/assets/js/datagovsg-search.js @@ -82,7 +82,7 @@ function databaseSearch(searchTerm, index, callback) { if (isDgsV2) { // Datagov-v2 search - query for dataset metadata first to retrieve column info request = $.ajax({ - url: `https://api-staging.data.gov.sg/v2/public/api/datasets/${resourceId}/metadata`, + url: `https://api-production.data.gov.sg/v2/public/api/datasets/${resourceId}/metadata`, dataType: 'json' }).then((resp) => { const respData = Object.values(resp.data.columnMetadata.metaMapping) @@ -96,7 +96,7 @@ function databaseSearch(searchTerm, index, callback) { data.q = JSON.stringify({[formattedSearchField]: searchTerm}) } return $.ajax({ - url: 'https://35q3y4991j.execute-api.ap-southeast-1.amazonaws.com/api/action/datastore_search', + url: 'https://data.gov.sg/api/action/datastore_search', data: data, dataType: 'json', success: callback @@ -106,7 +106,7 @@ function databaseSearch(searchTerm, index, callback) { } else { data.q = searchTerm request = $.ajax({ - url: 'https://35q3y4991j.execute-api.ap-southeast-1.amazonaws.com/api/action/datastore_search', + url: 'https://data.gov.sg/api/action/datastore_search', data: data, dataType: 'json', success: callback From b3fa12e236ada21aaced47d37b9366aebffc2986 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Sun, 18 Aug 2024 13:06:20 +0800 Subject: [PATCH 36/45] chore: add internal mapping --- _layouts/egazette-search-landing.html | 2 +- assets/js/algolia-constants.js | 31 +++++++++++++++++ assets/js/algolia-search-landing.js | 34 +++++++++++++++++- assets/js/algolia-search.js | 50 ++++++++++++++++++++++++--- 4 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 assets/js/algolia-constants.js diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html index 9f1e5119..3a354b72 100644 --- a/_layouts/egazette-search-landing.html +++ b/_layouts/egazette-search-landing.html @@ -39,7 +39,7 @@

{{- page.title -}}

- +
diff --git a/assets/js/algolia-constants.js b/assets/js/algolia-constants.js new file mode 100644 index 00000000..5d81afcc --- /dev/null +++ b/assets/js/algolia-constants.js @@ -0,0 +1,31 @@ +export const CATEGORY_INTERNAL_MAPPING = { + "Government Gazette": "Government Gazette", + "Legislative Supplements": "Legislation Supplements", + "Other Supplements": "Other Supplements", + "Advertisements": "Advertisements", + "Appointments": "Appointments", + "Audited Reports": "Audited Reports", + "Cessation of Service": "Cessation of Service", + "Corrigendum": "Corrigendum", + "Death": "Death", + "Dismissals": "Dismissals", + "Leave": "Leave", + "Bankruptcy Act Notice": "Notices (Bankruptcy Act)", + "Companies Act Notice": "Notices (Companies Act)", + "Notices under the Constitution": "Notices (Constitution)", + "Notices under other Acts": "Notices (other Acts)", + "Revocation": "Revocation", + "Tenders": "Tenders", + "Termination of Service": "Termination of Service", + "Vacation of Service": "Vacation of Service", + "Others": "Others", + "Bills Supplement": "Bills Supplement", + "Acts Supplement": "Acts Supplement", + "Subsidiary Legislation Supplement": "Subsidiary Legislation Supplement", + "Revised Acts": "Revised Acts", + "Revised Subsidiary Legislation": "Revised Subsidiary Legislation", + "Government Gazette Supplement": "Government Gazette Supplement", + "Industrial Relations Supplement": "Industrial Relations Supplement", + "Trade Marks Supplement": "Trade Marks Supplement", + "Treaties Supplement": "Treaties Supplement" +} diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index ab49f44d..addd0d1a 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -1,3 +1,35 @@ +const CATEGORY_INTERNAL_MAPPING = { + "Government Gazette": "Government Gazette", + "Legislative Supplements": "Legislation Supplements", + "Other Supplements": "Other Supplements", + "Advertisements": "Advertisements", + "Appointments": "Appointments", + "Audited Reports": "Audited Reports", + "Cessation of Service": "Cessation of Service", + "Corrigendum": "Corrigendum", + "Death": "Death", + "Dismissals": "Dismissals", + "Leave": "Leave", + "Bankruptcy Act Notice": "Notices (Bankruptcy Act)", + "Companies Act Notice": "Notices (Companies Act)", + "Notices under the Constitution": "Notices (Constitution)", + "Notices under other Acts": "Notices (other Acts)", + "Revocation": "Revocation", + "Tenders": "Tenders", + "Termination of Service": "Termination of Service", + "Vacation of Service": "Vacation of Service", + "Others": "Others", + "Bills Supplement": "Bills Supplement", + "Acts Supplement": "Acts Supplement", + "Subsidiary Legislation Supplement": "Subsidiary Legislation Supplement", + "Revised Acts": "Revised Acts", + "Revised Subsidiary Legislation": "Revised Subsidiary Legislation", + "Government Gazette Supplement": "Government Gazette Supplement", + "Industrial Relations Supplement": "Industrial Relations Supplement", + "Trade Marks Supplement": "Trade Marks Supplement", + "Treaties Supplement": "Treaties Supplement" +} + const searchClient = algoliasearch( "1V7DZGZJKK", "0ba2c5f100ff5fd004415e4abbcf9b9c" @@ -44,7 +76,7 @@ function createCheckboxes(container, categories, searchCategoryName) { checkbox.dataset.category = searchCategoryName const label = document.createElement('label'); label.htmlFor = checkbox.id; - label.textContent = categoryItem; + label.textContent = CATEGORY_INTERNAL_MAPPING[categoryItem]; container.appendChild(itemWrapper) itemWrapper.appendChild(checkbox); itemWrapper.appendChild(label); diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 26bc3c1e..cde9aeb3 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -1,3 +1,35 @@ +const CATEGORY_INTERNAL_MAPPING = { + "Government Gazette": "Government Gazette", + "Legislative Supplements": "Legislation Supplements", + "Other Supplements": "Other Supplements", + "Advertisements": "Advertisements", + "Appointments": "Appointments", + "Audited Reports": "Audited Reports", + "Cessation of Service": "Cessation of Service", + "Corrigendum": "Corrigendum", + "Death": "Death", + "Dismissals": "Dismissals", + "Leave": "Leave", + "Bankruptcy Act Notice": "Notices (Bankruptcy Act)", + "Companies Act Notice": "Notices (Companies Act)", + "Notices under the Constitution": "Notices (Constitution)", + "Notices under other Acts": "Notices (other Acts)", + "Revocation": "Revocation", + "Tenders": "Tenders", + "Termination of Service": "Termination of Service", + "Vacation of Service": "Vacation of Service", + "Others": "Others", + "Bills Supplement": "Bills Supplement", + "Acts Supplement": "Acts Supplement", + "Subsidiary Legislation Supplement": "Subsidiary Legislation Supplement", + "Revised Acts": "Revised Acts", + "Revised Subsidiary Legislation": "Revised Subsidiary Legislation", + "Government Gazette Supplement": "Government Gazette Supplement", + "Industrial Relations Supplement": "Industrial Relations Supplement", + "Trade Marks Supplement": "Trade Marks Supplement", + "Treaties Supplement": "Treaties Supplement" +} + const searchClient = algoliasearch( "1V7DZGZJKK", "0ba2c5f100ff5fd004415e4abbcf9b9c" @@ -131,7 +163,8 @@ search.addWidgets([ // Map all possible values to their corresponding item or a default item with count 0 const orderedItems = categories.map(value => { if (currentItemsMap.has(value)) { - return currentItemsMap.get(value) + const adjustedMapping = { ...currentItemsMap.get(value), highlighted: CATEGORY_INTERNAL_MAPPING[value] } + return adjustedMapping } else if (selectedCategories.includes(value)) { return { highlighted:value, value, label: value, count: 0, isRefined: true } } @@ -158,11 +191,11 @@ search.addWidgets([ const orderedItems = availableSubcategories.map(value => { const res = currentItemsMap.get(value) if (currentItemsMap.has(value)) { - return { ...res, highlighted: `${res.count === 0 ? `${value} (No results)` : value}`} + return { ...res, highlighted: `${res.count === 0 ? `${CATEGORY_INTERNAL_MAPPING[value]} (No results)` : CATEGORY_INTERNAL_MAPPING[value]}`} } else if (selectedSubcategories.includes(value)) { - return { highlighted: `${value} (No results)`, value, label: value, count: 0, isRefined: true } + return { highlighted: `${CATEGORY_INTERNAL_MAPPING[value]} (No results)`, value, label: value, count: 0, isRefined: true } } - return { highlighted: `${value} (No results)`, value, label: value, count: 0, isRefined: false } + return { highlighted: `${CATEGORY_INTERNAL_MAPPING[value]} (No results)`, value, label: value, count: 0, isRefined: false } }); return orderedItems; } @@ -177,6 +210,15 @@ search.addWidgets([ cssClasses: { delete: "currentRefinementsIsomer", }, + transformItems(items) { + return items.map(item => ({ + ...item, + refinements: item.refinements.map(refinement => ({ + ...refinement, + label: CATEGORY_INTERNAL_MAPPING[refinement.label] || refinement.label, // Map the label using internalMapping + })) + })); + } }), instantsearch.widgets.clearRefinements({ container: "#clear-refinements", From 0ccf3fa2352e6bae716d00e0b84636e3497ecd28 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Tue, 20 Aug 2024 16:04:11 +0800 Subject: [PATCH 37/45] fix: ui fixes --- assets/css/algolia.css | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/assets/css/algolia.css b/assets/css/algolia.css index c4922390..265d408a 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -61,6 +61,38 @@ background-image: url("https://raw.githubusercontent.com/atisawd/boxicons/master/svg/regular/bx-check.svg"); } +.ais-RangeInput-input { + width: 100%; +} + +@media (max-width: 768px) { + .ais-RangeInput-input { + width: inherit; + } +} + +@media (min-width: 769px) and (max-width: 1280px) { + .ais-RangeInput-form { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .ais-RangeInput-label { + width: 100%; + } + + .ais-RangeInput-submit { + margin-top: 0.25rem; + margin-left: 0; + } +} + +.ais-SearchBox-input { + padding-right: 2.5rem; +} + .algolia-searchbar { border-radius: 4px; border: 1px solid var(--color-divider-medium, #d0d0d0); From 8bc0e8cf1adce1603ba88a4ba3650551c87bdfad Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 21 Aug 2024 16:52:32 +0800 Subject: [PATCH 38/45] fix: timezone --- assets/js/algolia-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index cde9aeb3..44cb2d24 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -261,7 +261,7 @@ search.addWidgets([ )}

Date of publication: ${new Date( hit.publishTimestamp - ).toLocaleDateString("fr-CA")}

+ ).toLocaleDateString("en-SG")}

${ hit.text ? `

Content: ${instantsearch.snippet( From c94ab112989f8a90c4b5185fbc85ded39186b6b6 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 21 Aug 2024 21:28:34 +0800 Subject: [PATCH 39/45] fix: remove min Algolia auto initialises to lowest value in index --- assets/js/algolia-search.js | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 44cb2d24..912a6cbc 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -203,7 +203,6 @@ search.addWidgets([ instantsearch.widgets.rangeInput({ container: '#refinement-list-year', attribute: 'publishYear', - min: 1998, }), instantsearch.widgets.currentRefinements({ container: "#current-refinements", From cc1b7ed2433443effd4b4882077ab0371d96dc8e Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 5 Sep 2024 12:25:16 +0800 Subject: [PATCH 40/45] chore: encode date input --- assets/js/algolia-search-landing.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index addd0d1a..566317a9 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -141,8 +141,8 @@ function processSearch() { } // Date range filters - if (startDateInput) url += `&minYear=${startDateInput}` - if (endDateInput) url += `&maxYear=${endDateInput}` + if (startDateInput) url += `&minYear=${encodeURIComponent(startDateInput)}` + if (endDateInput) url += `&maxYear=${encodeURIComponent(endDateInput)}` // Redirect to results page window.location.href = url; From 73fd0ae952ae4c637c8ec868ff04f08faaec3aa8 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 5 Sep 2024 12:46:20 +0800 Subject: [PATCH 41/45] fix: encodeURIComponent --- assets/js/algolia-search-landing.js | 2 +- assets/js/algolia-search.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index 566317a9..fb9567ae 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -131,7 +131,7 @@ function processSearch() { // Search term const queryInput = document.getElementById("algolia-search-box-landing") - url += `q=${queryInput.value ? queryInput.value : ""}` + url += `q=${queryInput.value ? encodeURIComponent(queryInput.value) : ""}` // Category filters for (const [category, values] of Object.entries(selectedCategories)) { diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 912a6cbc..b7bca032 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -86,9 +86,8 @@ const search = instantsearch({ const yearData = indexUiState.range?.publishYear ? indexUiState.range.publishYear.split(":") : undefined const minYear = (yearData && yearData[0]) ? yearData[0] : undefined const maxYear = (yearData && yearData[1]) ? yearData[1] : undefined - console.log(minYear,maxYear) return { - q: indexUiState.query, + q: indexUiState.query ? encodeURIComponent(indexUiState.query) : undefined, category: indexUiState.refinementList && indexUiState.refinementList.category, subCategory: From db561f8b07d7be85d573faed57d87f3774c4f9b7 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Thu, 5 Sep 2024 15:46:53 +0800 Subject: [PATCH 42/45] fix: mobile ui --- _layouts/egazette-search.html | 2 +- assets/css/algolia.css | 3 +++ assets/js/algolia-search.js | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 622ab6c7..97fa53a9 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -43,7 +43,7 @@

Year
-
+
diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 265d408a..f0620a54 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -17,6 +17,9 @@ } /* General styling for the pagination container */ +.ais-Pagination { + overflow: hidden; +} .ais-Pagination-list { display: flex; list-style-type: none; diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index b7bca032..3d91b2d4 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -281,6 +281,7 @@ search.addWidgets([ container: "#pagination", showFirst: true, showLast: true, + padding: 2 }), ]); search.addWidget( From e3b3e9cad474baea6abdaad37dcbc6784b97af71 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Sat, 21 Sep 2024 13:48:50 +0800 Subject: [PATCH 43/45] fix: ios --- assets/css/algolia.css | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/assets/css/algolia.css b/assets/css/algolia.css index f0620a54..194bedb6 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -70,7 +70,20 @@ @media (max-width: 768px) { .ais-RangeInput-input { - width: inherit; + width: 100%; + } + .ais-RangeInput-label { + width: 33%; + max-width: 6.25rem; + } +} + +@media (max-width: 768px) { + .ais-RangeInput-input { + width: 100%; + } + .ais-RangeInput-label { + width: 33%; } } From c51d5d35b083045b1b9ee255bd20bc02a92da1e0 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 6 Nov 2024 11:14:03 +0800 Subject: [PATCH 44/45] fix: add debouncing --- assets/js/algolia-search.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 3d91b2d4..76780770 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -62,6 +62,10 @@ function getSubcategories(selectedCategories) { return filteredValues; } +// Used for debouncing +let timerId; +let timeout = 250; + const createToggleVisibilityWidget = (containerSelector, attribute) => ({ init({ helper }) { this.container = document.querySelector(containerSelector); @@ -123,6 +127,10 @@ search.addWidgets([ container: "#searchbox", autofocus: true, placeholder: "Start typing to search", + queryHook(query, refine) { + clearTimeout(timerId); + timerId = setTimeout(() => refine(query), timeout); + }, }), instantsearch.widgets.stats({ container: "#stats", From d9138996c51eed99b5cc56b5ee0026364ab35b03 Mon Sep 17 00:00:00 2001 From: Alexander Lee Date: Wed, 6 Nov 2024 11:15:17 +0800 Subject: [PATCH 45/45] feat: add month filter --- _layouts/egazette-search-landing.html | 6 ++++++ _layouts/egazette-search.html | 5 +++++ assets/css/algolia.css | 8 +++++++- assets/js/algolia-search-landing.js | 4 ++++ assets/js/algolia-search.js | 14 +++++++++++++- 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/_layouts/egazette-search-landing.html b/_layouts/egazette-search-landing.html index 3a354b72..b7c561c1 100644 --- a/_layouts/egazette-search-landing.html +++ b/_layouts/egazette-search-landing.html @@ -25,6 +25,12 @@

{{- page.title -}}

~

+
Month
+
+ +

~

+ +
Category
Please refer to the FAQ on the sub-categories below
diff --git a/_layouts/egazette-search.html b/_layouts/egazette-search.html index 97fa53a9..dbb1f8d2 100644 --- a/_layouts/egazette-search.html +++ b/_layouts/egazette-search.html @@ -37,6 +37,11 @@
Year

+
+
Month
+
+
+
diff --git a/assets/css/algolia.css b/assets/css/algolia.css index 194bedb6..5ad75508 100644 --- a/assets/css/algolia.css +++ b/assets/css/algolia.css @@ -153,7 +153,9 @@ } #algolia-search-box-landing, #input-start-date, -#input-end-date { +#input-end-date, +#input-start-month, +#input-end-month { border: 1px solid; border-radius: 4px; border-color: var(--color-divider-medium, #d0d0d0); @@ -212,6 +214,10 @@ display: none; } +.ais-RangeInput-label { + flex: 1; +} + .algolia-search-item-disabled { color: #cdcdc7; } \ No newline at end of file diff --git a/assets/js/algolia-search-landing.js b/assets/js/algolia-search-landing.js index fb9567ae..a5761baa 100644 --- a/assets/js/algolia-search-landing.js +++ b/assets/js/algolia-search-landing.js @@ -123,6 +123,8 @@ function processSearch() { const startDateInput = document.getElementById("input-start-date").value const endDateInput = document.getElementById("input-end-date").value + const startMonthInput = document.getElementById("input-start-month").value + const endMonthInput = document.getElementById("input-end-month").value // Construct URL with query params const categoryFormElement = document.querySelector("#categoryForm"); @@ -143,6 +145,8 @@ function processSearch() { // Date range filters if (startDateInput) url += `&minYear=${encodeURIComponent(startDateInput)}` if (endDateInput) url += `&maxYear=${encodeURIComponent(endDateInput)}` + if (startMonthInput) url += `&minMonth=${encodeURIComponent(startMonthInput)}` + if (endMonthInput) url += `&maxMonth=${encodeURIComponent(endMonthInput)}` // Redirect to results page window.location.href = url; diff --git a/assets/js/algolia-search.js b/assets/js/algolia-search.js index 76780770..92948623 100644 --- a/assets/js/algolia-search.js +++ b/assets/js/algolia-search.js @@ -90,6 +90,9 @@ const search = instantsearch({ const yearData = indexUiState.range?.publishYear ? indexUiState.range.publishYear.split(":") : undefined const minYear = (yearData && yearData[0]) ? yearData[0] : undefined const maxYear = (yearData && yearData[1]) ? yearData[1] : undefined + const monthData = indexUiState.range?.publishMonth ? indexUiState.range.publishMonth.split(":") : undefined + const minMonth = (monthData && monthData[0]) ? monthData[0] : undefined + const maxMonth = (monthData && monthData[1]) ? monthData[1] : undefined return { q: indexUiState.query ? encodeURIComponent(indexUiState.query) : undefined, category: @@ -99,11 +102,15 @@ const search = instantsearch({ indexUiState.refinementList.subCategory, minYear, maxYear, + minMonth, + maxMonth }; }, routeToState(routeState) { const hasPublishYear = routeState.minYear || routeState.maxYear const publishYear = hasPublishYear ? `${routeState.minYear || ""}: ${routeState.maxYear || ""}` : "" + const hasPublishMonth = routeState.minMonth || routeState.maxMonth + const publishMonth = hasPublishMonth ? `${routeState.minMonth || ""}: ${routeState.maxMonth || ""}` : "" return { [algoliaIndexName]: { query: routeState.q, @@ -112,7 +119,8 @@ const search = instantsearch({ subCategory: routeState.subCategory, }, range: { - publishYear + publishYear, + publishMonth }, }, }; @@ -211,6 +219,10 @@ search.addWidgets([ container: '#refinement-list-year', attribute: 'publishYear', }), + instantsearch.widgets.rangeInput({ + container: '#refinement-list-month', + attribute: 'publishMonth', + }), instantsearch.widgets.currentRefinements({ container: "#current-refinements", cssClasses: {