2022-11-15 14:24:50 +00:00
|
|
|
import type { Author, Shout, ShoutInput, ShoutsBy, Topic } from '../../graphql/types.gen'
|
2022-09-09 11:53:35 +00:00
|
|
|
import { apiClient } from '../../utils/apiClient'
|
2022-09-13 09:59:04 +00:00
|
|
|
import { addAuthorsByTopic } from './authors'
|
|
|
|
import { addTopicsByAuthor } from './topics'
|
|
|
|
import { byStat } from '../../utils/sortby'
|
2022-09-30 14:22:33 +00:00
|
|
|
import { createSignal } from 'solid-js'
|
2022-09-29 17:37:21 +00:00
|
|
|
import { createLazyMemo } from '@solid-primitives/memo'
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
const [sortedArticles, setSortedArticles] = createSignal<Shout[]>([])
|
|
|
|
const [articleEntities, setArticleEntities] = createSignal<{ [articleSlug: string]: Shout }>({})
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
const [topArticles, setTopArticles] = createSignal<Shout[]>([])
|
|
|
|
const [topMonthArticles, setTopMonthArticles] = createSignal<Shout[]>([])
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-29 17:37:21 +00:00
|
|
|
const articlesByAuthor = createLazyMemo(() => {
|
2022-09-28 20:16:44 +00:00
|
|
|
return Object.values(articleEntities()).reduce((acc, article) => {
|
|
|
|
article.authors.forEach((author) => {
|
|
|
|
if (!acc[author.slug]) {
|
|
|
|
acc[author.slug] = []
|
|
|
|
}
|
|
|
|
acc[author.slug].push(article)
|
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
return acc
|
|
|
|
}, {} as { [authorSlug: string]: Shout[] })
|
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
|
2022-09-29 17:37:21 +00:00
|
|
|
const articlesByTopic = createLazyMemo(() => {
|
2022-09-28 20:16:44 +00:00
|
|
|
return Object.values(articleEntities()).reduce((acc, article) => {
|
|
|
|
article.topics.forEach((topic) => {
|
|
|
|
if (!acc[topic.slug]) {
|
|
|
|
acc[topic.slug] = []
|
|
|
|
}
|
|
|
|
acc[topic.slug].push(article)
|
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
return acc
|
|
|
|
}, {} as { [authorSlug: string]: Shout[] })
|
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
|
2022-09-29 17:37:21 +00:00
|
|
|
const articlesByLayout = createLazyMemo(() => {
|
2022-09-28 20:16:44 +00:00
|
|
|
return Object.values(articleEntities()).reduce((acc, article) => {
|
|
|
|
if (!acc[article.layout]) {
|
|
|
|
acc[article.layout] = []
|
|
|
|
}
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
acc[article.layout].push(article)
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
return acc
|
|
|
|
}, {} as { [layout: string]: Shout[] })
|
|
|
|
})
|
2022-09-22 09:37:49 +00:00
|
|
|
|
2022-09-29 17:37:21 +00:00
|
|
|
const topViewedArticles = createLazyMemo(() => {
|
2022-09-28 20:16:44 +00:00
|
|
|
const result = Object.values(articleEntities())
|
|
|
|
result.sort(byStat('viewed'))
|
|
|
|
return result
|
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
|
2022-09-29 17:37:21 +00:00
|
|
|
const topCommentedArticles = createLazyMemo(() => {
|
2022-09-28 20:16:44 +00:00
|
|
|
const result = Object.values(articleEntities())
|
|
|
|
result.sort(byStat('commented'))
|
|
|
|
return result
|
|
|
|
})
|
2022-09-09 11:53:35 +00:00
|
|
|
|
|
|
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
2022-09-13 09:59:04 +00:00
|
|
|
const addArticles = (...args: Shout[][]) => {
|
|
|
|
const allArticles = args.flatMap((articles) => articles || [])
|
|
|
|
|
|
|
|
const newArticleEntities = allArticles.reduce((acc, article) => {
|
2022-09-09 11:53:35 +00:00
|
|
|
acc[article.slug] = article
|
|
|
|
return acc
|
2022-09-22 09:37:49 +00:00
|
|
|
}, {} as { [articleSLug: string]: Shout })
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
setArticleEntities((prevArticleEntities) => {
|
|
|
|
return {
|
|
|
|
...prevArticleEntities,
|
2022-09-09 11:53:35 +00:00
|
|
|
...newArticleEntities
|
2022-09-28 20:16:44 +00:00
|
|
|
}
|
|
|
|
})
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
const authorsByTopic = allArticles.reduce((acc, article) => {
|
|
|
|
const { authors, topics } = article
|
|
|
|
|
|
|
|
topics.forEach((topic) => {
|
|
|
|
if (!acc[topic.slug]) {
|
|
|
|
acc[topic.slug] = []
|
|
|
|
}
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
authors.forEach((author) => {
|
|
|
|
if (!acc[topic.slug].some((a) => a.slug === author.slug)) {
|
|
|
|
acc[topic.slug].push(author)
|
|
|
|
}
|
2022-09-09 11:53:35 +00:00
|
|
|
})
|
2022-09-13 09:59:04 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return acc
|
|
|
|
}, {} as { [topicSlug: string]: Author[] })
|
|
|
|
|
|
|
|
addAuthorsByTopic(authorsByTopic)
|
|
|
|
|
|
|
|
const topicsByAuthor = allArticles.reduce((acc, article) => {
|
|
|
|
const { authors, topics } = article
|
|
|
|
|
|
|
|
authors.forEach((author) => {
|
|
|
|
if (!acc[author.slug]) {
|
|
|
|
acc[author.slug] = []
|
|
|
|
}
|
|
|
|
|
|
|
|
topics.forEach((topic) => {
|
|
|
|
if (!acc[author.slug].some((t) => t.slug === topic.slug)) {
|
|
|
|
acc[author.slug].push(topic)
|
|
|
|
}
|
2022-09-09 11:53:35 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
return acc
|
|
|
|
}, {} as { [authorSlug: string]: Topic[] })
|
|
|
|
|
|
|
|
addTopicsByAuthor(topicsByAuthor)
|
|
|
|
}
|
|
|
|
|
|
|
|
const addSortedArticles = (articles: Shout[]) => {
|
2022-09-22 09:37:49 +00:00
|
|
|
setSortedArticles((prevSortedArticles) => [...prevSortedArticles, ...articles])
|
2022-09-09 11:53:35 +00:00
|
|
|
}
|
|
|
|
|
2022-11-15 14:24:50 +00:00
|
|
|
export const loadShoutsBy = async ({
|
|
|
|
by,
|
2022-10-28 21:21:47 +00:00
|
|
|
limit,
|
|
|
|
offset = 0
|
|
|
|
}: {
|
2022-11-15 14:24:50 +00:00
|
|
|
by: ShoutsBy
|
2022-10-28 21:21:47 +00:00
|
|
|
limit: number
|
|
|
|
offset?: number
|
|
|
|
}): Promise<{ hasMore: boolean }> => {
|
2022-11-15 14:24:50 +00:00
|
|
|
const newArticles = await apiClient.loadShoutsBy({
|
|
|
|
by,
|
|
|
|
amount: limit + 1,
|
2022-10-28 21:21:47 +00:00
|
|
|
offset
|
|
|
|
})
|
|
|
|
|
|
|
|
const hasMore = newArticles.length === limit + 1
|
|
|
|
|
|
|
|
if (hasMore) {
|
|
|
|
newArticles.splice(-1)
|
|
|
|
}
|
|
|
|
|
|
|
|
addArticles(newArticles)
|
|
|
|
addSortedArticles(newArticles)
|
|
|
|
|
|
|
|
return { hasMore }
|
2022-10-05 15:11:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const resetSortedArticles = () => {
|
|
|
|
setSortedArticles([])
|
|
|
|
}
|
|
|
|
|
2022-11-09 17:57:35 +00:00
|
|
|
export const createArticle = async ({ article }: { article: ShoutInput }) => {
|
|
|
|
try {
|
|
|
|
await apiClient.createArticle({ article })
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-09 11:53:35 +00:00
|
|
|
type InitialState = {
|
2022-11-15 14:24:50 +00:00
|
|
|
shouts?: Shout[]
|
2022-09-09 11:53:35 +00:00
|
|
|
}
|
|
|
|
|
2022-09-23 07:38:48 +00:00
|
|
|
export const useArticlesStore = (initialState: InitialState = {}) => {
|
2022-11-15 14:24:50 +00:00
|
|
|
addArticles([...(initialState.shouts || [])])
|
2022-09-09 12:18:09 +00:00
|
|
|
|
2022-11-15 14:24:50 +00:00
|
|
|
if (initialState.shouts) {
|
|
|
|
setSortedArticles([...initialState.shouts])
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
2022-09-09 12:18:09 +00:00
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
return {
|
2022-09-28 20:16:44 +00:00
|
|
|
articleEntities,
|
|
|
|
sortedArticles,
|
2022-11-15 14:24:50 +00:00
|
|
|
loadShoutsBy,
|
2022-09-28 20:16:44 +00:00
|
|
|
articlesByAuthor,
|
2022-11-15 14:24:50 +00:00
|
|
|
articlesByLayout,
|
|
|
|
articlesByTopic,
|
2022-09-28 20:16:44 +00:00
|
|
|
topMonthArticles,
|
2022-11-15 14:24:50 +00:00
|
|
|
topArticles,
|
2022-09-28 20:16:44 +00:00
|
|
|
topCommentedArticles,
|
2022-11-15 14:24:50 +00:00
|
|
|
topViewedArticles
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
2022-09-09 12:18:09 +00:00
|
|
|
}
|