postmerge-2

This commit is contained in:
Untone 2024-01-25 22:16:38 +03:00
parent 5f592e6fff
commit f77d7b28df
5 changed files with 50 additions and 44 deletions

View File

@ -356,7 +356,7 @@ export const Editor = (props: Props) => {
}) })
onCleanup(() => { onCleanup(() => {
editor().destroy() editor()?.destroy()
}) })
return ( return (

View File

@ -3,7 +3,6 @@ import type { Shout } from '../../../graphql/schema/core.gen'
import { createSignal, Show, For } from 'solid-js' import { createSignal, Show, For } from 'solid-js'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { apiClient } from '../../../graphql/client/core'
import { Button } from '../../_shared/Button' import { Button } from '../../_shared/Button'
import { Icon } from '../../_shared/Icon' import { Icon } from '../../_shared/Icon'
import { FEED_PAGE_SIZE } from '../../Views/Feed/Feed' import { FEED_PAGE_SIZE } from '../../Views/Feed/Feed'
@ -11,6 +10,9 @@ import { FEED_PAGE_SIZE } from '../../Views/Feed/Feed'
import { SearchResultItem } from './SearchResultItem' import { SearchResultItem } from './SearchResultItem'
import styles from './SearchModal.module.scss' import styles from './SearchModal.module.scss'
import { restoreScrollPosition, saveScrollPosition } from '../../../utils/scroll'
import { loadShoutsSearch, useArticlesStore } from '../../../stores/zine/articles'
import { byScore } from '../../../utils/sortby'
// @@TODO handle empty article options after backend support (subtitle, cover, etc.) // @@TODO handle empty article options after backend support (subtitle, cover, etc.)
// @@TODO implement load more // @@TODO implement load more
@ -48,40 +50,38 @@ const prepareSearchResults = (list, searchValue) =>
export const SearchModal = () => { export const SearchModal = () => {
const { t } = useLocalize() const { t } = useLocalize()
const { sortedArticles } = useArticlesStore()
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const [offset, setOffset] = createSignal(0)
const [inputValue, setInputValue] = createSignal('') const [inputValue, setInputValue] = createSignal('')
const [searchResultsList, setSearchResultsList] = createSignal<[] | null>([]) //const [searchResultsList, setSearchResultsList] = createSignal<[] | null>([])
const [isLoading, setIsLoading] = createSignal(false) const [isLoading, setIsLoading] = createSignal(false)
// const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) // const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const handleSearch = async () => { let searchEl: HTMLInputElement
const searchValue = inputValue() || '' const handleQueryChange = async (_ev) => {
setInputValue(searchEl.value)
if (Boolean(searchValue) && searchValue.length > 2) { if (inputValue() && inputValue().length > 2) await loadMore()
setIsLoading(true) }
try { const loadMore = async () => {
// TODO: use offset to load more setIsLoading(true)
const response = await apiClient.getShoutsSearch({ saveScrollPosition()
text: searchValue, if (inputValue() && inputValue().length > 2) {
limit: FEED_PAGE_SIZE, console.log(inputValue())
offset: 0, const { hasMore } = await loadShoutsSearch({
}) text: inputValue(),
const searchResult = await response.json() offset: offset(),
limit: FEED_PAGE_SIZE,
if (searchResult.length > 0) { })
const preparedSearchResultsList = prepareSearchResults(searchResult, searchValue) setIsLoadMoreButtonVisible(hasMore)
setOffset(offset() + FEED_PAGE_SIZE)
setSearchResultsList(preparedSearchResultsList) } else {
} else { console.warn('[SaerchView] no query found')
setSearchResultsList(null)
}
} catch (error) {
console.log('search request failed', error)
} finally {
setIsLoading(false)
}
} }
restoreScrollPosition()
setIsLoading(false)
} }
return ( return (
@ -90,16 +90,13 @@ export const SearchModal = () => {
type="search" type="search"
placeholder={t('Site search')} placeholder={t('Site search')}
class={styles.searchInput} class={styles.searchInput}
onInput={(event) => { onInput={handleQueryChange}
setInputValue(event.target.value) ref={searchEl}
handleSearch()
}}
/> />
<Button <Button
class={styles.searchButton} class={styles.searchButton}
onClick={handleSearch} onClick={loadMore}
value={isLoading() ? <div class={styles.searchLoader} /> : <Icon name="search" />} value={isLoading() ? <div class={styles.searchLoader} /> : <Icon name="search" />}
/> />
@ -111,14 +108,13 @@ export const SearchModal = () => {
/> />
<Show when={!isLoading()}> <Show when={!isLoading()}>
<Show when={searchResultsList()}> <Show when={sortedArticles()}>
<For each={searchResultsList()}> <For each={sortedArticles().sort(byScore())}>
{(article: Shout) => ( {(article: Shout) => (
<div> <div>
<SearchResultItem <SearchResultItem
article={article} article={article}
settings={{ settings={{
noimage: true, // @@TODO remove flag after cover support
isFloorImportant: true, isFloorImportant: true,
isSingle: true, isSingle: true,
nodate: true, nodate: true,
@ -128,16 +124,16 @@ export const SearchModal = () => {
)} )}
</For> </For>
{/* <Show when={isLoadMoreButtonVisible()}> <Show when={isLoadMoreButtonVisible()}>
<p class="load-more-container"> <p class="load-more-container">
<button class="button" onClick={loadMore}> <button class="button" onClick={loadMore}>
{t('Load more')} {t('Load more')}
</button> </button>
</p> </p>
</Show> */} </Show>
</Show> </Show>
<Show when={!searchResultsList()}> <Show when={!sortedArticles()}>
<p class={styles.searchDescription} innerHTML={t("We couldn't find anything for your request")} /> <p class={styles.searchDescription} innerHTML={t("We couldn't find anything for your request")} />
</Show> </Show>
</Show> </Show>

View File

@ -60,8 +60,8 @@ export const InviteMembers = (props: Props) => {
}) })
const start = page * PAGE_SIZE const start = page * PAGE_SIZE
const end = start + PAGE_SIZE const end = start + PAGE_SIZE
const authors = authorsToInvite().map((author) => ({ ...author, selected: false })) const authors = authorsToInvite()?.map((author) => ({ ...author, selected: false }))
return authors.slice(start, end) return authors?.slice(start, end)
} }
const [pages, infiniteScrollLoader, { end }] = createInfiniteScroll(fetcher) const [pages, infiniteScrollLoader, { end }] = createInfiniteScroll(fetcher)

View File

@ -22,7 +22,7 @@ const [topMonthArticles, setTopMonthArticles] = createSignal<Shout[]>([])
const articlesByAuthor = createLazyMemo(() => { const articlesByAuthor = createLazyMemo(() => {
return Object.values(articleEntities()).reduce( return Object.values(articleEntities()).reduce(
(acc, article) => { (acc, article) => {
article.authors.forEach((author) => { article.authors?.forEach((author) => {
if (!acc[author.slug]) { if (!acc[author.slug]) {
acc[author.slug] = [] acc[author.slug] = []
} }

View File

@ -40,6 +40,16 @@ export const byTopicStatDesc = (metric: keyof TopicStat) => {
} }
} }
export const byScore = () => {
return (a, b) => {
const x = a?.score || 0
const y = b?.score || 0
if (x > y) return -1
if (x < y) return 1
return 0
}
}
export const sortBy = (data, metric) => { export const sortBy = (data, metric) => {
const x = [...data] const x = [...data]
x.sort(typeof metric === 'function' ? metric : byStat(metric)) x.sort(typeof metric === 'function' ? metric : byStat(metric))