topics and authors grouped by letter

This commit is contained in:
Igor Lobanov 2022-10-05 17:56:59 +02:00
parent e63b018efa
commit 71cec8a6c2
3 changed files with 93 additions and 71 deletions

View File

@ -1,15 +1,14 @@
import { createEffect, createSignal, For, Show } from 'solid-js' import { createEffect, createMemo, createSignal, For, Show } from 'solid-js'
import type { Author } from '../../graphql/types.gen' import type { Author } from '../../graphql/types.gen'
import { AuthorCard } from '../Author/Card' import { AuthorCard } from '../Author/Card'
import { byFirstChar, sortBy } from '../../utils/sortby'
import { groupByName } from '../../utils/groupby'
import { Icon } from '../Nav/Icon' import { Icon } from '../Nav/Icon'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
import { useAuthorsStore } from '../../stores/zine/authors' import { useAuthorsStore, setSortAllBy as setSortAllAuthorsBy } from '../../stores/zine/authors'
import { handleClientRouteLinkClick, useRouter } from '../../stores/router' import { handleClientRouteLinkClick, useRouter } from '../../stores/router'
import { useAuthStore } from '../../stores/auth' import { useAuthStore } from '../../stores/auth'
import { getLogger } from '../../utils/logger' import { getLogger } from '../../utils/logger'
import '../../styles/AllTopics.scss' import '../../styles/AllTopics.scss'
import { Topic } from '../../graphql/types.gen'
const log = getLogger('AllAuthorsView') const log = getLogger('AllAuthorsView')
@ -23,31 +22,37 @@ type Props = {
export const AllAuthorsView = (props: Props) => { export const AllAuthorsView = (props: Props) => {
const { sortedAuthors } = useAuthorsStore({ authors: props.authors }) const { sortedAuthors } = useAuthorsStore({ authors: props.authors })
const [sortedKeys, setSortedKeys] = createSignal<string[]>([])
const [abc, setAbc] = createSignal([])
const { session } = useAuthStore() const { session } = useAuthStore()
createEffect(() => {
setSortAllAuthorsBy(getSearchParams().by || 'shouts')
})
const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || '')) const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || ''))
const { getSearchParams } = useRouter<AllAuthorsPageSearchParams>() const { getSearchParams } = useRouter<AllAuthorsPageSearchParams>()
createEffect(() => { const byLetter = createMemo<{ [letter: string]: Author[] }>(() => {
if ((!getSearchParams().by || getSearchParams().by === 'name') && abc().length === 0) { return sortedAuthors().reduce((acc, author) => {
console.log('[authors] default grouping by abc') const letter = author.name[0]
const grouped = { ...groupByName(sortedAuthors()) } if (!acc[letter]) {
grouped['A-Z'] = sortBy(grouped['A-Z'], byFirstChar) acc[letter] = []
setAbc(grouped)
const keys = Object.keys(abc)
keys.sort()
setSortedKeys(keys)
} else {
console.log('[authors] sorting by ' + getSearchParams().by)
///setSortedAuthors(sortBy(authorList(), getSearchParams().by))
} }
acc[letter].push(author)
return acc
}, {} as { [letter: string]: Author[] })
}) })
log.debug(getSearchParams()) const sortedKeys = createMemo<string[]>(() => {
const keys = Object.keys(byLetter())
keys.sort()
return keys
})
// log.debug(getSearchParams())
return ( return (
<div class="all-topics-page"> <div class="all-topics-page">
@ -108,7 +113,7 @@ export const AllAuthorsView = (props: Props) => {
<h2>{letter}</h2> <h2>{letter}</h2>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<For each={abc()[letter]}> <For each={byLetter()[letter]}>
{(author: Author) => ( {(author: Author) => (
<div class="topic col-sm-6 col-md-3"> <div class="topic col-sm-6 col-md-3">
<div class="topic-title"> <div class="topic-title">

View File

@ -1,4 +1,4 @@
import { createEffect, For, Show } from 'solid-js' import { createEffect, createMemo, For, Show } from 'solid-js'
import type { Topic } from '../../graphql/types.gen' import type { Topic } from '../../graphql/types.gen'
import { Icon } from '../Nav/Icon' import { Icon } from '../Nav/Icon'
import { t } from '../../utils/intl' import { t } from '../../utils/intl'
@ -33,6 +33,25 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
setSortAllTopicsBy(getSearchParams().by || 'shouts') setSortAllTopicsBy(getSearchParams().by || 'shouts')
}) })
const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => {
return sortedTopics().reduce((acc, topic) => {
const letter = topic.title[0]
if (!acc[letter]) {
acc[letter] = []
}
acc[letter].push(topic)
return acc
}, {} as { [letter: string]: Topic[] })
})
const sortedKeys = createMemo<string[]>(() => {
const keys = Object.keys(byLetter())
keys.sort()
return keys
})
const subscribed = (s) => Boolean(session()?.news?.topics && session()?.news?.topics?.includes(s || '')) const subscribed = (s) => Boolean(session()?.news?.topics && session()?.news?.topics?.includes(s || ''))
return ( return (
@ -80,6 +99,9 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
</li> </li>
</ul> </ul>
<Show
when={getSearchParams().by === 'title'}
fallback={() => (
<div class="stats"> <div class="stats">
<For each={sortedTopics()}> <For each={sortedTopics()}>
{(topic) => ( {(topic) => (
@ -87,41 +109,29 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
)} )}
</For> </For>
</div> </div>
)}
{/*FIXME*/} >
{/*<Show*/} <For each={sortedKeys()}>
{/* when={params()['by'] === 'abc'}*/} {(letter) => (
{/* fallback={() => (*/} <div class="group">
{/* <div class="stats">*/} <h2>{letter}</h2>
{/* <For each={getSortedTopics()}>*/} <div class="container">
{/* {(topic: Topic) => (*/} <div class="row">
{/* <TopicCard topic={topic} compact={false} subscribed={subscribed(topic.slug)} />*/} <For each={byLetter()[letter]}>
{/* )}*/} {(topic) => (
{/* </For>*/} <div class="topic col-sm-6 col-md-3">
{/* </div>*/} <div class="topic-title">
{/* )}*/} <a href={`/topic/${topic.slug}`}>{topic.title}</a>
{/*>*/} </div>
{/* <For each={sortedKeys() || []}>*/} </div>
{/* {(letter: string) => (*/} )}
{/* <div class="group">*/} </For>
{/* <h2>{letter}</h2>*/} </div>
{/* <div class="container">*/} </div>
{/* <div class="row">*/} </div>
{/* <For each={abc()[letter]}>*/} )}
{/* {(topic: Partial<Topic>) => (*/} </For>
{/* <div class="topic col-sm-6 col-md-3">*/} </Show>
{/* <div class="topic-title">*/}
{/* <a href={`/topic/${topic.slug}`}>{topic.title}</a>*/}
{/* </div>*/}
{/* </div>*/}
{/* )}*/}
{/* </For>*/}
{/* </div>*/}
{/* </div>*/}
{/* </div>*/}
{/* )}*/}
{/* </For>*/}
{/*</Show>*/}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
import { apiClient } from '../../utils/apiClient' import { apiClient } from '../../utils/apiClient'
import type { Author } from '../../graphql/types.gen' import type { Author } from '../../graphql/types.gen'
import { byCreated } from '../../utils/sortby' import { byCreated, byStat, byTopicStatDesc } from '../../utils/sortby'
import { getLogger } from '../../utils/logger' import { getLogger } from '../../utils/logger'
import { createSignal } from 'solid-js' import { createSignal } from 'solid-js'
@ -8,9 +8,11 @@ import { createLazyMemo } from '@solid-primitives/memo'
const log = getLogger('authors store') const log = getLogger('authors store')
export type AuthorsSortBy = 'created' | 'name' export type AuthorsSortBy = 'shouts' | 'name' | 'rating'
const [sortAllBy, setSortAllBy] = createSignal<AuthorsSortBy>('created') const [sortAllBy, setSortAllBy] = createSignal<AuthorsSortBy>('shouts')
export { setSortAllBy }
const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({}) const [authorEntities, setAuthorEntities] = createSignal<{ [authorSlug: string]: Author }>({})
const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({}) const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]: Author[] }>({})
@ -18,17 +20,22 @@ const [authorsByTopic, setAuthorsByTopic] = createSignal<{ [topicSlug: string]:
const sortedAuthors = createLazyMemo(() => { const sortedAuthors = createLazyMemo(() => {
const authors = Object.values(authorEntities()) const authors = Object.values(authorEntities())
switch (sortAllBy()) { switch (sortAllBy()) {
case 'created': { // case 'created': {
log.debug('sorted by created') // log.debug('sorted by created')
authors.sort(byCreated) // authors.sort(byCreated)
// break
// }
case 'rating':
// TODO:
break break
} case 'shouts':
case 'name': { // TODO:
break
case 'name':
log.debug('sorted by name') log.debug('sorted by name')
authors.sort((a, b) => a.name.localeCompare(b.name)) authors.sort((a, b) => a.name.localeCompare(b.name))
break break
} }
}
return authors return authors
}) })