resolve nextSibling error + refactoring Feed Sidebar

This commit is contained in:
ilya-bkv 2023-04-29 16:43:50 +03:00
parent 80876c5fc7
commit e39b6f4068
8 changed files with 225 additions and 229 deletions

View File

@ -57,7 +57,6 @@ export const EditorBubbleMenu = (props: BubbleMenuProps) => {
}
const handleLinkFormSubmit = (value: string) => {
console.log('!!! value:', value)
props.editor.chain().focus().setLink({ href: value }).run()
}

View File

@ -1,83 +0,0 @@
.sidebar {
max-height: calc(100vh - 120px);
overflow: auto;
position: sticky;
top: 120px;
}
.sidebarItemName {
margin-right: 0.5em;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
}
.counter {
@include font-size(1.2rem);
align-items: center;
align-self: flex-start;
background: #f6f6f6;
border-radius: 0.8rem;
display: flex;
font-weight: bold;
justify-content: center;
min-width: 2em;
margin-left: 0.5em;
padding: 0.25em 0.5em 0.15em;
transition: background-color 0.2s;
}
.unread {
position: relative;
&::after {
background: #2638d9;
border-radius: 100%;
content: '';
display: inline-block;
height: 0.5em;
left: 100%;
margin-left: 0.3em;
position: absolute;
top: 0.5em;
width: 0.5em;
}
}
.settings {
display: flex;
justify-content: space-between;
margin-bottom: 2em;
}
a {
img {
transition: filter 0.3s;
}
&:hover {
img {
filter: invert(1);
}
.counter {
background: #000;
}
}
}
.icon {
display: inline-block;
line-height: 1;
height: 2rem;
margin-right: 0.5em;
vertical-align: middle;
width: 2.2rem;
img {
height: 100%;
object-fit: contain;
object-position: center;
width: 100%;
}
}

View File

@ -1,138 +0,0 @@
import { For } from 'solid-js'
import type { Author } from '../../graphql/types.gen'
import { useAuthorsStore } from '../../stores/zine/authors'
import { Icon } from '../_shared/Icon'
import { useTopicsStore } from '../../stores/zine/topics'
import { useArticlesStore } from '../../stores/zine/articles'
import { useSeenStore } from '../../stores/zine/seen'
import { useSession } from '../../context/session'
import styles from './Sidebar.module.scss'
import { useLocalize } from '../../context/localize'
type FeedSidebarProps = {
authors: Author[]
}
export const FeedSidebar = (props: FeedSidebarProps) => {
const { t } = useLocalize()
const { seen } = useSeenStore()
const { session } = useSession()
const { authorEntities } = useAuthorsStore({ authors: props.authors })
const { articlesByTopic } = useArticlesStore()
const { topicEntities } = useTopicsStore()
const checkTopicIsSeen = (topicSlug: string) => {
return articlesByTopic()[topicSlug]?.every((article) => Boolean(seen()[article.slug]))
}
const checkAuthorIsSeen = (authorSlug: string) => {
return Boolean(seen()[authorSlug])
}
return (
<div class={styles.sidebar}>
<ul>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="feed-all" class={styles.icon} />
<strong>общая лента</strong>
</span>
</a>
</li>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="feed-my" class={styles.icon} />
моя лента
</span>
</a>
</li>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="feed-collaborate" class={styles.icon} />
соучастие
</span>
<span class={styles.counter}>7</span>
</a>
</li>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="feed-discussion" class={styles.icon} />
дискуссии
</span>
<span class={styles.counter}>18</span>
</a>
</li>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="feed-drafts" class={styles.icon} />
черновики
</span>
<span class={styles.counter}>283</span>
</a>
</li>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="bookmark" class={styles.icon} />
закладки
</span>
</a>
</li>
<li>
<a href="#">
<span class={styles.sidebarItemName}>
<Icon name="feed-notifications" class={styles.icon} />
уведомления
</span>
<span class={styles.counter}>283</span>
</a>
</li>
</ul>
<ul>
<li>
<a href="/feed?by=subscribed">
<strong>{t('My subscriptions')}</strong>
</a>
</li>
<For each={session()?.news?.authors}>
{(authorSlug: string) => (
<li>
<a
href={`/author/${authorSlug}`}
classList={{ [styles.unread]: checkAuthorIsSeen(authorSlug) }}
>
<small>@{authorSlug}</small>
{authorEntities()[authorSlug]?.name}
</a>
</li>
)}
</For>
<For each={session()?.news?.topics}>
{(topicSlug: string) => (
<li>
<a href={`/author/${topicSlug}`} classList={{ [styles.unread]: checkTopicIsSeen(topicSlug) }}>
{topicEntities()[topicSlug]?.title}
</a>
</li>
)}
</For>
</ul>
<div class={styles.settings}>
<a href="/feed/settings">
<Icon name="settings" class={styles.icon} />
{t('Feed settings')}
</a>
</div>
</div>
)
}

View File

@ -0,0 +1,89 @@
.sidebar {
max-height: calc(100vh - 120px);
overflow: auto;
position: sticky;
top: 120px;
ul > li {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.sidebarItemName {
margin-right: 0.5em;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
}
.counter {
@include font-size(1.2rem);
align-items: center;
align-self: flex-start;
background: #f6f6f6;
border-radius: 0.8rem;
display: inline-flex;
font-weight: bold;
justify-content: center;
min-width: 2em;
margin-left: 0.5em;
padding: 0.25em 0.5em 0.15em;
transition: background-color 0.2s;
}
.unread {
position: relative;
&::after {
background: #2638d9;
border-radius: 100%;
content: '';
display: inline-block;
height: 0.5em;
left: 100%;
margin-left: 0.3em;
position: absolute;
top: 0.5em;
width: 0.5em;
}
}
.settings {
display: flex;
justify-content: space-between;
margin-bottom: 2em;
}
a {
img {
transition: filter 0.3s;
}
&:hover {
img {
filter: invert(1);
}
.counter {
background: #000;
}
}
}
.icon {
display: inline-block;
line-height: 1;
height: 2rem;
margin-right: 0.5em;
vertical-align: middle;
width: 2.2rem;
img {
height: 100%;
object-fit: contain;
object-position: center;
width: 100%;
}
}
}

View File

@ -0,0 +1,129 @@
import { createSignal, For } from 'solid-js'
import type { Author } from '../../../graphql/types.gen'
import { useAuthorsStore } from '../../../stores/zine/authors'
import { Icon } from '../../_shared/Icon'
import { useTopicsStore } from '../../../stores/zine/topics'
import { useArticlesStore } from '../../../stores/zine/articles'
import { useSeenStore } from '../../../stores/zine/seen'
import { useSession } from '../../../context/session'
import { useLocalize } from '../../../context/localize'
import styles from './Sidebar.module.scss'
type FeedSidebarProps = {
authors: Author[]
}
type ListItem = {
title: string
icon?: string
counter?: number
href?: string
isBold?: boolean
}
export const Sidebar = (props: FeedSidebarProps) => {
const { t } = useLocalize()
const { seen } = useSeenStore()
const { session } = useSession()
const { authorEntities } = useAuthorsStore({ authors: props.authors })
const { articlesByTopic } = useArticlesStore()
const { topicEntities } = useTopicsStore()
createSignal(() => {
console.log('!!! topicEntities:', topicEntities())
})
const checkTopicIsSeen = (topicSlug: string) => {
return articlesByTopic()[topicSlug]?.every((article) => Boolean(seen()[article.slug]))
}
const checkAuthorIsSeen = (authorSlug: string) => {
return Boolean(seen()[authorSlug])
}
const menuItems: ListItem[] = [
{
icon: 'feed-all',
title: t('general feed')
},
{
icon: 'feed-my',
title: t('my feed')
},
{
icon: 'feed-collaborate',
title: t('accomplices')
},
{
icon: 'feed-discussion',
title: t('discussions'),
counter: 4
},
{
icon: 'feed-drafts',
title: t('drafts'),
counter: 14
},
{
icon: 'bookmark',
title: t('bookmarks'),
counter: 6
},
{
icon: 'feed-notifications',
title: t('notifications')
},
{
href: '/feed?by=subscribed',
title: t('My subscriptions'),
isBold: true
}
]
return (
<div class={styles.sidebar}>
<ul>
{menuItems.map((item: ListItem, index) => (
<li key={index}>
<a href="#">
<span class={styles.sidebarItemName}>
{item.icon && <Icon name={item.icon} class={styles.icon} />}
<strong>{item.title}</strong>
{item.counter && <span class={styles.counter}>18</span>}
</span>
</a>
</li>
))}
<For each={session()?.news?.authors}>
{(authorSlug: string) => (
<li>
<a
href={`/author/${authorSlug}`}
classList={{ [styles.unread]: checkAuthorIsSeen(authorSlug) }}
>
<small>@{authorSlug}</small>
{authorEntities()[authorSlug]?.name}
</a>
</li>
)}
</For>
<For each={session()?.news?.topics}>
{(topicSlug: string) => (
<li>
<a href={`/author/${topicSlug}`} classList={{ [styles.unread]: checkTopicIsSeen(topicSlug) }}>
{topicEntities()[topicSlug]?.title ? topicEntities()[topicSlug]?.title : topicSlug}
</a>
</li>
)}
</For>
</ul>
<div class={styles.settings}>
<a href="/feed/settings">
<Icon name="settings" class={styles.icon} />
{t('Feed settings')}
</a>
</div>
</div>
)
}

View File

@ -0,0 +1 @@
export { Sidebar } from './Sidebar'

View File

@ -1,9 +1,8 @@
import { For, Show } from 'solid-js'
import type { Topic } from '../../graphql/types.gen'
import { Icon } from '../_shared/Icon'
import './Topics.scss'
import { useLocalize } from '../../context/localize'
import './Topics.scss'
export const NavTopics = (props: { topics: Topic[] }) => {
const { t, lang } = useLocalize()

View File

@ -3,7 +3,7 @@ import '../../styles/Feed.scss'
import { Icon } from '../_shared/Icon'
import { ArticleCard } from '../Feed/Card'
import { AuthorCard } from '../Author/Card'
import { FeedSidebar } from '../Feed/Sidebar'
import { Sidebar } from '../Feed/Sidebar'
import { loadShouts, useArticlesStore } from '../../stores/zine/articles'
import { useAuthorsStore } from '../../stores/zine/authors'
import { useTopicsStore } from '../../stores/zine/topics'
@ -73,18 +73,18 @@ export const FeedView = () => {
onMount(async () => {
// load recent shouts not only published ( visibility = community )
loadMore()
await loadMore()
// load 5 recent comments overall
const comments = await loadReactionsBy({ by: { comment: true }, limit: 5 })
setTopComments(comments)
})
return (
<>
<div>
<div class="wide-container feed">
<div class="row">
<div class={clsx('col-md-5 col-xl-4', styles.feedNavigation)}>
<FeedSidebar authors={sortedAuthors()} />
<Sidebar authors={sortedAuthors()} />
</div>
<div class="col-md-12 offset-xl-1">
@ -198,6 +198,6 @@ export const FeedView = () => {
</aside>
</div>
</div>
</>
</div>
)
}