From 89450336e7a505ccfb4433a9dc4ee5a656b5db0c Mon Sep 17 00:00:00 2001 From: tonyrewin Date: Sat, 19 Nov 2022 11:09:52 +0300 Subject: [PATCH] authors-with-counters --- src/components/Views/AllAuthors.tsx | 204 +++++++++++++++++++--------- src/components/Views/AllTopics.tsx | 75 +++------- src/components/Views/FourOuFour.tsx | 2 +- src/graphql/client.ts | 20 +++ src/graphql/privateGraphQLClient.ts | 5 +- src/graphql/publicGraphQLClient.ts | 5 +- src/graphql/types.gen.ts | 1 + src/locales/ru.json | 71 +++++----- src/styles/AllTopics.module.scss | 1 + src/utils/config.ts | 4 +- 10 files changed, 230 insertions(+), 158 deletions(-) create mode 100644 src/graphql/client.ts diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx index 91db2bd3..7ef9f0ac 100644 --- a/src/components/Views/AllAuthors.tsx +++ b/src/components/Views/AllAuthors.tsx @@ -9,6 +9,8 @@ import styles from '../../styles/AllTopics.module.scss' import { clsx } from 'clsx' import { useSession } from '../../context/session' import { locale } from '../../stores/ui' +import { translit } from '../../utils/ru2en' +import { SearchField } from '../_shared/SearchField' type AllAuthorsPageSearchParams = { by: '' | 'name' | 'shouts' | 'rating' @@ -19,6 +21,7 @@ type Props = { } const PAGE_SIZE = 20 +const ALPHABET = Array.from('@АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ') export const AllAuthorsView = (props: Props) => { const { sortedAuthors } = useAuthorsStore({ authors: props.authors }) @@ -32,7 +35,7 @@ export const AllAuthorsView = (props: Props) => { const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || '')) - const { searchParams } = useRouter() + const { searchParams, changeSearchParam } = useRouter() const byLetter = createMemo<{ [letter: string]: Author[] }>(() => { return sortedAuthors().reduce((acc, author) => { @@ -51,82 +54,113 @@ export const AllAuthorsView = (props: Props) => { }) const showMore = () => setLimit((oldLimit) => oldLimit + PAGE_SIZE) + const AllAuthorsHead = () => ( +
+
+

{t('Authors')}

+

{t('Subscribe who you like to tune your personal feed')}

+ +
+
+ ) + const scrollHandler = (elemId) => { + const anchor = document.querySelector('#' + elemId) + // console.debug(elemId) + if (anchor) { + window.scrollTo({ + top: anchor.getBoundingClientRect().top - 100, + behavior: 'smooth' + }) + } + } + const [searchResults, setSearchResults] = createSignal([]) + // eslint-disable-next-line sonarjs/cognitive-complexity + const searchAuthors = (value) => { + /* very stupid search algorithm with no deps */ + let q = value.toLowerCase() + if (q.length > 0) { + console.debug(q) + setSearchResults([]) + + if (locale() === 'ru') q = translit(q, 'ru') + const aaa: Author[] = [] + sortedAuthors().forEach((a) => { + let flag = false + a.slug.split('-').forEach((w) => { + if (w.startsWith(q)) flag = true + }) + + if (!flag) { + let wrds: string = a.name.toLowerCase() + if (locale() === 'ru') wrds = translit(wrds, 'ru') + wrds.split(' ').forEach((w: string) => { + if (w.startsWith(q)) flag = true + }) + } + + if (flag && !aaa.includes(a)) aaa.push(a) + }) + + setSearchResults((sr: Author[]) => [...sr, ...aaa]) + changeSearchParam('by', '') + } + } return (
- 0}> + 0 || searchResults().length > 0}>
-
-
-

{t('Authors')}

-

{t('Subscribe who you like to tune your personal feed')}

+ - -
-
- - ( -
-
-
- - {(author) => ( - - )} - -
-
- limit()}> -
-
- -
-
-
+ +
+
+
- )} - > +
+ - {(letter) => ( + {(letter, index) => (
-

{letter}

+

{letter}

- {(author: Author) => ( + {(author) => (
{author.name} + {author.stat.shouts}
)} @@ -139,6 +173,54 @@ export const AllAuthorsView = (props: Props) => { )}
+ +
+ 0}> + + {(author) => ( + + )} + + + + +
+
+ + {(author) => ( + + )} + +
+
+
+ + limit()}> +
+
+ +
+
+
+
diff --git a/src/components/Views/AllTopics.tsx b/src/components/Views/AllTopics.tsx index e4c5e349..7db22a7c 100644 --- a/src/components/Views/AllTopics.tsx +++ b/src/components/Views/AllTopics.tsx @@ -20,46 +20,11 @@ type AllTopicsViewProps = { } const PAGE_SIZE = 20 +const ALPHABET = Array.from('#АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ') export const AllTopicsView = (props: AllTopicsViewProps) => { const { searchParams, changeSearchParam } = useRouter() const [limit, setLimit] = createSignal(PAGE_SIZE) - const ALPHABET = [ - '#', - 'А', - 'Б', - 'В', - 'Г', - 'Д', - 'Е', - 'Ё', - 'Ж', - 'З', - 'И', - 'Й', - 'К', - 'Л', - 'М', - 'Н', - 'О', - 'П', - 'Р', - 'С', - 'Т', - 'У', - 'Ф', - 'Х', - 'Ц', - 'Ч', - 'Ш', - 'Щ', - 'Ъ', - 'Ы', - 'Ь', - 'Э', - 'Ю', - 'Я' - ] const { sortedTopics } = useTopicsStore({ topics: props.topics, @@ -139,7 +104,7 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { {t('By authors')}
  • - {t('By alphabet')} + {t('By title')}
  • ) + + const scrollHandler = (elemId) => { + const anchor = document.querySelector('#' + elemId) + // console.debug(elemId) + if (anchor) { + window.scrollTo({ + top: anchor.getBoundingClientRect().top - 100, + behavior: 'smooth' + }) + } + } return (
    @@ -161,10 +137,14 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { {(letter, index) => (
  • - - {letter} + + scrollHandler(`letter-${index()}`)} + > + {letter} + - {letter}
  • )}
    @@ -211,20 +191,7 @@ export const AllTopicsView = (props: AllTopicsViewProps) => { - - - {(topic) => ( - - )} - - - - + {(topic) => ( {

    - {t('Back to mainpage')} + {t('Back to main page')}

    diff --git a/src/graphql/client.ts b/src/graphql/client.ts new file mode 100644 index 00000000..97a4eb57 --- /dev/null +++ b/src/graphql/client.ts @@ -0,0 +1,20 @@ +import { createClient } from '@urql/core' +import { isDev } from '../utils/config' + +const localClient = (options) => { + console.info('[graphql] using local client') + const url = 'http://localhost:8080' + return createClient({ ...options, url }) +} + +export const initClient = (options) => { + try { + if (isDev) { + console.info('[graphql] devmode detected') + return localClient(options) + } else return createClient(options) + } catch (e) { + console.error(e) + return localClient(options) + } +} diff --git a/src/graphql/privateGraphQLClient.ts b/src/graphql/privateGraphQLClient.ts index 442343cf..700498b1 100644 --- a/src/graphql/privateGraphQLClient.ts +++ b/src/graphql/privateGraphQLClient.ts @@ -1,6 +1,7 @@ -import { createClient, ClientOptions, dedupExchange, fetchExchange, Exchange } from '@urql/core' +import { ClientOptions, dedupExchange, fetchExchange, Exchange } from '@urql/core' import { devtoolsExchange } from '@urql/devtools' import { isDev, apiBaseUrl } from '../utils/config' +import { initClient } from './client' const TOKEN_LOCAL_STORAGE_KEY = 'token' @@ -37,4 +38,4 @@ const options: ClientOptions = { exchanges } -export const privateGraphQLClient = createClient(options) +export const privateGraphQLClient = initClient(options) diff --git a/src/graphql/publicGraphQLClient.ts b/src/graphql/publicGraphQLClient.ts index baa60d9a..78b5c2bb 100644 --- a/src/graphql/publicGraphQLClient.ts +++ b/src/graphql/publicGraphQLClient.ts @@ -1,6 +1,7 @@ -import { ClientOptions, dedupExchange, fetchExchange, createClient, Exchange } from '@urql/core' +import { ClientOptions, dedupExchange, fetchExchange, Exchange } from '@urql/core' import { devtoolsExchange } from '@urql/devtools' import { isDev, apiBaseUrl } from '../utils/config' +import { initClient } from './client' const exchanges: Exchange[] = [dedupExchange, fetchExchange] @@ -15,4 +16,4 @@ const options: ClientOptions = { exchanges } -export const publicGraphQLClient = createClient(options) +export const publicGraphQLClient = initClient(options) diff --git a/src/graphql/types.gen.ts b/src/graphql/types.gen.ts index a3bc45d2..493f21a1 100644 --- a/src/graphql/types.gen.ts +++ b/src/graphql/types.gen.ts @@ -39,6 +39,7 @@ export type AuthorStat = { followers?: Maybe followings?: Maybe rating?: Maybe + shouts?: Maybe } export type AuthorsBy = { diff --git a/src/locales/ru.json b/src/locales/ru.json index b71cdec3..dce9e981 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -2,26 +2,32 @@ "...subscribing": "...подписываем", "About the project": "О проекте", "All": "Все", + "All authors": "Все авторы", "All posts": "Все публикации", "All topics": "Все темы", - "All authors": "Все авторы", + "Almost done! Check your email.": "Почти готово! Осталось подтвердить вашу почту.", + "Artworks": "Артворки", + "Audio": "Аудио", "Authors": "Авторы", - "Back to mainpage": "Вернуться на главную", + "Back to main page": "Вернуться на главную", "Become an author": "Стать автором", "Bookmarked": "Сохранено", "By alphabet": "По алфавиту", "By authors": "По авторам", + "By name": "По имени", "By rating": "По популярности", "By relevance": "По релевантности", "By shouts": "По публикациям", "By signing up you agree with our": "Регистрируясь, вы соглашаетесь с", + "By title": "По названию", "By updates": "По обновлениям", "By views": "По просмотрам", "Collaborate": "Помочь редактировать", "Comments": "Комментарии", "Communities": "Сообщества", - "Create account": "Создать аккаунт", "Copy link": "Скопировать ссылку", + "Create account": "Создать аккаунт", + "Create post": "Создать публикацию", "Delete": "Удалить", "Discours": "Дискурс", "Discours is an intellectual environment, a web space and tools that allows authors to collaborate with readers and come together to co-create publications and media projects": "Дискурс — это интеллектуальная среда, веб-пространство и инструменты, которые позволяют авторам сотрудничать с читателями и объединяться для совместного создания публикаций и медиапроектов", @@ -31,6 +37,8 @@ "Dogma": "Догма", "Edit": "Редактировать", "Email": "Почта", + "Enter": "Войти", + "Enter text": "Введите текст", "Enter the Discours": "Войти в Дискурс", "Enter the code or click the link from email to confirm": "Введите код из письма или пройдите по ссылке в письме для подтверждения регистрации", "Enter your new password": "Введите новый пароль", @@ -44,18 +52,26 @@ "Follow": "Подписаться", "Follow the topic": "Подписаться на тему", "Forgot password?": "Забыли пароль?", + "Full 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": "Познакомитесь с выдающимися людьми нашего времени, участвуйте в редактировании и обсуждении статей, выступайте экспертом, оценивайте материалы других авторов со всего мира и определяйте, какие статьи будут опубликованы в журнале", + "Go to main page": "Перейти на главную", "Help to edit": "Помочь редактировать", + "Hooray! Welcome!": "Ура! Добро пожаловать!", "Horizontal collaborative journalistic platform": "Горизонтальная платформа для коллаборативной журналистики", "How it works": "Как это работает", "How to write an article": "Как написать статью", "I have an account": "У меня есть аккаунт!", "I have no account yet": "У меня еще нет аккаунта", "I know the password": "Я знаю пароль", + "Invalid email": "Проверьте правильность ввода почты", + "Join": "Присоединиться", "Join our maillist": "Чтобы получать рассылку лучших публикаций, просто укажите свою почту", "Join the community": "Присоединиться к сообществу", "Join the global community of authors!": "Присоединятесь к глобальному сообществу авторов со всего мира!", + "Just start typing...": "Просто начните печатать...", "Knowledge base": "База знаний", + "Link sent, check your email": "Ссылка отправлена, проверьте почту", + "Literature": "Литература", "Load more": "Показать ещё", "Loading": "Загрузка", "Manifest": "Манифест", @@ -76,6 +92,11 @@ "Passwords are not equal": "Пароли не совпадают", "Please check your email address": "Пожалуйста, проверьте введенный адрес почты", "Please confirm your email to finish": "Подтвердите почту и действие совершится", + "Please enter a name to sign your comments and publication": "Пожалуйста, введите имя, которое будет отображаться на сайте", + "Please enter email": "Пожалуйста, введите почту", + "Please enter password": "Пожалуйста, введите пароль", + "Please enter password again": "Пожалуйста, введите пароль ещё рез", + "Please, confirm email": "Пожалуйста, подтвердите электронную почту", "Popular": "Популярное", "Popular authors": "Популярные авторы", "Principles": "Принципы сообщества", @@ -86,12 +107,15 @@ "Reply": "Ответить", "Report": "Пожаловаться", "Resend code": "Выслать подтверждение", + "Restore password": "Восстановить пароль", "Search": "Поиск", "Search author": "Поиск автора", "Search topic": "Поиск темы", "Sections": "Разделы", + "Send link again": "Прислать ссылку ещё раз", "Share": "Поделиться", "Show": "Показать", + "Something went wrong, check email and password": "Что-то пошло не так. Проверьте адрес электронной почты и пароль", "Special projects": "Спецпроекты", "Subscribe": "Подписаться", "Subscribe what you like to tune your personal feed": "Подпишитесь на интересующие вас темы, чтобы настроить вашу персональную ленту и моментально узнавать о новых публикациях и обсуждениях", @@ -102,6 +126,7 @@ "Support us": "Помочь журналу", "Terms of use": "Правила сайта", "Thank you": "Благодарности", + "This email is already taken. If it's you": "Такой email уже зарегистрирован. Если это вы", "To leave a comment please": "Чтобы оставить комментарий, необходимо", "Top authors": "Рейтинг авторов", "Top commented": "Самое комментируемое", @@ -118,16 +143,21 @@ "Unfollow": "Отписаться", "Unfollow the topic": "Отписаться от темы", "Username": "Имя пользователя", + "Video": "Видео", "Views": "Просмотры", "We are convinced that one voice is good, but many is better": "Мы убеждены, один голос хорошо, а много — лучше", + "We can't find you, check email or": "Не можем вас найти, проверьте адрес электронной почты или", "We create the most amazing stories together": "Самые потрясающиe истории мы создаём вместе", "We know you, please try to login": "Такой адрес почты уже зарегистрирован, попробуйте залогиниться", + "We've sent you a message with a link to enter our website.": "Мы выслали вам письмо с ссылкой на почту. Перейдите по ссылке в письме, чтобы войти на сайт.", "Work with us": "Сотрудничать с Дискурсом", "Write": "Написать", "Write about the topic": "Написать в тему", "Write comment": "Написать комментарий", "Write to us": "Напишите нам", "You are subscribed": "Вы подписаны", + "You was successfully authorized": "Вы были успешно авторизованы", + "You've confirmed email": "Вы подтвердили почту", "You've reached a non-existed page": "Вы попали на несуществующую страницу", "actions": "действия", "all topics": "все темы", @@ -136,46 +166,17 @@ "collections": "коллекции", "community": "сообщество", "email not confirmed": "email не подтвержден", - "Enter": "Войти", + "enter": "войдите", "feed": "лента", "follower": "подписчик", "invalid password": "некорректный пароль", "personal data usage and email notifications": "на обработку персональных данных и на получение почтовых уведомлений", "post": "пост", + "register": "зарегистрируйтесь", "sign up or sign in": "зарегистрироваться или войти", "terms of use": "правилами пользования сайтом", "topics": "темы", "user already exist": "пользователь уже существует", "view": "просмотр", - "zine": "журнал", - "Please, confirm email": "Пожалуйста, подтвердите электронную почту", - "Something went wrong, check email and password": "Что-то пошло не так. Проверьте адрес электронной почты и пароль", - "You was successfully authorized": "Вы были успешно авторизованы", - "Invalid email": "Проверьте правильность ввода почты", - "Please enter email": "Пожалуйста, введите почту", - "Please enter password": "Пожалуйста, введите пароль", - "Please enter password again": "Пожалуйста, введите пароль ещё рез", - "Join": "Присоединиться", - "Please enter a name to sign your comments and publication": "Пожалуйста, введите имя, которое будет отображаться на сайте", - "Full name": "Имя и фамилия", - "Restore password": "Восстановить пароль", - "Hooray! Welcome!": "Ура! Добро пожаловать!", - "You've confirmed email": "Вы подтвердили почту", - "This email is already taken. If it's you": "Такой email уже зарегистрирован. Если это вы", - "enter": "войдите", - "Go to main page": "Перейти на главную", - "Back to main page": "Вернуться на главную", - "Almost done! Check your email.": "Почти готово! Осталось подтвердить вашу почту.", - "We've sent you a message with a link to enter our website.": "Мы выслали вам письмо с ссылкой на почту. Перейдите по ссылке в письме, чтобы войти на сайт.", - "Send link again": "Прислать ссылку ещё раз", - "Link sent, check your email": "Ссылка отправлена, проверьте почту", - "Create post": "Создать публикацию", - "Just start typing...": "Просто начните печатать...", - "Artworks": "Артворки", - "Audio": "Аудио", - "Video": "Видео", - "Literature": "Литература", - "We can't find you, check email or": "Не можем вас найти, проверьте адрес электронной почты или", - "register": "зарегистрируйтесь", - "Enter text": "Введите текст" + "zine": "журнал" } diff --git a/src/styles/AllTopics.module.scss b/src/styles/AllTopics.module.scss index ef536a42..e8258b43 100644 --- a/src/styles/AllTopics.module.scss +++ b/src/styles/AllTopics.module.scss @@ -64,5 +64,6 @@ li { min-width: 1.5em; margin-right: 3%; + color: gray; } } diff --git a/src/utils/config.ts b/src/utils/config.ts index 4bb1b83e..e5a6cc27 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,4 @@ export const isDev = import.meta.env.MODE === 'development' export const apiBaseUrl = 'https://v2.discours.io' -// export const apiBaseUrl = 'https://newapi.discours.io' -// testapi.discours.io -// export const apiBaseUrl = 'http://localhost:8080' +// export const apiBaseUrl = 'https://testapi.discours.io'