Feature/entity card (#246)

Add Bages components
This commit is contained in:
Ilya Y 2023-10-04 22:04:09 +03:00 committed by GitHub
parent 0f54752111
commit fac6422f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 423 additions and 169 deletions

View File

@ -9,11 +9,9 @@
"Add audio": "Add audio",
"Add blockquote": "Add blockquote",
"Add comment": "Comment",
"Here you can manage all your Discourse subscriptions": "Here you can manage all your Discourse subscriptions",
"Add cover": "Add cover",
"Add image": "Add image",
"Add images": "Add images",
"Collections": "Collections",
"Add intro": "Add intro",
"Add link": "Add link",
"Add rule": "Add rule",
@ -65,6 +63,7 @@
"Choose a title image for the article. You can immediately see how the publication card will look like.": "Choose a title image for the article. You can immediately see how the publication card will look like.",
"Choose who you want to write to": "Choose who you want to write to",
"Collaborate": "Help Edit",
"Collections": "Collections",
"Come up with a subtitle for your story": "Come up with a subtitle for your story",
"Come up with a title for your story": "Come up with a title for your story",
"Comment successfully deleted": "Comment successfully deleted",
@ -147,6 +146,7 @@
"Help": "Помощь",
"Help to edit": "Help to edit",
"Here you can customize your profile the way you want.": "Here you can customize your profile the way you want.",
"Here you can manage all your Discourse subscriptions": "Here you can manage all your Discourse subscriptions",
"Hide table of contents": "Hide table of contents",
"Highlight": "Highlight",
"Hooray! Welcome!": "Hooray! Welcome!",
@ -154,8 +154,8 @@
"Hot topics": "Hot topics",
"Hotkeys": "Горячие клавиши",
"How can I help/skills": "How can I help/skills",
"How to help": "How to help?",
"How it works": "How it works",
"How to help": "How to help?",
"How to write a good article": "Как написать хорошую статью",
"How to write an article": "How to write an article",
"I have an account": "I have an account!",
@ -202,16 +202,17 @@
"My feed": "My feed",
"My subscriptions": "Subscriptions",
"Name": "Name",
"Newsletter": "Newsletter",
"New literary work": "New literary work",
"New only": "New only",
"New password": "New password",
"New stories every day and even more!": "New stories and more are waiting for you every day!",
"Newsletter": "Newsletter",
"Night mode": "Night mode",
"No such account, please try to register": "No such account found, please try to register",
"Nothing here yet": "There's nothing here yet",
"Nothing is here": "There is nothing here",
"Notifications": "Notifications",
"Registered since {{date}}": "Registered since {{date}}",
"Or continue with social network": "Or continue with social network",
"Or paste a link to an image": "Or paste a link to an image",
"Ordered list": "Ordered list",
@ -285,9 +286,9 @@
"Start conversation": "Start a conversation",
"Subsccriptions": "Subscriptions",
"Subscribe": "Subscribe",
"Subscribe us": "Subscribe us",
"Subscribe what you like to tune your personal feed": "Subscribe to topics that interest you to customize your personal feed and get instant updates on new posts and discussions",
"Subscribe who you like to tune your personal feed": "Subscribe to authors you're interested in to customize your personal feed and get instant updates on new posts and discussions",
"Subscribe us": "Subscribe us",
"Subscription": "Subscription",
"Subscriptions": "Subscriptions",
"Substrate": "Substrate",
@ -328,6 +329,7 @@
"Upload video": "Upload video",
"Username": "Username",
"Userpic": "Userpic",
"Users": "Users",
"Video": "Video",
"Video format not supported": "Video format not supported",
"Views": "Views",
@ -351,8 +353,8 @@
"You ll be able to participate in discussions, rate others' comments and learn about new responses": "You ll be able to participate in discussions, rate others' comments and learn about new responses",
"You've confirmed email": "You've confirmed email",
"You've reached a non-existed page": "You've reached a non-existed page",
"Your name will appear on your profile page and as your signature in publications, comments and responses.": "Your name will appear on your profile page and as your signature in publications, comments and responses",
"Your email": "Your email",
"Your name will appear on your profile page and as your signature in publications, comments and responses.": "Your name will appear on your profile page and as your signature in publications, comments and responses",
"accomplices": "accomplices",
"actions": "actions",
"add link": "add link",
@ -395,17 +397,16 @@
"shout": "post",
"sign up or sign in": "sign up or sign in",
"slug is used by another user": "Slug is already taken by another user",
"terms of use": "terms of use",
"topics": "topics",
"user already exist": "user already exists",
"video": "video",
"view": "view",
"zine": "zine",
"subscriber": "subscriber",
"subscriber_rp": "subscriber",
"subscribers": "subscribers",
"subscription": "subscription",
"subscription_rp": "subscription",
"subscriptions": "subscriptions",
"Users": "Users"
"terms of use": "terms of use",
"topics": "topics",
"user already exist": "user already exists",
"video": "video",
"view": "view",
"zine": "zine"
}

View File

@ -67,6 +67,7 @@
"Choose a title image for the article. You can immediately see how the publication card will look like.": "Выберите заглавное изображение для статьи. Тут же сразу можно увидеть как будет выглядеть карточка публикации.",
"Choose who you want to write to": "Выберите кому хотите написать",
"Collaborate": "Помочь редактировать",
"Collections": "Коллекции",
"Come up with a subtitle for your story": "Придумайте подзаголовок вашей истории",
"Come up with a title for your story": "Придумайте заголовок вашей истории",
"Comment successfully deleted": "Комментарий успешно удален",
@ -75,7 +76,6 @@
"Confirm": "Подтвердить",
"Cooperate": "Соучаствовать",
"Copy": "Скопировать",
"Collections": "Коллекции",
"Copy link": "Скопировать ссылку",
"Corrections history": "История правок",
"Create Chat": "Создать чат",
@ -111,6 +111,7 @@
"Email": "Почта",
"Enter": "Войти",
"Enter URL address": "Введите адрес ссылки",
"Enter footnote text": "Введите текст сноски",
"Enter image description": "Введите описание изображения",
"Enter image title": "Введите название изображения",
"Enter text": "Введите текст",
@ -153,6 +154,7 @@
"Help": "Помощь",
"Help to edit": "Помочь редактировать",
"Here you can customize your profile the way you want.": "Здесь можно настроить свой профиль так, как вы хотите.",
"Here you can manage all your Discourse subscriptions": "Здесь можно управлять всеми своими подписками на Дискурсе",
"Hide table of contents": "Скрыть главление",
"Highlight": "Подсветка",
"Hooray! Welcome!": "Ура! Добро пожаловать!",
@ -209,18 +211,18 @@
"Move up": "Переместить вверх",
"My feed": "Моя лента",
"My subscriptions": "Подписки",
"Here you can manage all your Discourse subscriptions": "Здесь можно управлять всеми своими подписками на Дискурсе",
"Name": "Имя",
"Newsletter": "Рассылка",
"New literary work": "Новое произведение",
"New only": "Только новые",
"New password": "Новый пароль",
"New stories every day and even more!": "Каждый день вас ждут новые истории и ещё много всего интересного!",
"Newsletter": "Рассылка",
"Night mode": "Ночная тема",
"No such account, please try to register": "Такой адрес не найден, попробуйте зарегистрироваться",
"Nothing here yet": "Здесь пока ничего нет",
"Nothing is here": "Здесь ничего нет",
"Notifications": "Уведомления",
"Registered since {{date}}": "На сайте c {{date}}",
"Or continue with social network": "Или войдите через соцсеть",
"Or paste a link to an image": "Или вставьте ссылку на изображение",
"Ordered list": "Нумерованный список",
@ -286,8 +288,8 @@
"Share": "Поделиться",
"Short opening": "Расскажите вашу историю...",
"Show": "Показать",
"Show more": "Читать дальше",
"Show lyrics": "Текст песни",
"Show more": "Читать дальше",
"Show table of contents": "Показать главление",
"Slug": "Постоянная ссылка",
"Social networks": "Социальные сети",
@ -302,11 +304,10 @@
"Subheader": "Подзаголовок",
"Subscribe": "Подписаться",
"Subscribe to comments": "Подписаться на комментарии",
"Subscribe us": "Подпишитесь на нас",
"Subscribe what you like to tune your personal feed": "Подпишитесь на интересующие вас темы, чтобы настроить вашу персональную ленту и моментально узнавать о новых публикациях и обсуждениях",
"Subscribe who you like to tune your personal feed": "Подпишитесь на интересующих вас авторов, чтобы настроить вашу персональную ленту и моментально узнавать о новых публикациях и обсуждениях",
"Subscribe us": "Подпишитесь на нас",
"Subscription": "Подписка",
"subscription": "подписка",
"Subscriptions": "Подписки",
"Substrate": "Подложка",
"Success": "Успешно",
@ -340,12 +341,13 @@
"Try to find another way": "Попробуйте найти по-другому",
"Unfollow": "Отписаться",
"Unfollow the topic": "Отписаться от темы",
"Unnamed draft": "Unnamed draft",
"Unnamed draft": "Черновик без названия",
"Upload": "Загрузить",
"Upload error": "Ошибка загрузки",
"Upload video": "Загрузить видео",
"Username": "Имя пользователя",
"Userpic": "Аватар",
"Users": "Пользователи",
"Video": "Видео",
"Video format not supported": "Тип видео не поддерживается",
"Views": "Просмотры",
@ -371,8 +373,8 @@
"You've confirmed email": "Вы подтвердили почту",
"You've reached a non-existed page": "Вы попали на несуществующую страницу",
"You've successfully logged out": "Вы успешно вышли из аккаунта",
"Your name will appear on your profile page and as your signature in publications, comments and responses.": "Ваше имя появится на странице вашего профиля и как ваша подпись в публикациях, комментариях и откликах",
"Your email": "Ваш email",
"Your name will appear on your profile page and as your signature in publications, comments and responses.": "Ваше имя появится на странице вашего профиля и как ваша подпись в публикациях, комментариях и откликах",
"actions": "действия",
"add link": "добавить ссылку",
"all topics": "все темы",
@ -395,6 +397,7 @@
"email not confirmed": "email не подтвержден",
"enter": "войдите",
"feed": "лента",
"follower": "подписчик",
"general feed": "Общая лента",
"header 1": "заголовок 1",
"header 2": "заголовок 2",
@ -420,18 +423,16 @@
"sign up or sign in": "зарегистрироваться или войти",
"slug is used by another user": "Имя уже занято другим пользователем",
"squib": "Подверстка",
"subscriber": "подписчик",
"subscriber_rp": "подписчика",
"subscribers": "подписчиков",
"subscription": "подписка",
"subscription_rp": "подписки",
"subscriptions": "подписок",
"terms of use": "правилами пользования сайтом",
"topics": "темы",
"user already exist": "пользователь уже существует",
"video": "видео",
"view": "просмотр",
"zine": "журнал",
"Enter footnote text": "Введите текст сноски",
"follower": "подписчик",
"subscriber": "подписчик",
"subscriber_rp": "подписчика",
"subscribers": "подписчиков",
"subscription_rp": "подписки",
"subscriptions": "подписок",
"Users": "Пользователи"
"zine": "журнал"
}

View File

@ -1,6 +1,6 @@
import { createEffect, JSX, Show } from 'solid-js'
import { useSession } from '../../context/session'
import { hideModal, showModal } from '../../stores/ui'
import { hideModal } from '../../stores/ui'
import { useRouter } from '../../stores/router'
import { RootSearchParams } from '../../pages/types'
import { AuthModalSearchParams } from '../Nav/AuthModal/types'

View File

@ -0,0 +1,32 @@
.AuthorBadge {
display: flex;
flex-flow: row nowrap;
align-items: flex-start;
margin-bottom: 1rem;
.info {
@include font-size(1.4rem);
display: flex;
flex-direction: column;
border: none;
&:hover {
background: unset;
}
.name {
color: var(--default-color);
font-weight: 500;
}
.bio {
color: var(--black-400);
}
}
.actions {
margin-left: auto;
padding-left: 1rem;
}
}

View File

@ -0,0 +1,92 @@
import { clsx } from 'clsx'
import styles from './AuthorBadge.module.scss'
import { Userpic } from '../Userpic'
import { Author, FollowingEntity } from '../../../graphql/types.gen'
import { createMemo, createSignal, Show } from 'solid-js'
import { formatDate } from '../../../utils'
import { useLocalize } from '../../../context/localize'
import { Button } from '../../_shared/Button'
import { useSession } from '../../../context/session'
import { follow, unfollow } from '../../../stores/zine/common'
import { CheckButton } from '../../_shared/CheckButton'
type Props = {
author: Author
minimizeSubscribeButton?: boolean
}
export const AuthorBadge = (props: Props) => {
const [isSubscribing, setIsSubscribing] = createSignal(false)
const {
isAuthenticated,
session,
actions: { loadSession }
} = useSession()
const { t } = useLocalize()
const subscribed = createMemo<boolean>(() => {
return session()?.news?.authors?.some((u) => u === props.author.slug) || false
})
const subscribe = async (really = true) => {
setIsSubscribing(true)
await (really
? follow({ what: FollowingEntity.Author, slug: props.author.slug })
: unfollow({ what: FollowingEntity.Author, slug: props.author.slug }))
await loadSession()
setIsSubscribing(false)
}
return (
<div class={clsx(styles.AuthorBadge)}>
<Userpic hasLink={true} isMedium={true} name={props.author.name} userpic={props.author.userpic} />
<a href={`/author/${props.author.slug}`} class={styles.info}>
<div class={styles.name}>{props.author.name}</div>
<Show
when={props.author.bio}
fallback={
<div class={styles.bio}>
{t('Registered since {{date}}', { date: formatDate(new Date(props.author.createdAt)) })}
</div>
}
>
<div class={clsx('text-truncate', styles.bio)}>{props.author.bio}</div>
</Show>
</a>
<Show when={isAuthenticated() && props.author.slug !== session().user.slug}>
<div class={styles.actions}>
<Show
when={!props.minimizeSubscribeButton}
fallback={
<CheckButton
text={t('Follow')}
checked={subscribed()}
onClick={() => subscribe(!subscribed)}
/>
}
>
<Show
when={subscribed()}
fallback={
<Button
variant="primary"
size="S"
value={isSubscribing() ? t('...subscribing') : t('Subscribe')}
onClick={() => subscribe(true)}
/>
}
>
<Button
onClick={() => subscribe(false)}
variant="secondary"
size="S"
value={t('You are subscribed')}
/>
</Show>
</Show>
</div>
</Show>
</div>
)
}

View File

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

View File

@ -1,6 +1,6 @@
.author {
align-items: center;
display: flex;
align-items: center;
flex-flow: row nowrap;
margin-bottom: 1.6rem;
@ -600,8 +600,10 @@
align-items: center;
margin-bottom: 0.4rem;
.authorName {
.authorName,
.authorAbout {
@include font-size(1.2rem);
margin-bottom: 0;
}

View File

@ -15,11 +15,11 @@ import { useLocalize } from '../../../context/localize'
import { ConditionalWrapper } from '../../_shared/ConditionalWrapper'
import { Modal } from '../../Nav/Modal'
import { showModal } from '../../../stores/ui'
import { TopicCard } from '../../Topic/Card'
import { getNumeralsDeclension } from '../../../utils/getNumeralsDeclension'
import { SubscriptionFilter } from '../../../pages/types'
import { isAuthor } from '../../../utils/isAuthor'
import { CheckButton } from '../../_shared/CheckButton'
import { AuthorBadge } from '../AuthorBadge'
import { TopicBadge } from '../../Topic/TopicBadge'
type Props = {
caption?: string
@ -42,7 +42,6 @@ type Props = {
followers?: Author[]
following?: Array<Author | Topic>
showPublicationsCounter?: boolean
minimizeSubscribeButton?: boolean
}
export const AuthorCard = (props: Props) => {
@ -285,7 +284,7 @@ export const AuthorCard = (props: Props) => {
</For>
</div>
</Show>
<Show when={!props.minimizeSubscribeButton}>
<Show
when={subscribed()}
fallback={
@ -349,14 +348,6 @@ export const AuthorCard = (props: Props) => {
</Show>
</button>
</Show>
</Show>
<Show when={props.minimizeSubscribeButton}>
<CheckButton
text={t('Follow')}
checked={subscribed()}
onClick={() => subscribe(false)}
/>
</Show>
<Show when={!props.hideWriteButton}>
<button
@ -390,17 +381,7 @@ export const AuthorCard = (props: Props) => {
<div class="row">
<div class="col-24">
<For each={props.followers}>
{(follower: Author) => (
<AuthorCard
author={follower}
hideWriteButton={true}
hasLink={true}
isTextButton={true}
liteButtons={true}
truncateBio={true}
showPublicationsCounter={true}
/>
)}
{(follower: Author) => <AuthorBadge author={follower} />}
</For>
</div>
</div>
@ -444,23 +425,9 @@ export const AuthorCard = (props: Props) => {
<For each={following()}>
{(subscription) =>
isAuthor(subscription) ? (
<AuthorCard
author={subscription}
hideWriteButton={true}
hasLink={true}
isTextButton={true}
truncateBio={true}
showPublicationsCounter={true}
/>
<AuthorBadge author={subscription} />
) : (
<TopicCard
compact
isTopicInRow
showDescription
isCardMode
withIcon
topic={subscription}
/>
<TopicBadge topic={subscription} />
)
}
</For>

View File

@ -3,14 +3,14 @@
background: #f7f7f8;
border-radius: 100%;
display: flex;
height: 32px;
justify-content: center;
margin-right: 1.2rem;
min-width: 32px;
max-width: 32px;
height: 32px;
width: 32px;
overflow: hidden;
position: relative;
width: 32px;
img {
height: 100%;
@ -55,6 +55,17 @@
}
}
&.medium {
width: 40px;
height: 40px;
min-width: 40px;
max-width: 40px;
.letters {
line-height: 40px;
}
}
&.big {
aspect-ratio: 1/1;
margin: 0 auto;

View File

@ -13,8 +13,8 @@ type Props = {
onClick?: () => void
loading?: boolean
isBig?: boolean
isMedium?: boolean
hasLink?: boolean
isAuthorsList?: boolean
isFeedMode?: boolean
}
@ -30,6 +30,7 @@ export const Userpic = (props: Props) => {
<div
class={clsx(styles.Userpic, props.class, {
[styles.big]: props.isBig,
[styles.medium]: props.isMedium,
[styles.authorsList]: props.isAuthorsList,
[styles.feedMode]: props.isFeedMode,
['cursorPointer']: props.onClick

View File

@ -167,7 +167,6 @@ export const ArticleCard = (props: ArticleCardProps) => {
</Show>
</a>
</div>
<Show when={!props.settings?.noauthor || !props.settings?.nodate}>
<div
class={clsx(styles.shoutDetails, { [styles.shoutDetailsFeedMode]: props.settings?.isFeedMode })}
@ -181,6 +180,7 @@ export const ArticleCard = (props: ArticleCardProps) => {
author={author}
hideWriteButton={true}
hideFollow={true}
truncateBio={true}
isFeedMode={true}
hasLink={!props.settings?.noAuthorLink}
/>

View File

@ -2,16 +2,15 @@
import { For, Show } from 'solid-js'
import { ArticleCard } from './ArticleCard'
import { AuthorCard } from '../Author/AuthorCard'
import { TopicCard } from '../Topic/Card'
import styles from './Beside.module.scss'
import type { Author, Shout, Topic, User } from '../../graphql/types.gen'
import { Icon } from '../_shared/Icon'
import { clsx } from 'clsx'
import { useLocalize } from '../../context/localize'
import { AuthorBadge } from '../Author/AuthorBadge'
interface BesideProps {
type Props = {
title?: string
values: (Shout | User | Topic | Author)[]
beside: Shout
@ -24,7 +23,7 @@ interface BesideProps {
nodate?: boolean
}
export const Beside = (props: BesideProps) => {
export const Beside = (props: Props) => {
const { t } = useLocalize()
return (
<Show when={!!props.beside?.slug && props.values?.length > 0}>
@ -76,14 +75,7 @@ export const Beside = (props: BesideProps) => {
/>
</Show>
<Show when={props.wrapper === 'author'}>
<AuthorCard
author={value as Author}
hideWriteButton={true}
hasLink={true}
truncateBio={true}
isTextButton={true}
class={styles.author}
/>
<AuthorBadge author={value as Author} />
</Show>
<Show when={props.wrapper === 'article' && value?.slug}>
<ArticleCard

View File

@ -46,7 +46,7 @@ export const Header = (props: Props) => {
actions: { requireAuthentication }
} = useSession()
const { page, searchParams } = useRouter<HeaderSearchParams>()
const { searchParams } = useRouter<HeaderSearchParams>()
const [randomTopics, setRandomTopics] = createSignal([])
const [getIsScrollingBottom, setIsScrollingBottom] = createSignal(false)

View File

@ -0,0 +1,60 @@
.TopicBadge {
display: flex;
flex-direction: row;
align-items: flex-start;
gap: 1rem;
margin-bottom: 1rem;
.picture {
display: block;
width: 40px;
height: 40px;
min-width: 40px;
border-radius: 8px;
background-color: var(--black-50);
background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE5LjUgMTQuMjVDMTkuOTE0MSAxNC4yNSAyMC4yNSAxNC41ODU5IDIwLjI1IDE1QzIwLjI1IDE1LjQxNDEgMTkuOTE0MSAxNS43NSAxOS41IDE1Ljc1SDE1Ljc1VjE5LjVDMTUuNzUgMTkuOTE0MSAxNS40MTQxIDIwLjI1IDE1IDIwLjI1QzE0LjU4NTkgMjAuMjUgMTQuMjUgMTkuOTE0MSAxNC4yNSAxOS41VjE1Ljc1SDkuNzVWMTkuNUM5Ljc1IDE5LjkxNDEgOS40MTQwNiAyMC4yNSA5IDIwLjI1QzguNTg1OTQgMjAuMjUgOC4yNSAxOS45MTQxIDguMjUgMTkuNVYxNS43NUg0LjVDNC4wODU5NCAxNS43NSAzLjc1IDE1LjQxNDEgMy43NSAxNUMzLjc1IDE0LjU4NTkgNC4wODU5NCAxNC4yNSA0LjUgMTQuMjVIOC4yNVY5Ljc1SDQuNUM0LjA4NTk0IDkuNzUgMy43NSA5LjQxNDA2IDMuNzUgOUMzLjc1IDguNTg1OTQgNC4wODU5NCA4LjI1IDQuNSA4LjI1SDguMjVWNC41QzguMjUgNC4wODU5NCA4LjU4NTk0IDMuNzUgOSAzLjc1QzkuNDE0MDYgMy43NSA5Ljc1IDQuMDg1OTQgOS43NSA0LjVWOC4yNUgxNC4yNVY0LjVDMTQuMjUgNC4wODU5NCAxNC41ODU5IDMuNzUgMTUgMy43NUMxNS40MTQxIDMuNzUgMTUuNzUgNC4wODU5NCAxNS43NSA0LjVWOC4yNUgxOS41QzE5LjkxNDEgOC4yNSAyMC4yNSA4LjU4NTk0IDIwLjI1IDlDMjAuMjUgOS40MTQwNiAxOS45MTQxIDkuNzUgMTkuNSA5Ljc1SDE1Ljc1VjE0LjI1SDE5LjVaTTkuNzUgMTQuMjVIMTQuMjVWOS43NUg5Ljc1VjE0LjI1WiIgZmlsbD0iIzlGQTFBNyIvPgo8L3N2Zz4K');
background-position: 50% 50%;
background-repeat: no-repeat;
border: none;
&:hover {
background-color: var(--black-50);
}
&.withImage {
background-size: cover;
}
}
.info {
display: flex;
flex-direction: column;
border: none;
@include font-size(1.4rem);
&:hover {
background: unset;
}
.title {
color: var(--blue-500);
font-weight: 700;
}
.description {
color: var(--black-400);
}
.stat {
display: flex;
gap: 1rem;
flex-direction: row;
color: var(--default-color);
}
}
.actions {
margin-left: auto;
padding-left: 1rem;
}
}

View File

@ -0,0 +1,111 @@
import { clsx } from 'clsx'
import styles from './TopicBadge.module.scss'
import { FollowingEntity, Topic } from '../../../graphql/types.gen'
import { createMemo, createSignal, Show } from 'solid-js'
import { imageProxy } from '../../../utils/imageProxy'
import { capitalize } from '../../../utils'
import { Button } from '../../_shared/Button'
import { useSession } from '../../../context/session'
import { useLocalize } from '../../../context/localize'
import { follow, unfollow } from '../../../stores/zine/common'
import { CheckButton } from '../../_shared/CheckButton'
type Props = {
topic: Topic
minimizeSubscribeButton?: boolean
}
export const TopicBadge = (props: Props) => {
const [isSubscribing, setIsSubscribing] = createSignal(false)
const { t } = useLocalize()
const {
isAuthenticated,
session,
actions: { loadSession }
} = useSession()
const subscribed = createMemo(() => {
if (!session()?.user?.slug || !session()?.news?.topics) {
return false
}
return session()?.news.topics.includes(props.topic.slug)
})
const subscribe = async (really = true) => {
setIsSubscribing(true)
await (really
? follow({ what: FollowingEntity.Topic, slug: props.topic.slug })
: unfollow({ what: FollowingEntity.Topic, slug: props.topic.slug }))
await loadSession()
setIsSubscribing(false)
}
return (
<div class={styles.TopicBadge}>
<a
href={`/topic/${props.topic.slug}`}
class={clsx(styles.picture, { [styles.withImage]: props.topic.pic })}
style={props.topic.pic && { 'background-image': `url('${imageProxy(props.topic.pic)}')` }}
/>
<a href={`/topic/${props.topic.slug}`} class={styles.info}>
<span class={styles.title}>{capitalize(props.topic.title)}</span>
<Show when={props.topic.body}>
<div class={clsx('text-truncate', styles.description)}>{props.topic.body}</div>
</Show>
<span class={styles.stat}>
<Show when={props.topic.stat.authors}>
<div>
{t('Authors')}: {props.topic.stat.authors}
</div>
</Show>
<Show when={props.topic.stat.followers}>
<div>
{t('Followers')}: {props.topic.stat.followers}
</div>
</Show>
<Show when={props.topic.stat.shouts}>
<div>
{t('Publications')}: {props.topic.stat.shouts}
</div>
</Show>
</span>
</a>
<Show when={isAuthenticated()}>
<div class={styles.actions}>
<Show
when={!props.minimizeSubscribeButton}
fallback={
<CheckButton
text={t('Follow')}
checked={subscribed()}
onClick={() => subscribe(!subscribed)}
/>
}
>
<Show
when={subscribed()}
fallback={
<Button
variant="primary"
size="S"
value={isSubscribing() ? t('...subscribing') : t('Subscribe')}
onClick={() => subscribe(true)}
/>
}
>
<Button
onClick={() => subscribe(false)}
variant="secondary"
size="S"
value={t('You are subscribed')}
/>
</Show>
</Show>
</div>
</Show>
</div>
)
}

View File

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

View File

@ -1,4 +1,4 @@
import { Accessor, createEffect, createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
import { Accessor, createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
import { useLocalize } from '../../context/localize'
import { clsx } from 'clsx'
import { Title } from '@solidjs/meta'

View File

@ -1,12 +1,9 @@
import { clsx } from 'clsx'
// import styles from './ProfileSubscriptions.module.scss'
import { ProfileSettingsNavigation } from '../../Nav/ProfileSettingsNavigation'
import { createEffect, createSignal, For, onMount, Show } from 'solid-js'
import { Loading } from '../../_shared/Loading'
import { SearchField } from '../../_shared/SearchField'
import { isAuthor } from '../../../utils/isAuthor'
import { AuthorCard } from '../../Author/AuthorCard'
import { TopicCard } from '../../Topic/Card'
import { useLocalize } from '../../../context/localize'
import { useSession } from '../../../context/session'
import { Author, Topic } from '../../../graphql/types.gen'
@ -16,6 +13,8 @@ import { dummyFilter } from '../../../utils/dummyFilter'
// TODO: refactor styles
import styles from '../../../pages/profile/Settings.module.scss'
import stylesSettings from '../../../styles/FeedSettings.module.scss'
import { AuthorBadge } from '../../Author/AuthorBadge'
import { TopicBadge } from '../../Topic/TopicBadge'
export const ProfileSubscriptions = () => {
const { t, lang } = useLocalize()
@ -104,23 +103,9 @@ export const ProfileSubscriptions = () => {
{(followingItem) => (
<div>
{isAuthor(followingItem) ? (
<AuthorCard
author={followingItem}
hideWriteButton={true}
hasLink={true}
isTextButton={true}
truncateBio={true}
minimizeSubscribeButton={true}
/>
<AuthorBadge minimizeSubscribeButton={true} author={followingItem} />
) : (
<TopicCard
compact
isTopicInRow
showDescription
isCardMode
topic={followingItem}
minimizeSubscribeButton={true}
/>
<TopicBadge minimizeSubscribeButton={true} topic={followingItem} />
)}
</div>
)}

View File

@ -5,6 +5,7 @@
justify-content: center;
font-weight: 500;
cursor: pointer;
white-space: nowrap;
&.primary {
background: #000;
@ -57,7 +58,10 @@
margin-right: 0.8em;
min-width: auto !important;
padding: 0;
transition: border-color 0.3s, background-color 0.3s, color 0.3s;
transition:
border-color 0.3s,
background-color 0.3s,
color 0.3s;
&:hover,
&:active {

View File

@ -4,6 +4,7 @@
justify-content: center;
height: 32px;
min-width: 33px;
line-height: 32px;
box-sizing: border-box;
padding: 0 8px;
background: var(--background-color);

View File

@ -30,6 +30,8 @@ export default gql`
name
slug
userpic
createdAt
bio
}
createdAt
publishedAt

View File

@ -25,6 +25,7 @@ export type Author = {
about?: Maybe<Scalars['String']>
bio?: Maybe<Scalars['String']>
caption?: Maybe<Scalars['String']>
createdAt?: Maybe<Scalars['DateTime']>
id: Scalars['Int']
lastSeen?: Maybe<Scalars['DateTime']>
links?: Maybe<Array<Maybe<Scalars['String']>>>
@ -116,6 +117,7 @@ export type LoadShoutsFilters = {
author?: InputMaybe<Scalars['String']>
body?: InputMaybe<Scalars['String']>
days?: InputMaybe<Scalars['Int']>
excludeLayout?: InputMaybe<Scalars['String']>
layout?: InputMaybe<Scalars['String']>
reacted?: InputMaybe<Scalars['Boolean']>
title?: InputMaybe<Scalars['String']>
@ -589,20 +591,6 @@ export type ShoutInput = {
topics?: InputMaybe<Array<InputMaybe<TopicInput>>>
}
export type ShoutsFilterBy = {
author?: InputMaybe<Scalars['String']>
authors?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
body?: InputMaybe<Scalars['String']>
days?: InputMaybe<Scalars['Int']>
layout?: InputMaybe<Scalars['String']>
slug?: InputMaybe<Scalars['String']>
stat?: InputMaybe<Scalars['String']>
title?: InputMaybe<Scalars['String']>
topic?: InputMaybe<Scalars['String']>
topics?: InputMaybe<Array<InputMaybe<Scalars['String']>>>
visibility?: InputMaybe<Scalars['String']>
}
export type Stat = {
commented?: Maybe<Scalars['Int']>
ranking?: Maybe<Scalars['Int']>

View File

@ -177,7 +177,7 @@ export const ProfileSettingsPage = () => {
value={(value) => updateFormField('bio', value)}
initialValue={form.bio}
allowEnterKey={false}
maxLength={80}
maxLength={120}
/>
<h4>{t('About myself')}</h4>

View File

@ -31,9 +31,11 @@
// names from figma
--black-50: #f7f7f8;
--black-100: #e9e9ee;
--black-300: #9fa1a7;
--black-500: #141414;
--black-400: #696969;
--white-500: #fff;
--blue-500: #2638d9;
}
[data-editor-dark-mode='true'] {