Skip to content

Commit ce919d4

Browse files
authored
Merge pull request #1184 from prezly/feature/care-6003-clean-up-algolia-code-from-themes
[CARE-6003][CARE-5923] Clean up Algolia code
2 parents 5a5f6c4 + 91103e8 commit ce919d4

17 files changed

+56
-104
lines changed

.env.example

-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@ PREZLY_THEME_UUID=73015107-ac86-418b-9120-4ffa439d5c0f
1111
# NEXT_PUBLIC_HCAPTCHA_SITEKEY=
1212

1313
# This key is unique for every newsroom
14-
ALGOLIA_API_KEY=
1514
MEILISEARCH_API_KEY=
1615

1716
# These variables have default values in the code, but you can override them if you need to
18-
# ALGOLIA_APP_ID=
19-
# ALGOLIA_INDEX=
2017
# MEILISEARCH_HOST=
2118
# MEILISEARCH_INDEX=
2219

README.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Bea Prezly Theme is based on [Next.js] 12+ framework.
66
- Multi-language is powered by [React Intl] and [Prezly Themes Translations].
77
- Analytics powered by [Prezly Analytics].
88
- Code-style is ensured by [ESLint], [StyleLint] and [Prettier].
9-
- Search is powered by [Algolia]
9+
- Search is powered by Meilisearch
1010
- Error-logging with [Sentry].
1111

1212
### Requirements
@@ -33,7 +33,7 @@ cp .env.example .env.local
3333
You'll need to populate it with your Prezly Access Token and your newsroom's UUID.
3434
Additionally, you'll need to provide:
3535
- Sitekey for HCaptcha if you want HCaptcha to work on the Subscribe form.
36-
- Algolia API key for Prezly's search index (you can contact [Prezly support](https://www.prezly.com/talk-to-us) to issue a token for you)
36+
- API key for Prezly's search index (you can contact [Prezly support](https://www.prezly.com/talk-to-us) to issue a token for you)
3737

3838
After that you can run locally in development mode with live reload:
3939

@@ -102,11 +102,9 @@ Made with ♥ by [Prezly](https://www.prezly.com/developers)
102102
[Prezly Theme Kit]: https://github.com/prezly/theme-kit-nextjs
103103
[Typescript]: https://www.typescriptlang.org
104104
[ESLint]: https://eslint.org
105-
[Algolia]: https://algolia.com
106105
[StyleLint]: https://stylelint.io
107106
[Prettier]: https://prettier.io
108107
[React Intl]: https://www.npmjs.com/package/react-intl
109-
[Algolia Search]: https://www.npmjs.com/package/algoliasearch
110108
[Prezly Content React Renderer]: https://www.npmjs.com/package/@prezly/content-renderer-react-js
111109
[Prezly Themes Translations]: https://github.com/prezly/themes-intl-messages
112110
[Prezly Analytics]: https://github.com/prezly/analytics

adapters/server/environment.ts

-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ const Schema = z.object({
1616
MEILISEARCH_HOST: z.string().optional(),
1717
MEILISEARCH_INDEX: z.string().optional(),
1818

19-
ALGOLIA_API_KEY: z.string().optional(),
20-
ALGOLIA_APP_ID: z.string().optional(),
21-
ALGOLIA_INDEX: z.string().optional(),
22-
2319
PREZLY_MODE: z.string().optional(),
2420
});
2521

adapters/server/search.ts

-12
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import { environment } from './environment';
44

55
export function getSearchSettings(): SearchSettings | undefined {
66
const {
7-
ALGOLIA_API_KEY = '',
8-
ALGOLIA_APP_ID = 'UI4CNRAHQB',
9-
ALGOLIA_INDEX = 'public_stories_prod',
107
MEILISEARCH_API_KEY = '',
118
MEILISEARCH_HOST = 'https://search.prezly.com',
129
MEILISEARCH_INDEX = 'public_stories',
@@ -21,14 +18,5 @@ export function getSearchSettings(): SearchSettings | undefined {
2118
};
2219
}
2320

24-
if (ALGOLIA_API_KEY && ALGOLIA_APP_ID && ALGOLIA_INDEX) {
25-
return {
26-
apiKey: ALGOLIA_API_KEY,
27-
appId: ALGOLIA_APP_ID,
28-
index: ALGOLIA_INDEX,
29-
searchBackend: 'algolia',
30-
};
31-
}
32-
3321
return undefined;
3422
}

modules/Header/ui/SearchWidget/SearchWidget.tsx

+1-4
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@ export function SearchWidget({
3535
}: Props) {
3636
const searchClient = useMemo(() => getSearchClient(settings), [settings]);
3737

38-
const filters =
39-
settings.searchBackend === 'algolia'
40-
? `attributes.culture.code:${localeCode}`
41-
: `attributes.culture.code=${localeCode}`;
38+
const filters = `attributes.culture.code=${localeCode}`;
4239

4340
return (
4441
<Modal

modules/Search/Search.tsx

+4-7
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import type { ThemeSettings } from 'theme-settings';
1010
import type { SearchSettings } from 'types';
1111
import { getSearchClient } from 'utils/getSearchClient';
1212

13-
import AlgoliaStateContextProvider from './components/AlgoliaStateContext';
1413
import { Results } from './components/Results';
1514
import { SearchBar } from './components/SearchBar';
15+
import SearchStateContextProvider from './components/SearchStateContext';
1616
import { Subtitle } from './components/Subtitle';
1717
import { Title } from './components/Title';
1818
import type { SearchState } from './types';
@@ -35,10 +35,7 @@ export function Search({ localeCode, settings, showDate, showSubtitle, storyCard
3535

3636
const searchClient = useMemo(() => getSearchClient(settings), [settings]);
3737

38-
const filters =
39-
settings.searchBackend === 'algolia'
40-
? `attributes.culture.code:${localeCode}`
41-
: `attributes.culture.code=${localeCode}`;
38+
const filters = `attributes.culture.code=${localeCode}`;
4239

4340
const scheduleUrlUpdate = useDebounce(DEBOUNCE_TIME_MS, (updatedSearchState: SearchState) => {
4441
if (typeof window === 'undefined') {
@@ -62,7 +59,7 @@ export function Search({ localeCode, settings, showDate, showSubtitle, storyCard
6259
createURL={createUrl}
6360
>
6461
<Configure hitsPerPage={6} filters={filters} />
65-
<AlgoliaStateContextProvider>
62+
<SearchStateContextProvider>
6663
<Title />
6764
<SearchBar />
6865
<Subtitle />
@@ -71,7 +68,7 @@ export function Search({ localeCode, settings, showDate, showSubtitle, storyCard
7168
showSubtitle={showSubtitle}
7269
storyCardVariant={storyCardVariant}
7370
/>
74-
</AlgoliaStateContextProvider>
71+
</SearchStateContextProvider>
7572
</InstantSearch>
7673
);
7774
}

modules/Search/components/AlgoliaStateContext.tsx

-35
This file was deleted.

modules/Search/components/Facet.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useCallback, useMemo, useState } from 'react';
55
import type { RefinementListExposed, RefinementListProvided } from 'react-instantsearch-core';
66
import { connectRefinementList } from 'react-instantsearch-dom';
77

8-
import { FormattedDate, FormattedMessage, useLocale } from '@/adapters/client';
8+
import { FormattedMessage, useLocale } from '@/adapters/client';
99
import { Button } from '@/components/Button';
1010
import { Dropdown } from '@/components/Dropdown';
1111

@@ -59,13 +59,13 @@ export const Facet = connectRefinementList(
5959
case FacetAttribute.MONTH: {
6060
const date = new Date();
6161
date.setMonth(Number(item.label) - 1);
62-
return <FormattedDate value={date} />;
62+
return date.toLocaleDateString(locale, { month: 'long' });
6363
}
6464
default:
6565
return item.label;
6666
}
6767
},
68-
[attribute],
68+
[attribute, locale],
6969
);
7070

7171
if (!items.length) {

modules/Search/components/Results.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { useIntl } from '@/adapters/client';
99
import { Button } from '@/components/Button';
1010
import type { ThemeSettings } from 'theme-settings';
1111

12-
import { useAlgoliaState } from './AlgoliaStateContext';
1312
import type { Props as HitProps } from './Hit';
1413
import { Hit } from './Hit';
14+
import { useSearchState } from './SearchStateContext';
1515

1616
import styles from './Results.module.scss';
1717
import containerStyles from '@/modules/InfiniteStories/InfiniteStories.module.scss'; // FIXME: Pass this from outside
@@ -33,7 +33,7 @@ export const Results = connectInfiniteHits(
3333
storyCardVariant,
3434
}: InfiniteHitsProvided<HitProps['hit']> & Props) => {
3535
const { formatMessage } = useIntl();
36-
const { searching: isSearching } = useAlgoliaState();
36+
const { searching: isSearching } = useSearchState();
3737

3838
return (
3939
<div className={containerStyles.container}>

modules/Search/components/SearchBar.tsx

+1-7
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,7 @@ export function SearchBar() {
4545
<FormattedMessage locale={locale} for={translations.search.filters} />
4646
</p>
4747
{AVAILABLE_FACET_ATTRIBUTES.map((attribute) => (
48-
<Facet
49-
key={attribute}
50-
attribute={attribute}
51-
// This is a hack to make Algolia return more than 10 facets by default. We need to upgrade to v7 to allow finer control over this.
52-
showMore
53-
showMoreLimit={50}
54-
/>
48+
<Facet key={attribute} attribute={attribute} showMore showMoreLimit={50} />
5549
))}
5650
</div>
5751
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use client';
2+
3+
import type { Search } from '@prezly/theme-kit-nextjs';
4+
import type { PropsWithChildren } from 'react';
5+
import { createContext, useContext } from 'react';
6+
import type { StateResultsProvided } from 'react-instantsearch-core';
7+
import { connectStateResults } from 'react-instantsearch-dom';
8+
9+
const SearchStateContext = createContext<StateResultsProvided<Search.IndexedStory> | undefined>(
10+
undefined,
11+
);
12+
13+
function SearchStateContextProvider({
14+
children,
15+
...contextValue
16+
}: PropsWithChildren<StateResultsProvided<Search.IndexedStory>>) {
17+
return (
18+
<SearchStateContext.Provider value={contextValue}>{children}</SearchStateContext.Provider>
19+
);
20+
}
21+
22+
export default connectStateResults(SearchStateContextProvider);
23+
24+
export function useSearchState() {
25+
const state = useContext(SearchStateContext);
26+
27+
if (!state) {
28+
throw new Error('`useSearchState` should only be used inside `SearchStateContextProvider`');
29+
}
30+
31+
return state;
32+
}

modules/Search/components/Subtitle.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { translations } from '@prezly/theme-kit-nextjs';
44

55
import { FormattedMessage, useLocale } from '@/adapters/client';
66

7-
import { useAlgoliaState } from './AlgoliaStateContext';
7+
import { useSearchState } from './SearchStateContext';
88

99
import styles from './Subtitle.module.scss';
1010

1111
export function Subtitle() {
1212
const locale = useLocale();
13-
const { searchState, searchResults } = useAlgoliaState();
13+
const { searchState, searchResults } = useSearchState();
1414

1515
const { query: searchQuery } = searchState;
1616
const resultsCount = searchResults ? searchResults.nbHits : 0;

modules/Search/components/Title.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { translations } from '@prezly/theme-kit-nextjs';
55
import { useIntl } from '@/adapters/client';
66
import { PageTitle } from '@/components/PageTitle';
77

8-
import { useAlgoliaState } from './AlgoliaStateContext';
8+
import { useSearchState } from './SearchStateContext';
99

1010
export function Title() {
1111
const { formatMessage } = useIntl();
12-
const { searchState } = useAlgoliaState();
12+
const { searchState } = useSearchState();
1313

1414
const { query: searchQuery } = searchState;
1515

package-lock.json

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
"@react-hookz/web": "14.7.1",
4242
"@sentry/nextjs": "7.98.0",
4343
"@uploadcare/nextjs-loader": "1.0.0",
44-
"algoliasearch": "4.22.1",
4544
"classnames": "2.5.1",
4645
"modern-normalize": "1.1.0",
4746
"next": "14.2.3",

types.ts

+6-13
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,9 @@ import type { Story } from '@prezly/sdk';
22

33
export type ListStory = Story & Pick<Story.ExtraFields, 'thumbnail_image'>;
44

5-
export type SearchSettings =
6-
| {
7-
searchBackend: 'algolia';
8-
appId: string;
9-
apiKey: string;
10-
index: string;
11-
}
12-
| {
13-
searchBackend: 'meilisearch';
14-
host: string;
15-
apiKey: string;
16-
index: string;
17-
};
5+
export type SearchSettings = {
6+
searchBackend: 'meilisearch';
7+
host: string;
8+
apiKey: string;
9+
index: string;
10+
};

utils/getSearchClient.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import { instantMeiliSearch } from '@meilisearch/instant-meilisearch';
2-
import algoliasearch from 'algoliasearch';
32

43
import type { SearchSettings } from 'types';
54

65
export function getSearchClient(settings: SearchSettings) {
7-
return settings.searchBackend === 'algolia'
8-
? algoliasearch(settings.appId, settings.apiKey)
9-
: instantMeiliSearch(settings.host, settings.apiKey).searchClient;
6+
return instantMeiliSearch(settings.host, settings.apiKey).searchClient;
107
}

0 commit comments

Comments
 (0)