diff --git a/public/icons/arrow-right-2.svg b/public/icons/arrow-right-2.svg new file mode 100644 index 00000000..2b4a95b3 --- /dev/null +++ b/public/icons/arrow-right-2.svg @@ -0,0 +1,5 @@ + + + + diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index aab672da..09e06239 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -55,6 +55,7 @@ "Be the first to rate": "Be the first to rate", "Become an author": "Become an author", "bold": "bold", + "Block rules": "За что можно получить бан", "Bold": "Bold", "Bookmarked": "Saved", "bookmarks": "bookmarks", @@ -98,6 +99,7 @@ "Commenting": "Commenting", "Comments": "Comments", "CommentsWithCount": "{count, plural, =0 {{count} comments} one {{count} comment} few {{count} comments} other {{count} comments}}", + "Common feed": "All", "Communities": "Communities", "community": "community", "Community Discussion Rules": "Community Discussion Rules", @@ -125,6 +127,7 @@ "Create post": "Create post", "Create video": "Create video", "Crop image": "Crop image", + "Current discussions": "Актуальные дискуссии", "Culture": "Culture", "Current password": "Current password", "Date of Birth": "Date of Birth", @@ -180,6 +183,8 @@ "Feed settings": "Feed settings", "Feedback": "Feedback", "Fill email": "Fill email", + "Find co-authors": "Найти соавторов", + "Find collaborators": "Найдите соавторов и экспертов", "Fixed": "Fixed", "Follow": "Follow", "Follow the topic": "Follow the topic", @@ -197,6 +202,7 @@ "Gallery name": "Gallery name", "Get to know the most intelligent people of our time, edit and discuss the articles, share your expertise, rate and decide what to publish in the magazine": "Get to know the most intelligent people of our time, edit and discuss the articles, share your expertise, rate and decide what to publish in the magazine", "Go to main page": "Go to main page", + "Go to discussions": "Перейти к обсуждениям", "Group Chat": "Group Chat", "Groups": "Groups", "header 1": "header 1", @@ -254,10 +260,15 @@ "Italic": "Italic", "Join": "Join", "Join our maillist": "To receive the best postings, just enter your email", + "Join our team of authors": "Join our team of authors", + "Join our team of authors text": "Каждый месяц на Дискурсе публикуются десятки новых авторов. Станьте одним из них — предложите свой материал в журнал и присоединитесь к горизонтальной редакции", "Join the community": "Join the community", "Join the global community of authors!": "Join the global community of authors from all over the world!", "journal": "journal", "jpg, .png, max. 10 mb.": "jpg, .png, макс. 10 мб.", + "Join": "Join", + "Join discussions": "Присоединяйтесь к дискуссиям", + "Join discussions text": "Дискурс — свободная платформа для осмысленного общения.
Здесь появятся ваши реплики, чтобы в любой момент вернуться к диалогу.", "Just start typing...": "Just start typing...", "keywords": "Discours.io, Discours magazine, Discours, culture, science, art, society, independent journalism, literature, music, cinema, video, photography", "Knowledge base": "Knowledge base", @@ -313,6 +324,7 @@ "Our regular contributor": "Our regular contributor", "Paragraphs": "Абзацев", "Participate in the Discours: share information, join the editorial team": "Участвуйте в Дискурсе: делитесь информацией, присоединяйтесь к редакции", + "Participate in discussions": "Участвуйте в дискуссиях", "Participating": "Participating", "Participation": "Participation", "Partners": "Partners", @@ -327,6 +339,9 @@ "Personal": "Personal", "personal data usage and email notifications": "to process personal data and receive email notifications", "Pin": "Pin", + "Placeholder feed": "Подпишитесь на любимые темы, авторов и сообщества — моментально узнавайте о новых публикациях и обсуждениях", + "Placeholder feedCollaborations": "На платформе можно писать материалы вместе. Здесь появятся публикации, в которые вы внесли вклад", + "Placeholder feedDiscussions": "Дискурс — свободная платформа для осмысленного общения. Здесь появятся все ваши реплики, чтобы в любой момент вернуться к диалогу", "Platform Guide": "Platform Guide", "Please check your email address": "Please check your email address", "Please confirm your email to finish": "Confirm your email and the action will complete", diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 412d2782..abae2819 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -35,6 +35,7 @@ "All posts rating": "Рейтинг всех постов", "all topics": "все темы", "All topics": "Все темы", + "All": "Все", "Almost done! Check your email.": "Почти готово! Осталось подтвердить вашу почту.", "and some more authors": "{restUsersCount, plural, =0 {} one { и ещё 1 пользователя} few { и ещё {restUsersCount} пользователей} other { и ещё {restUsersCount} пользователей}}", "Are you sure you want to delete this comment?": "Уверены, что хотите удалить этот комментарий?", @@ -59,6 +60,7 @@ "Be the first to rate": "Оцените первым", "Become an author": "Стать автором", "bold": "жирный", + "Block rules": "За что можно получить бан", "Bold": "Жирный", "Bookmarked": "Сохранено", "bookmarks": "закладки", @@ -103,6 +105,7 @@ "Commenting": "Комментирование", "Comments": "Комментарии", "CommentsWithCount": "{count, plural, =0 {{count} комментариев} one {{count} комментарий} few {{count} комментария} other {{count} комментариев}}", + "Common feed": "Общая лента", "Communities": "Сообщества", "community": "сообщество", "Community Discussion Rules": "Правила дискуссий в сообществе", @@ -126,14 +129,14 @@ "Create an account to vote": "Создайте аккаунт, чтобы голосовать", "Create Chat": "Создать чат", "Create gallery": "Создать галерею", - "Create Group": "Создать группу", + "Create own feed": "Создать свою ленту", "Create post": "Создать публикацию", "Create video": "Создать видео", "create_chat": "Создать чат", "create_group": "Создать группу", "Crop image": "Кадрировать изображение", "Culture": "Культура", - "Current password": "Текущий пароль", + "Current discussions": "Актуальные дискуссии", "Date of Birth": "Дата рождения", "Decline": "Отмена", "Delete": "Удалить", @@ -188,6 +191,8 @@ "Feed settings": "Настроить ленту", "Feedback": "Обратная связь", "Fill email": "Введите почту", + "Find co-authors": "Найти соавторов", + "Find collaborators": "Найдите соавторов и экспертов", "Fixed": "Все поправлено", "Follow": "Подписаться", "Follow the topic": "Подписаться на тему", @@ -207,6 +212,7 @@ "Get notifications": "Получать уведомления", "Get to know the most intelligent people of our time, edit and discuss the articles, share your expertise, rate and decide what to publish in the magazine": "Познакомитесь с выдающимися людьми нашего времени, участвуйте в редактировании и обсуждении статей, выступайте экспертом, оценивайте материалы других авторов со всего мира и определяйте, какие статьи будут опубликованы в журнале", "Go to main page": "Перейти на главную", + "Go to discussions": "Перейти к обсуждениям", "Group Chat": "Общий чат", "Groups": "Группы", "Header": "Заголовок", @@ -266,8 +272,13 @@ "Italic": "Курсив", "Join": "Присоединиться", "Join our maillist": "Чтобы получать рассылку лучших публикаций, просто укажите свою почту", + "Join our team of authors": "Станьте автором", + "Join our team of authors text": "Каждый месяц на Дискурсе публикуются десятки новых авторов.
Станьте одним из них — предложите свой материал в журнал и присоединитесь к горизонтальной редакции", "Join the community": "Присоединиться к сообществу", "Join the global community of authors!": "Присоединятесь к глобальному сообществу авторов со всего мира!", + "Join": "Присоединиться", + "Join discussions": "Присоединяйтесь к дискуссиям", + "Join discussions text": "Дискурс — свободная платформа для осмысленного общения.
Здесь появятся ваши реплики, чтобы в любой момент вернуться к диалогу.", "journal": "журнал", "jpg, .png, max. 10 mb.": "jpg, .png, макс. 10 мб.", "Just start typing...": "Просто начните печатать...", @@ -328,6 +339,7 @@ "Our regular contributor": "Наш постоянный автор", "Paragraphs": "Абзацев", "Participate in the Discours: share information, join the editorial team": "Participate in the Discours: share information, join the editorial team", + "Participate in discussions": "Участвуйте в дискуссиях", "Participating": "Участвовать", "Participation": "Соучастие", "Partners": "Партнёры", @@ -342,6 +354,9 @@ "Personal": "Личные", "personal data usage and email notifications": "на обработку персональных данных и на получение почтовых уведомлений", "Pin": "Закрепить", + "Placeholder feed": "Подпишитесь на любимые темы, авторов и сообщества — моментально узнавайте о новых публикациях и обсуждениях", + "Placeholder feedCollaborations": "На платформе можно писать материалы вместе. Здесь появятся публикации, в которые вы внесли вклад", + "Placeholder feedDiscussions": "Дискурс — свободная платформа для осмысленного общения. Здесь появятся все ваши реплики, чтобы в любой момент вернуться к диалогу", "Platform Guide": "Гид по дискурсу", "Please check your email address": "Пожалуйста, проверьте введенный адрес почты", "Please check your inbox! We have sent a password reset link.": "Пожалуйста, проверьте свою почту, мы отправили вам письмо со ссылкой для сброса пароля", diff --git a/public/placeholder-discussions.webp b/public/placeholder-discussions.webp new file mode 100644 index 00000000..a653abed Binary files /dev/null and b/public/placeholder-discussions.webp differ diff --git a/public/placeholder-experts.webp b/public/placeholder-experts.webp new file mode 100644 index 00000000..a40021b2 Binary files /dev/null and b/public/placeholder-experts.webp differ diff --git a/public/placeholder-feed.webp b/public/placeholder-feed.webp new file mode 100644 index 00000000..9d002486 Binary files /dev/null and b/public/placeholder-feed.webp differ diff --git a/public/placeholder-join.webp b/public/placeholder-join.webp new file mode 100644 index 00000000..887c55cf Binary files /dev/null and b/public/placeholder-join.webp differ diff --git a/src/components/Author/AuthorCard/AuthorCard.module.scss b/src/components/Author/AuthorCard/AuthorCard.module.scss index 5cc5cc17..a8e7e0e9 100644 --- a/src/components/Author/AuthorCard/AuthorCard.module.scss +++ b/src/components/Author/AuthorCard/AuthorCard.module.scss @@ -18,9 +18,8 @@ .authorName { @include font-size(4rem); - font-weight: 700; - margin-bottom: 0.2em; + margin-bottom: 1.2rem; } .authorAbout { @@ -429,64 +428,19 @@ } } -.followersContainer { +.listWrapper { + max-height: 70vh; +} + +.subscribersContainer { display: flex; flex-wrap: wrap; font-size: 1.4rem; - margin-top: 1.5rem; + gap: 1rem; + margin-top: 0; + white-space: nowrap; @include media-breakpoint-down(md) { justify-content: center; } } - -.followers { - align-items: center; - cursor: pointer; - display: inline-flex; - margin: 0 2% 1rem; - vertical-align: top; - border-bottom: unset !important; - - &:first-child { - margin-left: 0; - } - - &:last-child { - margin-right: 0; - } - - .followersItem { - position: relative; - - &:nth-child(1) { - z-index: 2; - } - - &:nth-child(2) { - z-index: 1; - } - - &:not(:last-child) { - margin-right: -4px; - box-shadow: 0 0 0 1px var(--background-color); - } - } - - .followsCounter { - font-weight: 500; - margin-left: 1rem; - } - - &:hover { - background: none !important; - - .followsCounter { - background: var(--background-color-invert); - } - } -} - -.listWrapper { - max-height: 70vh; -} \ No newline at end of file diff --git a/src/components/Author/AuthorCard/AuthorCard.tsx b/src/components/Author/AuthorCard/AuthorCard.tsx index 61a50537..f288eb5e 100644 --- a/src/components/Author/AuthorCard/AuthorCard.tsx +++ b/src/components/Author/AuthorCard/AuthorCard.tsx @@ -18,6 +18,7 @@ import { Modal } from '../../Nav/Modal' import { TopicBadge } from '../../Topic/TopicBadge' import { Button } from '../../_shared/Button' import { ShowOnlyOnClient } from '../../_shared/ShowOnlyOnClient' +import { Subscribers } from '../../_shared/Subscribers' import { AuthorBadge } from '../AuthorBadge' import { Userpic } from '../Userpic' @@ -192,61 +193,14 @@ export const AuthorCard = (props: Props) => {
- 0 || props.flatFollows?.length > 0}> - diff --git a/src/components/Feed/Placeholder/Placeholder.module.scss b/src/components/Feed/Placeholder/Placeholder.module.scss new file mode 100644 index 00000000..abd61262 --- /dev/null +++ b/src/components/Feed/Placeholder/Placeholder.module.scss @@ -0,0 +1,213 @@ +.placeholder { + border-radius: 2.2rem; + display: flex; + @include font-size(1.4rem); + font-weight: 500; + overflow: hidden; + position: relative; + + h3 { + @include font-size(2.4rem); + } + + button, + .button { + align-items: center; + border-radius: 1.2rem; + display: flex; + @include font-size(1.5rem); + gap: 0.6rem; + margin-top: 3rem; + padding: 1rem 2rem; + width: 100%; + + .icon { + height: 2.4rem; + width: 2.4rem; + } + } +} + +.placeholder--feed-mode { + aspect-ratio: 1 / 0.8; + flex-direction: column; + text-align: center; + + &:after { + bottom: 0; + content: ''; + height: 20%; + left: 0; + position: absolute; + width: 100%; + + .placeholder--feed & { + background: linear-gradient(to top, #171032, rgba(23, 16, 50, 0)); + } + + .placeholder--feedCollaborations & { + background: linear-gradient(to top, #070709, rgba(7, 7, 9, 0)); + } + } + + .placeholderCover { + flex: 0 100%; + width: 100%; + + img { + position: absolute; + } + } +} + +.placeholder--profile-mode { + min-height: 28rem; + + .placeholderCover { + flex: 0 45rem; + min-width: 45rem; + order: 2; + padding: 1.6rem; + + img { + height: auto; + width: 100%; + } + } + + .placeholderContent { + display: flex; + flex-direction: column; + justify-content: space-between; + @include font-size(2rem); + line-height: 1.2; + padding: 3rem; + } + + h3 { + @include font-size(3.8rem); + } + + .button { + background: var(--background-color-invert); + color: var(--default-color-invert); + bottom: 2rem; + position: absolute; + right: 2rem; + width: auto; + + .icon { + filter: invert(1); + } + } +} + +.placeholderCover { + position: relative; + + img { + left: 0; + height: 100%; + object-fit: cover; + width: 100%; + } +} + +.placeholderContent { + padding: 1.6rem; +} + +.placeholder--feed, +.placeholder--feedCollaborations { + color: var(--default-color-invert); + + button, + .button { + background: var(--background-color); + color: var(--default-color); + } +} + +.placeholder--feed { + background: #171032; + + .placeholderCover { + img { + object-position: top; + } + } +} + +.placeholder--feedCollaborations { + background: #070709; + + .placeholderCover { + img { + object-position: bottom; + } + } +} + +.placeholder--feedDiscussions { + background: #E9E9EE; + + .placeholderCover { + padding: 2rem; + text-align: center; + + img { + height: 90%; + mix-blend-mode: multiply; + object-fit: contain; + top: 10%; + } + } + + button, + .button { + background: var(--background-color-invert); + color: var(--default-color-invert); + } +} + + +.placeholder--author { + background: #E58B72; +} + +.placeholder--authorComments { + background: #E9E9EE; + + .placeholderCover { + img { + mix-blend-mode: multiply; + } + } +} + +.bottomLinks { + display: flex; + @include font-size(1.6rem); + gap: 4rem; + + a { + border: none !important; + padding-left: 2.6rem; + position: relative; + + &:hover { + .icon { + filter: invert(0); + } + } + } + + .icon { + filter: invert(1); + height: 1.8rem; + left: 0; + position: absolute; + transition: filter 0.2s; + width: 1.8rem; + } +} diff --git a/src/components/Feed/Placeholder/Placeholder.tsx b/src/components/Feed/Placeholder/Placeholder.tsx new file mode 100644 index 00000000..94fa247a --- /dev/null +++ b/src/components/Feed/Placeholder/Placeholder.tsx @@ -0,0 +1,120 @@ +import { clsx } from 'clsx' +import { For, Show } from 'solid-js' + +import { useLocalize } from '../../../context/localize' +import { useSession } from '../../../context/session' +import { Icon } from '../../_shared/Icon' +import styles from './Placeholder.module.scss' + +export type PlaceholderProps = { + type: string + mode: 'feed' | 'profile' +} + +export const Placeholder = (props: PlaceholderProps) => { + const { t } = useLocalize() + const { author } = useSession() + + const data = { + feed: { + image: 'placeholder-feed.webp', + header: t('Feed settings'), + text: t('Placeholder feed'), + buttonLabel: author() ? t('Popular authors') : t('Create own feed'), + href: '/authors?by=followers', + }, + feedCollaborations: { + image: 'placeholder-experts.webp', + header: t('Find collaborators'), + text: t('Placeholder feedCollaborations'), + buttonLabel: t('Find co-authors'), + href: '/authors?by=name', + }, + feedDiscussions: { + image: 'placeholder-discussions.webp', + header: t('Participate in discussions'), + text: t('Placeholder feedDiscussions'), + buttonLabel: author() ? t('Current discussions') : t('Enter'), + href: '/feed?by=last_comment', + }, + author: { + image: 'placeholder-join.webp', + header: t('Join our team of authors'), + text: t('Join our team of authors text'), + buttonLabel: t('Create post'), + href: '/create', + profileLinks: [ + { + href: '/how-to-write-a-good-article', + label: t('How to write a good article'), + }, + ], + }, + authorComments: { + image: 'placeholder-discussions.webp', + header: t('Join discussions'), + text: t('Placeholder feedDiscussions'), + buttonLabel: t('Go to discussions'), + href: '/feed?by=last_comment', + profileLinks: [ + { + href: '/about/discussion-rules', + label: t('Discussion rules'), + }, + { + href: '/about/discussion-rules#ban', + label: t('Block rules'), + }, + ], + }, + } + + return ( +
+
+ +
+
+
+

+

+

+ + +
+ + {(link) => ( + + + {link.label} + + )} + +
+
+ + + {data[props.type].buttonLabel} + + } + > + + {data[props.type].buttonLabel} + + + + + +
+
+ ) +} diff --git a/src/components/Feed/Placeholder/index.ts b/src/components/Feed/Placeholder/index.ts new file mode 100644 index 00000000..20413aa5 --- /dev/null +++ b/src/components/Feed/Placeholder/index.ts @@ -0,0 +1 @@ +export { Placeholder } from './Placeholder' diff --git a/src/components/Feed/Sidebar/Sidebar.tsx b/src/components/Feed/Sidebar/Sidebar.tsx index 313dd0b6..c6f794d4 100644 --- a/src/components/Feed/Sidebar/Sidebar.tsx +++ b/src/components/Feed/Sidebar/Sidebar.tsx @@ -83,32 +83,6 @@ export const Sidebar = () => { -
  • - - - - {t('Bookmarks')} - - -
  • -
  • - - - - {t('Notifications')} - - -
  • 0 || follows?.topics?.length > 0}> diff --git a/src/components/Topic/Full.module.scss b/src/components/Topic/Full.module.scss index bfa1efbb..c34ea44e 100644 --- a/src/components/Topic/Full.module.scss +++ b/src/components/Topic/Full.module.scss @@ -1,6 +1,5 @@ .topicHeader { - @include font-size(1.7rem); - + font-weight: 500; padding: 2.8rem $container-padding-x 0; text-align: center; @@ -12,10 +11,16 @@ } } +.topicDescription { + @include font-size(1.8rem); + line-height: 1.4; + margin: 1rem 0 2rem; +} + .topicActions { margin-top: 2.8rem; - .write { + .writeControl { display: inline-flex; align-items: center; justify-content: center; @@ -23,13 +28,38 @@ min-width: 64px; font-size: 17px; padding: 8px 16px; - background: var(--background-color-invert); - color: var(--default-color-invert); - border: none; + border: 1px solid #f7f7f7; + background: #f7f7f7; + color: var(--default-color); font-weight: 500; - border-radius: 2px; cursor: pointer; margin: 0 1.2rem 1em; white-space: nowrap; } + + .followControl, + .writeControl { + border-radius: 0.8rem; + } +} + +.topicDetails { + align-items: flex-start; + display: flex; + flex-wrap: wrap; + font-size: 1.4rem; + justify-content: center; + gap: 1rem; + margin-top: 1.5rem; +} + +.topicDetailsItem { + align-items: center; + display: flex; + margin-right: 1rem; + white-space: nowrap; +} + +.topicDetailsIcon { + display: block; } diff --git a/src/components/Topic/Full.tsx b/src/components/Topic/Full.tsx index ec2c85f1..d0bf8cad 100644 --- a/src/components/Topic/Full.tsx +++ b/src/components/Topic/Full.tsx @@ -1,4 +1,4 @@ -import type { Topic } from '../../graphql/schema/core.gen' +import type { Author, Topic } from '../../graphql/schema/core.gen' import { clsx } from 'clsx' import { Show, createEffect, createSignal } from 'solid-js' @@ -9,10 +9,14 @@ import { useSession } from '../../context/session' import { FollowingEntity } from '../../graphql/schema/core.gen' import { Button } from '../_shared/Button' +import { Icon } from '../_shared/Icon' +import { Subscribers } from '../_shared/Subscribers' import styles from './Full.module.scss' type Props = { topic: Topic + followers?: Author[] + authors?: Author[] } export const FullTopic = (props: Props) => { @@ -39,19 +43,39 @@ export const FullTopic = (props: Props) => { return (

    #{props.topic?.title}

    -

    +

    + +

    + +
    + + {t('PublicationsWithCount', { + count: props.topic?.stat.shouts ?? 0, + })} +
    +
    + + +
    + - {props.topic?.title} + {props.topic?.title}
    ) diff --git a/src/components/Views/Author/Author.tsx b/src/components/Views/Author/Author.tsx index 4f3b3bc5..883a095b 100644 --- a/src/components/Views/Author/Author.tsx +++ b/src/components/Views/Author/Author.tsx @@ -27,6 +27,7 @@ import { Loading } from '../../_shared/Loading' import { MODALS, hideModal } from '../../../stores/ui' import { byCreated } from '../../../utils/sortby' import stylesArticle from '../../Article/Article.module.scss' +import { Placeholder } from '../../Feed/Placeholder' import styles from './Author.module.scss' type Props = { @@ -250,6 +251,10 @@ export const AuthorView = (props: Props) => {
    +
    + +
    +
    @@ -270,46 +275,56 @@ export const AuthorView = (props: Props) => {
    - - + +
    + +
    - - - + 0}> + + + - - - + + + - 3}> - - - - - - + + + - - {(page) => ( - <> - - - - - - - - )} - - + 3}> + + + + + + - -

    - -

    + + {(page) => ( + <> + + + + + + + + )} + +
    + + +

    + +

    +
    diff --git a/src/components/Views/Feed/Feed.module.scss b/src/components/Views/Feed/Feed.module.scss index 3cb18604..61e1c161 100644 --- a/src/components/Views/Feed/Feed.module.scss +++ b/src/components/Views/Feed/Feed.module.scss @@ -175,6 +175,7 @@ -webkit-line-clamp: 1; a { + border: none; color: rgb(0 0 0 / 65%); &:hover { diff --git a/src/components/Views/Feed/Feed.tsx b/src/components/Views/Feed/Feed.tsx index 96e98fa5..39a4b757 100644 --- a/src/components/Views/Feed/Feed.tsx +++ b/src/components/Views/Feed/Feed.tsx @@ -20,6 +20,7 @@ import { getShareUrl } from '../../Article/SharePopup' import { AuthorBadge } from '../../Author/AuthorBadge' import { AuthorLink } from '../../Author/AuthorLink' import { ArticleCard } from '../../Feed/ArticleCard' +import { Placeholder } from '../../Feed/Placeholder' import { Sidebar } from '../../Feed/Sidebar' import { Modal } from '../../Nav/Modal' import { DropDown } from '../../_shared/DropDown' @@ -100,7 +101,7 @@ export const FeedView = (props: Props) => { const { page, searchParams, changeSearchParams } = useRouter() const [isLoading, setIsLoading] = createSignal(false) const [isRightColumnLoaded, setIsRightColumnLoaded] = createSignal(false) - const { session } = useSession() + const { author, session } = useSession() const { loadReactionsBy } = useReactions() const { sortedArticles } = useArticlesStore() const { topTopics } = useTopics() @@ -238,107 +239,112 @@ export const FeedView = (props: Props) => {
    -
    -
      -
    • - {t('Recent')} -
    • - {/*
    • */} - {/* {t('Most read')}*/} - {/*
    • */} -
    • - changeSearchParams({ by: 'likes' })}> - {t('Top rated')} - -
    • -
    • - changeSearchParams({ by: 'last_comment' })}> - {t('Most commented')} - -
    • -
    -
    - + } + > +
    +
      +
    • + {t('Recent')} +
    • + {/*
    • */} + {/* {t('Most read')}*/} + {/*
    • */} +
    • + changeSearchParams({ by: 'likes' })}> + {t('Top rated')} + +
    • +
    • + changeSearchParams({ by: 'last_comment' })}> + {t('Most commented')} + +
    • +
    +
    + + changeSearchParams({ period: period.value })} + /> + changeSearchParams({ period: period.value })} + onChange={(visibility: VisibilityItem) => + changeSearchParams({ visibility: visibility.value }) + } /> - - - changeSearchParams({ visibility: visibility.value }) - } - /> +
    -
    - }> - 0}> - - {(article) => ( - handleShare(shared)} - onInvite={() => showModal('inviteMembers')} - article={article} - settings={{ isFeedMode: true }} - desktopCoverSize="M" - /> - )} - + }> + 0}> + + {(article) => ( + handleShare(shared)} + onInvite={() => showModal('inviteMembers')} + article={article} + settings={{ isFeedMode: true }} + desktopCoverSize="M" + /> + )} + -
    -
    -

    {t('Popular authors')}

    - - {t('All authors')} - - +
    +
    +

    {t('Popular authors')}

    + + {t('All authors')} + + +
    + +
      + + {(author) => ( +
    • + +
    • + )} +
      +
    -
      - - {(author) => ( -
    • - -
    • - )} -
      -
    -
    + + {(article) => ( + + )} + + - - {(article) => ( - - )} - - - - -

    - -

    + +

    + +

    +
    diff --git a/src/components/Views/Topic.tsx b/src/components/Views/Topic.tsx index 08f4f57f..7389b3a5 100644 --- a/src/components/Views/Topic.tsx +++ b/src/components/Views/Topic.tsx @@ -1,4 +1,4 @@ -import { LoadShoutsOptions, Shout, Topic } from '../../graphql/schema/core.gen' +import { Author, AuthorsBy, LoadShoutsOptions, Shout, Topic } from '../../graphql/schema/core.gen' import { clsx } from 'clsx' import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js' @@ -33,6 +33,7 @@ interface Props { topic: Topic shouts: Shout[] topicSlug: string + followers?: Author[] } export const PRERENDERED_ARTICLES_COUNT = 28 @@ -56,6 +57,11 @@ export const TopicView = (props: Props) => { setTopic(topics[props.topicSlug]) } }) + const [followers, setFollowers] = createSignal(props.followers || []) + const loadTopicFollowers = async () => { + const result = await apiClient.getTopicFollowers({ slug: props.topicSlug }) + setFollowers(result) + } const loadFavoriteTopArticles = async (topic: string) => { const options: LoadShoutsOptions = { @@ -81,13 +87,29 @@ export const TopicView = (props: Props) => { setReactedTopMonthArticles(result) } + const [topicAuthors, setTopicAuthors] = createSignal([]) + const loadTopicAuthors = async () => { + const by: AuthorsBy = { topic: props.topicSlug } + const result = await apiClient.loadAuthorsBy({ by }) + setTopicAuthors(result) + } const loadRandom = () => { loadFavoriteTopArticles(topic()?.slug) loadReactedTopMonthArticles(topic()?.slug) } - createEffect(on(topic, loadRandom, { defer: true })) + createEffect( + on( + () => topic()?.id, + (_) => { + loadTopicFollowers() + loadTopicAuthors() + loadRandom() + }, + { defer: true }, + ), + ) const title = createMemo( () => @@ -152,7 +174,7 @@ export const TopicView = (props: Props) => { - +
    diff --git a/src/components/_shared/Subscribers/Subscribers.module.scss b/src/components/_shared/Subscribers/Subscribers.module.scss new file mode 100644 index 00000000..84494bd3 --- /dev/null +++ b/src/components/_shared/Subscribers/Subscribers.module.scss @@ -0,0 +1,50 @@ +.subscribers { + align-items: center; + cursor: pointer; + display: inline-flex; + margin: 0 1rem 0 0; + vertical-align: top; + border-bottom: unset !important; + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + + .subscribersItem { + position: relative; + + &:nth-child(1) { + z-index: 2; + } + + &:nth-child(2) { + z-index: 1; + } + + &:not(:last-child) { + margin-right: -4px; + box-shadow: 0 0 0 1px var(--background-color); + } + } + + .subscribersCounter { + font-weight: 500; + } + + &:hover { + background: none !important; + + .subscribersCounter { + background: var(--background-color-invert); + } + } +} + +.subscribersList { + display: flex; + margin-right: 0.6rem; +} diff --git a/src/components/_shared/Subscribers/Subscribers.tsx b/src/components/_shared/Subscribers/Subscribers.tsx new file mode 100644 index 00000000..899f5565 --- /dev/null +++ b/src/components/_shared/Subscribers/Subscribers.tsx @@ -0,0 +1,67 @@ +import { For, Show } from 'solid-js' + +import { useLocalize } from '../../../context/localize' + +import { Author, Topic } from '../../../graphql/schema/core.gen' +import { Userpic } from '../../Author/Userpic' + +import styles from './Subscribers.module.scss' + +type Props = { + followers?: Author[] + followersAmount?: number + following?: Array + followingAmount?: number +} + +export const Subscribers = (props: Props) => { + const { t } = useLocalize() + + return ( + <> + + 0}> +
    + + {(f) => } + +
    +
    +
    + {t('SubscriberWithCount', { + count: props.followersAmount || props.followers.length || 0, + })} +
    +
    + + + 0}> +
    + + {(f) => { + if ('name' in f) { + return ( + + ) + } + + if ('title' in f) { + return ( + + ) + } + + return null + }} + +
    +
    +
    + {t('SubscriptionWithCount', { + count: props.followingAmount || props.following?.length || 0, + })} +
    +
    + + ) +} diff --git a/src/components/_shared/Subscribers/index.ts b/src/components/_shared/Subscribers/index.ts new file mode 100644 index 00000000..cfa0eef9 --- /dev/null +++ b/src/components/_shared/Subscribers/index.ts @@ -0,0 +1 @@ +export { Subscribers } from './Subscribers' diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index bbfa00f4..cb9f4719 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -5,6 +5,7 @@ import type { LoadShoutsOptions, MutationDelete_ShoutArgs, ProfileInput, + QueryGet_Topic_FollowersArgs, QueryLoad_Authors_ByArgs, QueryLoad_Shouts_Random_TopArgs, QueryLoad_Shouts_SearchArgs, @@ -44,6 +45,7 @@ import authorsAll from '../query/core/authors-all' import authorsLoadBy from '../query/core/authors-load-by' import reactionsLoadBy from '../query/core/reactions-load-by' import topicBySlug from '../query/core/topic-by-slug' +import topicFollowers from '../query/core/topic-followers' import topicsAll from '../query/core/topics-all' import topicsRandomQuery from '../query/core/topics-random' @@ -129,6 +131,11 @@ export const apiClient = { return response.data.get_author_followers }, + getTopicFollowers: async ({ slug }: QueryGet_Topic_FollowersArgs): Promise => { + const response = await publicGraphQLClient.query(topicFollowers, { slug }).toPromise() + return response.data.get_topic_followers + }, + getAuthorFollows: async (params: { slug?: string author_id?: number diff --git a/src/graphql/query/core/topic-followers.ts b/src/graphql/query/core/topic-followers.ts new file mode 100644 index 00000000..1ec60ead --- /dev/null +++ b/src/graphql/query/core/topic-followers.ts @@ -0,0 +1,25 @@ +import { gql } from '@urql/core' + +export default gql` + query TopicFollowersQuery($slug: String) { + get_topic_followers(slug: $slug) { + id + slug + name + bio + about + pic + # communities + links + created_at + last_seen + stat { + shouts + authors + followers + rating + comments + } + } + } +` diff --git a/src/pages/about/discussionRules.page.tsx b/src/pages/about/discussionRules.page.tsx index 917beb61..899dfd5e 100644 --- a/src/pages/about/discussionRules.page.tsx +++ b/src/pages/about/discussionRules.page.tsx @@ -40,7 +40,7 @@ export const DiscussionRulesPage = () => { людей рождается истина.

    -

    За что можно получить дырку в карме и выиграть бан в сообществе

    +

    За что можно получить дырку в карме и выиграть бан в сообществе

    1. diff --git a/src/pages/feed.page.tsx b/src/pages/feed.page.tsx index 92f1c5c8..ac0e4c45 100644 --- a/src/pages/feed.page.tsx +++ b/src/pages/feed.page.tsx @@ -1,6 +1,5 @@ -import { Match, Switch, createEffect, on, onCleanup } from 'solid-js' +import { createEffect, on, onCleanup } from 'solid-js' -import { AuthGuard } from '../components/AuthGuard' import { Feed } from '../components/Views/Feed' import { PageLayout } from '../components/_shared/PageLayout' import { useLocalize } from '../context/localize' @@ -32,16 +31,7 @@ export const FeedPage = () => { return ( - }> - - - - - - - - - + )