expo pages (#111)

* layout pages

* lint

* code review, lint, build fix

* lint
This commit is contained in:
Igor Lobanov 2023-06-16 16:47:24 +02:00 committed by GitHub
parent 03bcd7eced
commit 75c3d5faea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 249 additions and 229 deletions

View File

@ -56,11 +56,11 @@
"Create Chat": "Create Chat", "Create Chat": "Create Chat",
"Create Group": "Create a group", "Create Group": "Create a group",
"Create account": "Create an account", "Create account": "Create an account",
"Create account from subscribe": "Create an account to subscribe to new publications",
"Create account from discussions": "Create an account to participate in discussions",
"Create account from vote": "Create an account to vote",
"Create account from bookmark": "Create an account to add to your bookmarks", "Create account from bookmark": "Create an account to add to your bookmarks",
"Create account from discussions": "Create an account to participate in discussions",
"Create account from follow": "Create an account to subscribe", "Create account from follow": "Create an account to subscribe",
"Create account from subscribe": "Create an account to subscribe to new publications",
"Create account from vote": "Create an account to vote",
"Create post": "Create post", "Create post": "Create post",
"Date of Birth": "Date of Birth", "Date of Birth": "Date of Birth",
"Delete": "Delete", "Delete": "Delete",
@ -69,6 +69,7 @@
"Discours is created with our common effort": "Discours exists because of our common effort", "Discours is created with our common effort": "Discours exists because of our common effort",
"Discussing": "Discussing", "Discussing": "Discussing",
"Discussion rules": "Discussion rules", "Discussion rules": "Discussion rules",
"Discussions": "Discussions",
"Dogma": "Dogma", "Dogma": "Dogma",
"Drafts": "Drafts", "Drafts": "Drafts",
"Drag the image to this area": "Drag the image to this area", "Drag the image to this area": "Drag the image to this area",
@ -79,11 +80,11 @@
"Enter URL address": "Enter URL address", "Enter URL address": "Enter URL address",
"Enter text": "Enter text", "Enter text": "Enter text",
"Enter the Discours": "Enter the Discours", "Enter the Discours": "Enter the Discours",
"Enter the Discours from subscribe": "Sign in to subscribe to new publications",
"Enter the Discours from discussions": "Sign in to participate in the discussions",
"Enter the Discours from vote": "Sign in to vote",
"Enter the Discours from bookmark": "Sign in to add to bookmarks", "Enter the Discours from bookmark": "Sign in to add to bookmarks",
"Enter the Discours from discussions": "Sign in to participate in the discussions",
"Enter the Discours from follow": "Sign in to follow", "Enter the Discours from follow": "Sign in to follow",
"Enter the Discours from subscribe": "Sign in to subscribe to new publications",
"Enter the Discours from vote": "Sign in to vote",
"Enter the code or click the link from email to confirm": "Enter the code from the email or follow the link in the email to confirm registration", "Enter the code or click the link from email to confirm": "Enter the code from the email or follow the link in the email to confirm registration",
"Enter your new password": "Enter your new password", "Enter your new password": "Enter your new password",
"Error": "Error", "Error": "Error",
@ -115,6 +116,7 @@
"Highlight": "Highlight", "Highlight": "Highlight",
"Hooray! Welcome!": "Hooray! Welcome!", "Hooray! Welcome!": "Hooray! Welcome!",
"Horizontal collaborative journalistic platform": "Horizontal collaborative journalism platform", "Horizontal collaborative journalistic platform": "Horizontal collaborative journalism platform",
"Hot topics": "Hot topics",
"Hotkeys": "Горячие клавиши", "Hotkeys": "Горячие клавиши",
"How can I help/skills": "How can I help/skills", "How can I help/skills": "How can I help/skills",
"How it works": "How it works", "How it works": "How it works",
@ -127,6 +129,7 @@
"Incut": "Incut", "Incut": "Incut",
"Independant magazine with an open horizontal cooperation about culture, science and society": "Independant magazine with an open horizontal cooperation about culture, science and society", "Independant magazine with an open horizontal cooperation about culture, science and society": "Independant magazine with an open horizontal cooperation about culture, science and society",
"Insert footnote": "Insert footnote", "Insert footnote": "Insert footnote",
"Insert video link": "Insert video link",
"Introduce": "Introduction", "Introduce": "Introduction",
"Invalid email": "Check if your email is correct", "Invalid email": "Check if your email is correct",
"Invalid image URL": "Invalid image URL", "Invalid image URL": "Invalid image URL",
@ -149,6 +152,7 @@
"Load more": "Show more", "Load more": "Show more",
"Loading": "Loading", "Loading": "Loading",
"Logout": "Logout", "Logout": "Logout",
"Looks like you forgot to upload the video": "Looks like you forgot to upload the video",
"Manifest": "Manifest", "Manifest": "Manifest",
"Many files, choose only one": "Many files, choose only one", "Many files, choose only one": "Many files, choose only one",
"Material card": "Material card", "Material card": "Material card",
@ -165,6 +169,7 @@
"No such account, please try to register": "No such account found, please try to register", "No such account, please try to register": "No such account found, please try to register",
"Nothing here yet": "There's nothing here yet", "Nothing here yet": "There's nothing here yet",
"Nothing is here": "There is nothing here", "Nothing is here": "There is nothing here",
"Notifications": "Notifications",
"Or continue with social network": "Or continue with social network", "Or continue with social network": "Or continue with social network",
"Or paste a link to an image": "Or paste a link to an image", "Or paste a link to an image": "Or paste a link to an image",
"Ordered list": "Ordered list", "Ordered list": "Ordered list",
@ -256,7 +261,6 @@
"Top viewed": "Most viewed", "Top viewed": "Most viewed",
"Topic is supported by": "Topic is supported by", "Topic is supported by": "Topic is supported by",
"Topics": "Topics", "Topics": "Topics",
"Hot topics": "Hot topics",
"Topics which supported by author": "Topics which supported by author", "Topics which supported by author": "Topics which supported by author",
"Try to find another way": "Try to find another way", "Try to find another way": "Try to find another way",
"Unfollow": "Unfollow", "Unfollow": "Unfollow",
@ -305,7 +309,6 @@
"community": "community", "community": "community",
"delimiter": "delimiter", "delimiter": "delimiter",
"discussion": "discourse", "discussion": "discourse",
"Discussions": "Discussions",
"drafts": "drafts", "drafts": "drafts",
"email not confirmed": "email not confirmed", "email not confirmed": "email not confirmed",
"enter": "enter", "enter": "enter",
@ -322,7 +325,6 @@
"marker list": "marker list", "marker list": "marker list",
"music": "music", "music": "music",
"my feed": "my ribbon", "my feed": "my ribbon",
"Notifications": "Notifications",
"number list": "number list", "number list": "number list",
"personal data usage and email notifications": "to process personal data and receive email notifications", "personal data usage and email notifications": "to process personal data and receive email notifications",
"post": "post", "post": "post",
@ -336,7 +338,5 @@
"user already exist": "user already exists", "user already exist": "user already exists",
"video": "video", "video": "video",
"view": "view", "view": "view",
"zine": "zine", "zine": "zine"
"Insert video link": "Insert video link",
"Looks like you forgot to upload the video": "Looks like you forgot to upload the video"
} }

View File

@ -3,6 +3,7 @@
"A short introduction to keep the reader interested": "Небольшое вступление, чтобы заинтересовать читателя", "A short introduction to keep the reader interested": "Небольшое вступление, чтобы заинтересовать читателя",
"About myself": "О себе", "About myself": "О себе",
"About the project": "О проекте", "About the project": "О проекте",
"Accomplices": "Соучастники",
"Add another image": "Добавить другое изображение", "Add another image": "Добавить другое изображение",
"Add comment": "Комментировать", "Add comment": "Комментировать",
"Add image": "Добавить изображение", "Add image": "Добавить изображение",
@ -58,11 +59,11 @@
"Create Chat": "Создать чат", "Create Chat": "Создать чат",
"Create Group": "Создать группу", "Create Group": "Создать группу",
"Create account": "Создать аккаунт", "Create account": "Создать аккаунт",
"Create account from subscribe": "Создайте аккаунт для подписки на новые публикации",
"Create account from discussions": "Создайте аккаунт для участия в дискуссиях",
"Create account from vote": "Создайте аккаунт, чтобы голосовать",
"Create account from bookmark": "Создайте аккаунт, чтобы добавить в закладки", "Create account from bookmark": "Создайте аккаунт, чтобы добавить в закладки",
"Create account from discussions": "Создайте аккаунт для участия в дискуссиях",
"Create account from follow": "Создайте аккаунт, чтобы подписаться", "Create account from follow": "Создайте аккаунт, чтобы подписаться",
"Create account from subscribe": "Создайте аккаунт для подписки на новые публикации",
"Create account from vote": "Создайте аккаунт, чтобы голосовать",
"Create post": "Создать публикацию", "Create post": "Создать публикацию",
"Date of Birth": "Дата рождения", "Date of Birth": "Дата рождения",
"Delete": "Удалить", "Delete": "Удалить",
@ -71,6 +72,7 @@
"Discours is created with our common effort": "Дискурс существует благодаря нашему общему вкладу", "Discours is created with our common effort": "Дискурс существует благодаря нашему общему вкладу",
"Discussing": "Обсуждаемое", "Discussing": "Обсуждаемое",
"Discussion rules": "Правила сообществ самиздата в соцсетях", "Discussion rules": "Правила сообществ самиздата в соцсетях",
"Discussions": "Дискуссии",
"Dogma": "Догма", "Dogma": "Догма",
"Drafts": "Черновики", "Drafts": "Черновики",
"Drag the image to this area": "Перетащите изображение в эту область", "Drag the image to this area": "Перетащите изображение в эту область",
@ -82,11 +84,11 @@
"Enter URL address": "Введите адрес ссылки", "Enter URL address": "Введите адрес ссылки",
"Enter text": "Введите текст", "Enter text": "Введите текст",
"Enter the Discours": "Войти в Дискурс", "Enter the Discours": "Войти в Дискурс",
"Enter the Discours from subscribe": "Войдите для подписки на новые публикации",
"Enter the Discours from discussions": "Войдите для участия в дискуссиях",
"Enter the Discours from vote": "Войдите, чтобы голосовать",
"Enter the Discours from bookmark": "Войдите, чтобы добавить в закладки", "Enter the Discours from bookmark": "Войдите, чтобы добавить в закладки",
"Enter the Discours from discussions": "Войдите для участия в дискуссиях",
"Enter the Discours from follow": "Войдите, чтобы подписаться", "Enter the Discours from follow": "Войдите, чтобы подписаться",
"Enter the Discours from subscribe": "Войдите для подписки на новые публикации",
"Enter the Discours from vote": "Войдите, чтобы голосовать",
"Enter the code or click the link from email to confirm": "Введите код из письма или пройдите по ссылке в письме для подтверждения регистрации", "Enter the code or click the link from email to confirm": "Введите код из письма или пройдите по ссылке в письме для подтверждения регистрации",
"Enter your new password": "Введите новый пароль", "Enter your new password": "Введите новый пароль",
"Error": "Ошибка", "Error": "Ошибка",
@ -120,6 +122,7 @@
"Highlight": "Подсветка", "Highlight": "Подсветка",
"Hooray! Welcome!": "Ура! Добро пожаловать!", "Hooray! Welcome!": "Ура! Добро пожаловать!",
"Horizontal collaborative journalistic platform": "Горизонтальная платформа для коллаборативной журналистики", "Horizontal collaborative journalistic platform": "Горизонтальная платформа для коллаборативной журналистики",
"Hot topics": "Горячие темы",
"Hotkeys": "Горячие клавиши", "Hotkeys": "Горячие клавиши",
"How can I help/skills": "Чем могу помочь/навыки", "How can I help/skills": "Чем могу помочь/навыки",
"How it works": "Как это работает", "How it works": "Как это работает",
@ -132,6 +135,7 @@
"Incut": "Подверстка", "Incut": "Подверстка",
"Independant magazine with an open horizontal cooperation about culture, science and society": "Независимый журнал с открытой горизонтальной редакцией о культуре, науке и обществе", "Independant magazine with an open horizontal cooperation about culture, science and society": "Независимый журнал с открытой горизонтальной редакцией о культуре, науке и обществе",
"Insert footnote": "Вставить сноску", "Insert footnote": "Вставить сноску",
"Insert video link": "Вставить ссылку на видео",
"Introduce": "Представление", "Introduce": "Представление",
"Invalid email": "Проверьте правильность ввода почты", "Invalid email": "Проверьте правильность ввода почты",
"Invalid image URL": "Некорректная ссылка на изображение", "Invalid image URL": "Некорректная ссылка на изображение",
@ -156,6 +160,7 @@
"Load more": "Показать ещё", "Load more": "Показать ещё",
"Loading": "Загрузка", "Loading": "Загрузка",
"Logout": "Выход", "Logout": "Выход",
"Looks like you forgot to upload the video": "Похоже, что вы забыли загрузить видео",
"Manifest": "Манифест", "Manifest": "Манифест",
"Many files, choose only one": "Много файлов, выберете один", "Many files, choose only one": "Много файлов, выберете один",
"Material card": "Карточка материала", "Material card": "Карточка материала",
@ -172,6 +177,7 @@
"No such account, please try to register": "Такой адрес не найден, попробуйте зарегистрироваться", "No such account, please try to register": "Такой адрес не найден, попробуйте зарегистрироваться",
"Nothing here yet": "Здесь пока ничего нет", "Nothing here yet": "Здесь пока ничего нет",
"Nothing is here": "Здесь ничего нет", "Nothing is here": "Здесь ничего нет",
"Notifications": "Уведомления",
"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": "Нумерованный список",
@ -255,7 +261,7 @@
"Thank you": "Благодарности", "Thank you": "Благодарности",
"This comment has not yet been rated": "Этот комментарий еще пока никто не оценил", "This comment has not yet been rated": "Этот комментарий еще пока никто не оценил",
"This email is already taken. If it's you": "Такой email уже зарегистрирован. Если это вы", "This email is already taken. If it's you": "Такой email уже зарегистрирован. Если это вы",
"This functionality is currently not available, we would like to work on this issue. Use the download link.": "В данный момент этот функционал не доступен, бы работаем над этой проблемой. Воспользуйтесь загрузкой по ссылке.", "This functionality is currently not available, we would like to work on this issue. Use the download link.": "В данный момент этот функционал недоступен, мы работаем над этой проблемой. Воспользуйтесь загрузкой по ссылке.",
"This post has not been rated yet": "Эту публикацию еще пока никто не оценил", "This post has not been rated yet": "Эту публикацию еще пока никто не оценил",
"To leave a comment please": "Чтобы оставить комментарий, необходимо", "To leave a comment please": "Чтобы оставить комментарий, необходимо",
"To write a comment, you must": "Чтобы написать комментарий, необходимо", "To write a comment, you must": "Чтобы написать комментарий, необходимо",
@ -269,7 +275,6 @@
"Top viewed": "Самое читаемое", "Top viewed": "Самое читаемое",
"Topic is supported by": "Тему поддерживают", "Topic is supported by": "Тему поддерживают",
"Topics": "Темы", "Topics": "Темы",
"Hot topics": "Горячие темы",
"Topics which supported by author": "Автор поддерживает темы", "Topics which supported by author": "Автор поддерживает темы",
"Try to find another way": "Попробуйте найти по-другому", "Try to find another way": "Попробуйте найти по-другому",
"Unfollow": "Отписаться", "Unfollow": "Отписаться",
@ -304,7 +309,6 @@
"You've reached a non-existed page": "Вы попали на несуществующую страницу", "You've reached a non-existed page": "Вы попали на несуществующую страницу",
"You've successfully logged out": "Вы успешно вышли из аккаунта", "You've successfully logged out": "Вы успешно вышли из аккаунта",
"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": "Соучастники",
"actions": "действия", "actions": "действия",
"add link": "добавить ссылку", "add link": "добавить ссылку",
"all topics": "все темы", "all topics": "все темы",
@ -323,7 +327,6 @@
"delimiter": "разделитель", "delimiter": "разделитель",
"discourse_theme": "Тема дискурса", "discourse_theme": "Тема дискурса",
"discussion": "дискурс", "discussion": "дискурс",
"Discussions": "Дискуссии",
"drafts": "черновики", "drafts": "черновики",
"email not confirmed": "email не подтвержден", "email not confirmed": "email не подтвержден",
"enter": "войдите", "enter": "войдите",
@ -340,7 +343,6 @@
"marker list": "маркир. список", "marker list": "маркир. список",
"music": "музыка", "music": "музыка",
"my feed": "моя лента", "my feed": "моя лента",
"Notifications": "Уведомления",
"number list": "нумер. список", "number list": "нумер. список",
"or": "или", "or": "или",
"personal data usage and email notifications": "на обработку персональных данных и на получение почтовых уведомлений", "personal data usage and email notifications": "на обработку персональных данных и на получение почтовых уведомлений",
@ -358,7 +360,5 @@
"user already exist": "пользователь уже существует", "user already exist": "пользователь уже существует",
"video": "видео", "video": "видео",
"view": "просмотр", "view": "просмотр",
"zine": "журнал", "zine": "журнал"
"Insert video link": "Вставить ссылку на видео",
"Looks like you forgot to upload the video": "Похоже, что вы забыли загрузить видео"
} }

View File

@ -1,5 +1,6 @@
h1 { h1 {
@include font-size(4rem); @include font-size(4rem);
line-height: 1.1; line-height: 1.1;
margin-top: 0.5em; margin-top: 0.5em;
} }
@ -154,6 +155,7 @@ img {
.shoutStatsItem { .shoutStatsItem {
@include font-size(1.5rem); @include font-size(1.5rem);
font-weight: 500; font-weight: 500;
display: inline-block; display: inline-block;
margin: 0 6% 1em 0; margin: 0 6% 1em 0;

View File

@ -170,8 +170,9 @@
} }
.articleLink { .articleLink {
flex: 0 0 50%;
@include font-size(1.2rem); @include font-size(1.2rem);
flex: 0 0 50%;
margin-right: 2em; margin-right: 2em;
@include media-breakpoint-down(md) { @include media-breakpoint-down(md) {

View File

@ -5,7 +5,6 @@ import { Show, createMemo, createSignal, For, lazy, Suspense } from 'solid-js'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import type { Author, Reaction } from '../../graphql/types.gen' import type { Author, Reaction } from '../../graphql/types.gen'
import MD from './MD' import MD from './MD'
import { formatDate } from '../../utils'
import Userpic from '../Author/Userpic' import Userpic from '../Author/Userpic'
import { useSession } from '../../context/session' import { useSession } from '../../context/session'
import { ReactionKind } from '../../graphql/types.gen' import { ReactionKind } from '../../graphql/types.gen'
@ -78,9 +77,6 @@ export const Comment = (props: Props) => {
} }
} }
const formattedDate = (date) =>
createMemo(() => formatDate(new Date(date), { hour: 'numeric', minute: 'numeric' }))
const toggleEditMode = () => { const toggleEditMode = () => {
setEditMode((oldEditMode) => !oldEditMode) setEditMode((oldEditMode) => !oldEditMode)
} }

View File

@ -1,4 +1,6 @@
.commentDates { .commentDates {
@include font-size(1.2rem);
flex: 1; flex: 1;
display: flex; display: flex;
gap: 1rem; gap: 1rem;
@ -7,7 +9,6 @@
font-size: 1.2rem; font-size: 1.2rem;
margin: 0 1em 4px 0; margin: 0 1em 4px 0;
color: rgb(0 0 0 / 30%); color: rgb(0 0 0 / 30%);
@include font-size(1.2rem);
.date { .date {
.icon { .icon {

View File

@ -1,6 +1,6 @@
import styles from './CommentDate.module.scss' import styles from './CommentDate.module.scss'
import { Icon } from '../_shared/Icon' import { Icon } from '../_shared/Icon'
import { Show, createMemo } from 'solid-js' import { Show } from 'solid-js'
import type { Reaction } from '../../graphql/types.gen' import type { Reaction } from '../../graphql/types.gen'
import { formatDate } from '../../utils' import { formatDate } from '../../utils'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
@ -15,10 +15,13 @@ type Props = {
export const CommentDate = (props: Props) => { export const CommentDate = (props: Props) => {
const { t } = useLocalize() const { t } = useLocalize()
const formattedDate = (date) => const formattedDate = (date) => {
props.isShort const formatDateOptions: Intl.DateTimeFormatOptions = props.isShort
? formatDate(new Date(date), { month: 'long', day: 'numeric', year: 'numeric' }) ? { month: 'long', day: 'numeric', year: 'numeric' }
: createMemo(() => formatDate(new Date(date), { hour: 'numeric', minute: 'numeric' })) : { hour: 'numeric', minute: 'numeric' }
return formatDate(new Date(date), formatDateOptions)
}
return ( return (
<div class={clsx(styles.commentDates, { [styles.commentDatesLastInRow]: props.isLastInRow })}> <div class={clsx(styles.commentDates, { [styles.commentDatesLastInRow]: props.isLastInRow })}>

View File

@ -13,7 +13,6 @@ import { FollowingEntity } from '../../graphql/types.gen'
import { router, useRouter } from '../../stores/router' import { router, useRouter } from '../../stores/router'
import { openPage } from '@nanostores/router' import { openPage } from '@nanostores/router'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
import { init } from 'i18next'
interface AuthorCardProps { interface AuthorCardProps {
caption?: string caption?: string

View File

@ -1,5 +1,6 @@
.discoursFooter { .discoursFooter {
@include font-size(1.7rem); @include font-size(1.7rem);
background: #000; background: #000;
color: rgb(255 255 255 / 64%); color: rgb(255 255 255 / 64%);
padding: 2.4rem 0 4.2rem; padding: 2.4rem 0 4.2rem;

View File

@ -1,10 +1,10 @@
@mixin input-placeholder-overflow($direction: 'down') { @mixin input-placeholder-overflow($direction: 'down') {
@if $direction == 'down' { @if $direction == 'down' {
@media (max-width: 1410px) { @media (width <= 1410px) {
@content; @content;
} }
} @else if $direction == 'up' { } @else if $direction == 'up' {
@media (min-width: 1411px) { @media (width > 1410px) {
@content; @content;
} }
} @else { } @else {
@ -38,7 +38,7 @@
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0.2em 0.5em 0.2em 0.5em; padding: 0.2em 0.5em;
width: 100%; width: 100%;
outline: none; outline: none;
border: 1px solid #fff; border: 1px solid #fff;

View File

@ -1,6 +1,5 @@
import type { Editor } from '@tiptap/core' import type { Editor } from '@tiptap/core'
import styles from './BubbleMenu.module.scss' import styles from './BubbleMenu.module.scss'
import { clsx } from 'clsx'
import { Icon } from '../../_shared/Icon' import { Icon } from '../../_shared/Icon'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { Popover } from '../../_shared/Popover' import { Popover } from '../../_shared/Popover'

View File

@ -73,22 +73,23 @@
&.yellow { &.yellow {
background: #f6e3a1; background: #f6e3a1;
} }
&.white { &.white {
background: #fff; background: #fff;
box-shadow: inset 0 0 0 1px #000; box-shadow: inset 0 0 0 1px #000;
border-color: #fff; border-color: #fff;
} }
&.yellow {
background: #f6e3a1;
}
&.pink { &.pink {
background: #f1b5bc; background: #f1b5bc;
} }
&.green { &.green {
background: #bfe9cb; background: #bfe9cb;
box-shadow: inset 0 0 0 1px #000; box-shadow: inset 0 0 0 1px #000;
border-color: #fff; border-color: #fff;
} }
&.black { &.black {
background: #000; background: #000;
} }

View File

@ -1,6 +1,5 @@
import type { Editor } from '@tiptap/core' import type { Editor } from '@tiptap/core'
import styles from './BubbleMenu.module.scss' import styles from './BubbleMenu.module.scss'
import { clsx } from 'clsx'
import { Icon } from '../../_shared/Icon' import { Icon } from '../../_shared/Icon'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { Popover } from '../../_shared/Popover' import { Popover } from '../../_shared/Popover'

View File

@ -112,7 +112,7 @@
} }
.backToMenuControl { .backToMenuControl {
color: rgb(255 255 255 / 0.7); color: rgb(255 255 255 / 70%);
} }
.shortcutList { .shortcutList {

View File

@ -76,11 +76,13 @@ mark.highlight {
[data-float] { [data-float] {
max-width: 50%; max-width: 50%;
} }
[data-float='left'] { [data-float='left'] {
max-width: 30%; max-width: 30%;
float: left; float: left;
margin: 1rem 1rem 0 0; margin: 1rem 1rem 0 0;
} }
[data-float='right'] { [data-float='right'] {
max-width: 30%; max-width: 30%;
float: right; float: right;
@ -93,11 +95,12 @@ mark.highlight {
float: left; float: left;
margin: 1rem 1rem 0; margin: 1rem 1rem 0;
} }
[data-float='half-right'] { [data-float='half-right'] {
max-width: 50%; max-width: 50%;
min-width: 30%; min-width: 30%;
float: right; float: right;
margin: 1rem 0 1rem; margin: 1rem 0;
} }
.ProseMirror blockquote { .ProseMirror blockquote {
@ -162,16 +165,20 @@ mark.highlight {
background: #000; background: #000;
color: #fff; color: #fff;
} }
&[data-bg='yellow'] { &[data-bg='yellow'] {
background: #f6e3a1; background: #f6e3a1;
} }
&[data-bg='pink'] { &[data-bg='pink'] {
background: #f1b5bc; background: #f1b5bc;
} }
&[data-bg='green'] { &[data-bg='green'] {
background: #bfe9cb; background: #bfe9cb;
box-shadow: 0 0 0 1px #000; box-shadow: 0 0 0 1px #000;
} }
&[data-bg='white'] { &[data-bg='white'] {
background: #fff; background: #fff;
box-shadow: 0 0 0 1px #000; box-shadow: 0 0 0 1px #000;

View File

@ -2,7 +2,7 @@
margin: 2rem 0; margin: 2rem 0;
.dropArea { .dropArea {
border: 2px dashed rgba(38, 56, 217, 0.3); border: 2px dashed rgb(38 56 217 / 30%);
border-radius: 16px; border-radius: 16px;
color: #2638d9; color: #2638d9;
display: flex; display: flex;

View File

@ -1,5 +1,4 @@
import { Blockquote } from '@tiptap/extension-blockquote' import { Blockquote } from '@tiptap/extension-blockquote'
import { Command } from '@tiptap/core'
export type QuoteTypes = 'quote' | 'punchline' export type QuoteTypes = 'quote' | 'punchline'

View File

@ -42,7 +42,7 @@
a:link { a:link {
border: none; border: none;
&:before { &::before {
content: ''; content: '';
height: 100%; height: 100%;
left: 0; left: 0;
@ -118,6 +118,7 @@
.shoutCardTitle { .shoutCardTitle {
@include font-size(2.2rem); @include font-size(2.2rem);
font-weight: 700; font-weight: 700;
line-height: 1.1; line-height: 1.1;
margin-bottom: 0.8rem; margin-bottom: 0.8rem;
@ -138,8 +139,9 @@
} }
.shoutCardSubtitle { .shoutCardSubtitle {
color: #141414;
@include font-size(1.8rem); @include font-size(1.8rem);
color: #141414;
font-weight: 400; font-weight: 400;
line-height: 1.3; line-height: 1.3;
margin-bottom: 1.4rem; margin-bottom: 1.4rem;
@ -269,6 +271,7 @@
.shoutCardTitle, .shoutCardTitle,
.shoutCardSubtitle { .shoutCardSubtitle {
@include font-size(2.6rem); @include font-size(2.6rem);
display: inline; display: inline;
line-height: 1.2; line-height: 1.2;
} }
@ -324,11 +327,11 @@
} }
.shoutCardSubtitle { .shoutCardSubtitle {
color: rgb(255 255 255 / 0.5); color: rgb(255 255 255 / 50%);
} }
&:global(.swiper-slide-active) .shoutCardCover { &:global(.swiper-slide-active) .shoutCardCover {
&:after { &::after {
background: linear-gradient(to bottom, rgb(0 0 0 / 0%) 40%, rgb(0 0 0 / 70%) 100%); background: linear-gradient(to bottom, rgb(0 0 0 / 0%) 40%, rgb(0 0 0 / 70%) 100%);
} }
} }
@ -336,7 +339,7 @@
.shoutCardWithCover { .shoutCardWithCover {
aspect-ratio: 16/9; aspect-ratio: 16/9;
padding: 0 2.4rem 0; padding: 0 2.4rem;
width: 100%; width: 100%;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
@ -561,7 +564,7 @@
} }
.shoutDate { .shoutDate {
color: rgb(255 255 255 / 0.5); color: rgb(255 255 255 / 50%);
} }
} }
@ -596,6 +599,7 @@
.shoutCardBigTitle { .shoutCardBigTitle {
.shoutCardTitle { .shoutCardTitle {
@include font-size(3.2rem); @include font-size(3.2rem);
display: block; display: block;
padding-right: 0; padding-right: 0;
} }
@ -609,6 +613,7 @@
.shoutCardTitle, .shoutCardTitle,
.shoutCardSubtitle { .shoutCardSubtitle {
@include font-size(2.2rem); @include font-size(2.2rem);
display: inline; display: inline;
line-height: 1.2; line-height: 1.2;
} }
@ -634,8 +639,9 @@
.shoutCardTitle, .shoutCardTitle,
.shoutCardSubtitle { .shoutCardSubtitle {
display: inline;
@include font-size(1.8rem); @include font-size(1.8rem);
display: inline;
} }
.shoutCardSubtitle { .shoutCardSubtitle {
@ -705,12 +711,14 @@
.shoutCardTitle { .shoutCardTitle {
@include font-size(4rem); @include font-size(4rem);
font-weight: 900; font-weight: 900;
line-height: 1.1; line-height: 1.1;
} }
.shoutCardSubtitle { .shoutCardSubtitle {
@include font-size(2.4rem); @include font-size(2.4rem);
flex: 1; flex: 1;
} }
} }

View File

@ -68,8 +68,9 @@
} }
a:link { a:link {
border: none;
@include font-size(1.4rem); @include font-size(1.4rem);
border: none;
font-weight: bold; font-weight: bold;
padding-right: 0.3em; padding-right: 0.3em;
white-space: nowrap; white-space: nowrap;
@ -87,6 +88,7 @@
h4 { h4 {
@include font-size(2.6rem); @include font-size(2.6rem);
font-weight: bold; font-weight: bold;
padding-right: 1em; padding-right: 1em;
} }

View File

@ -18,6 +18,7 @@
.counter { .counter {
@include font-size(1.2rem); @include font-size(1.2rem);
align-items: center; align-items: center;
align-self: flex-start; align-self: flex-start;
background: #f6f6f6; background: #f6f6f6;
@ -89,6 +90,7 @@
h4 { h4 {
@include font-size(1.2rem); @include font-size(1.2rem);
font-weight: bold; font-weight: bold;
color: #9fa1a7; color: #9fa1a7;
cursor: pointer; cursor: pointer;

View File

@ -87,6 +87,7 @@
.disclaimer { .disclaimer {
@include font-size(1.2rem); @include font-size(1.2rem);
color: #9fa1a7; color: #9fa1a7;
margin-bottom: 0; margin-bottom: 0;
} }
@ -127,13 +128,15 @@
} }
.authLink { .authLink {
cursor: pointer;
@include font-size(1.6rem); @include font-size(1.6rem);
cursor: pointer;
font-weight: 500; font-weight: 500;
} }
.authSubtitle { .authSubtitle {
@include font-size(1.5rem); @include font-size(1.5rem);
margin-bottom: 1em; margin-bottom: 1em;
} }

View File

@ -7,6 +7,7 @@
.text { .text {
@include font-size(1.5rem); @include font-size(1.5rem);
font-weight: 500; font-weight: 500;
margin-bottom: 1em; margin-bottom: 1em;
text-align: center; text-align: center;

View File

@ -1,5 +1,6 @@
.subnavigation { .subnavigation {
@include font-size(1.4rem); @include font-size(1.4rem);
height: 6rem; height: 6rem;
line-height: 6rem; line-height: 6rem;
margin-bottom: 5rem !important; margin-bottom: 5rem !important;

View File

@ -35,6 +35,7 @@
.topicTitle { .topicTitle {
@include font-size(2.2rem); @include font-size(2.2rem);
font-weight: bold; font-weight: bold;
margin-bottom: 1.2rem; margin-bottom: 1.2rem;
margin-top: 0.5rem !important; margin-top: 0.5rem !important;
@ -59,6 +60,7 @@
.topicDescription { .topicDescription {
@include font-size(1.4rem); @include font-size(1.4rem);
font-weight: 500; font-weight: 500;
color: #696969; color: #696969;
line-height: 1.3; line-height: 1.3;
@ -74,6 +76,7 @@
.topicDetails { .topicDetails {
@include font-size(1.6rem); @include font-size(1.6rem);
color: #9fa1a7; color: #9fa1a7;
display: flex; display: flex;
margin-bottom: 1em; margin-bottom: 1em;
@ -85,6 +88,7 @@
.topicDetailsItem { .topicDetailsItem {
@include font-size(1.4rem); @include font-size(1.4rem);
margin-right: 1.6rem; margin-right: 1.6rem;
white-space: nowrap; white-space: nowrap;

View File

@ -5,8 +5,9 @@
text-align: center; text-align: center;
h1 { h1 {
color: #2638d9;
@include font-size(2rem); @include font-size(2rem);
color: #2638d9;
text-transform: uppercase; text-transform: uppercase;
} }
} }

View File

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

View File

@ -4,6 +4,7 @@
.feedNavigation { .feedNavigation {
@include font-size(1.6rem); @include font-size(1.6rem);
font-weight: 500; font-weight: 500;
h4 { h4 {
@ -39,6 +40,7 @@
.feedAside { .feedAside {
h4 { h4 {
@include font-size(2.2rem); @include font-size(2.2rem);
font-weight: bold; font-weight: bold;
margin-bottom: 2.4rem; margin-bottom: 2.4rem;
} }
@ -51,9 +53,10 @@
} }
.topic { .topic {
@include font-size(1.2rem);
background: transparentize(#2638d9, 0.95); background: transparentize(#2638d9, 0.95);
display: inline-block; display: inline-block;
@include font-size(1.2rem);
font-weight: bold; font-weight: bold;
line-height: 3.4rem; line-height: 3.4rem;
margin: 0 0.6rem 0.6rem 0; margin: 0 0.6rem 0.6rem 0;
@ -88,6 +91,7 @@
ul { ul {
@include font-size(1.4rem); @include font-size(1.4rem);
font-weight: bold; font-weight: bold;
margin: 1rem 0 0; margin: 1rem 0 0;
line-height: 1.3; line-height: 1.3;
@ -97,7 +101,7 @@
padding-left: 2.6rem; padding-left: 2.6rem;
position: relative; position: relative;
&:before { &::before {
background: url(/public/icons/knowledge-base-bullet.svg) no-repeat; background: url(/public/icons/knowledge-base-bullet.svg) no-repeat;
content: ''; content: '';
height: 1.6rem; height: 1.6rem;
@ -140,6 +144,7 @@
.commentBody { .commentBody {
@include font-size(1.4rem); @include font-size(1.4rem);
margin-bottom: 1.2rem; margin-bottom: 1.2rem;
line-clamp: 3; line-clamp: 3;
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
@ -155,7 +160,7 @@
-webkit-line-clamp: 1; -webkit-line-clamp: 1;
a { a {
color: rgb(0 0 0 / 0.65); color: rgb(0 0 0 / 65%);
&:hover { &:hover {
color: #fff; color: #fff;
@ -166,5 +171,6 @@
.commentArticleTitle, .commentArticleTitle,
.commentAuthor { .commentAuthor {
@include font-size(1.2rem); @include font-size(1.2rem);
font-weight: 500; font-weight: 500;
} }

View File

@ -6,7 +6,7 @@
position: relative; position: relative;
width: 4.6rem; width: 4.6rem;
&:before { &::before {
background: #fff; background: #fff;
border-radius: 100%; border-radius: 100%;
content: ''; content: '';
@ -41,14 +41,14 @@
padding: 0; padding: 0;
position: relative; position: relative;
&:before { &::before {
display: none; display: none;
} }
} }
&:checked + label { &:checked + label {
.switcher { .switcher {
&:before { &::before {
left: 2.4rem; left: 2.4rem;
} }
} }

View File

@ -2,7 +2,7 @@ import { clsx } from 'clsx'
import styles from './DarkModeToggle.module.scss' import styles from './DarkModeToggle.module.scss'
import { Icon } from '../Icon' import { Icon } from '../Icon'
import { useLocalize } from '../../../context/localize' import { useLocalize } from '../../../context/localize'
import { createEffect, createSignal, onCleanup, onMount } from 'solid-js' import { createSignal, onCleanup, onMount } from 'solid-js'
import { createPrefersDark } from '@solid-primitives/media' import { createPrefersDark } from '@solid-primitives/media'
type Props = { type Props = {

View File

@ -59,7 +59,7 @@
line-height: 1; line-height: 1;
user-select: none; user-select: none;
transition: opacity 0.3s ease-in-out; transition: opacity 0.3s ease-in-out;
background: rgba(255, 255, 255, 0.8); background: rgb(255 255 255 / 80%);
&.visible { &.visible {
opacity: 1; opacity: 1;

View File

@ -1,5 +1,6 @@
.statMetrics { .statMetrics {
@include font-size(1.7rem); @include font-size(1.7rem);
color: #9fa1a7; color: #9fa1a7;
display: flex; display: flex;
margin: 0 0 1em; margin: 0 0 1em;

View File

@ -11,6 +11,7 @@
flex-direction: row; flex-direction: row;
margin-top: auto; margin-top: auto;
} }
.deleteAction { .deleteAction {
position: absolute; position: absolute;
top: -15px; top: -15px;

View File

@ -1,5 +1,13 @@
import { Accessor, JSX, Resource, createEffect } from 'solid-js' import type { Accessor, JSX, Resource } from 'solid-js'
import { createContext, createMemo, createResource, createSignal, onMount, useContext } from 'solid-js' import {
createEffect,
createContext,
createMemo,
createResource,
createSignal,
onMount,
useContext
} from 'solid-js'
import type { AuthResult, User } from '../graphql/types.gen' import type { AuthResult, User } from '../graphql/types.gen'
import { apiClient } from '../utils/apiClient' import { apiClient } from '../utils/apiClient'
import { resetToken, setToken } from '../graphql/privateGraphQLClient' import { resetToken, setToken } from '../graphql/privateGraphQLClient'

View File

@ -1,4 +1,4 @@
import { createEffect, createMemo, createSignal, lazy, onMount, Show, Suspense } from 'solid-js' import { createMemo, createSignal, lazy, onMount, Show, Suspense } from 'solid-js'
import { PageLayout } from '../components/_shared/PageLayout' import { PageLayout } from '../components/_shared/PageLayout'
import { Loading } from '../components/_shared/Loading' import { Loading } from '../components/_shared/Loading'
import { useSession } from '../context/session' import { useSession } from '../context/session'

View File

@ -1,11 +1,12 @@
import type { PageContext } from '../renderer/types' import type { PageContext } from '../renderer/types'
import { apiClient } from '../utils/apiClient' import { apiClient } from '../utils/apiClient'
import type { PageProps } from './types' import type { PageProps } from './types'
import { PRERENDERED_ARTICLES_COUNT } from './layoutShouts.page'
export const onBeforeRender = async (pageContext: PageContext) => { export const onBeforeRender = async (pageContext: PageContext) => {
const { layout } = pageContext.routeParams const { layout } = pageContext.routeParams
const layoutShouts = await apiClient.getShouts({ filters: { layout }, limit: 50 }) const layoutShouts = await apiClient.getShouts({ filters: { layout }, limit: PRERENDERED_ARTICLES_COUNT })
const pageProps: PageProps = { layoutShouts } const pageProps: PageProps = { layoutShouts }

View File

@ -1,9 +1,8 @@
import { PageLayout } from '../components/_shared/PageLayout' import { PageLayout } from '../components/_shared/PageLayout'
import type { PageProps } from './types' import type { LayoutType, PageProps } from './types'
import { createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js' import { createEffect, createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js'
import { loadShouts, resetSortedArticles } from '../stores/zine/articles' import { loadShouts, resetSortedArticles, useArticlesStore } from '../stores/zine/articles'
import { useRouter } from '../stores/router' import { router, useRouter } from '../stores/router'
import { LayoutType, useLayoutsStore } from '../stores/zine/layouts'
import { Loading } from '../components/_shared/Loading' import { Loading } from '../components/_shared/Loading'
import { restoreScrollPosition, saveScrollPosition } from '../utils/scroll' import { restoreScrollPosition, saveScrollPosition } from '../utils/scroll'
import type { Shout } from '../graphql/types.gen' import type { Shout } from '../graphql/types.gen'
@ -18,42 +17,38 @@ import { Row1 } from '../components/Feed/Row1'
import styles from '../styles/Topic.module.scss' import styles from '../styles/Topic.module.scss'
import { ArticleCard } from '../components/Feed/ArticleCard' import { ArticleCard } from '../components/Feed/ArticleCard'
import { useLocalize } from '../context/localize' import { useLocalize } from '../context/localize'
import { getPagePath } from '@nanostores/router'
import { Title } from '@solidjs/meta'
export const PRERENDERED_ARTICLES_COUNT = 21 export const PRERENDERED_ARTICLES_COUNT = 27
const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3 const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3
export const LayoutShoutsPage = (props: PageProps) => { export const LayoutShoutsPage = (props: PageProps) => {
const { t } = useLocalize() const { t } = useLocalize()
const getLayout = createMemo<LayoutType>(() => {
const { page: getPage } = useRouter() const { page: getPage } = useRouter()
const page = getPage()
if (page.route !== 'expo') { const getLayout = createMemo<LayoutType>(() => {
throw new Error('ts guard') const layout = getPage().params['layout']
}
const { layout } = page.params
return layout as LayoutType return layout as LayoutType
}) })
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const { sortedLayoutShouts, loadLayoutShoutsBy } = useLayoutsStore(getLayout(), props.layoutShouts)
const sortedArticles = createMemo<Shout[]>(() => sortedLayoutShouts().get(getLayout()) || [])
const loadMoreLayout = async (_kind: LayoutType) => {
saveScrollPosition()
const { hasMore } = await loadLayoutShoutsBy({
// filters: { layout: kind },
limit: LOAD_MORE_PAGE_SIZE, const { sortedArticles } = useArticlesStore({
shouts: props.layoutShouts
})
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
const loadMore = async (count) => {
saveScrollPosition()
const { hasMore } = await loadShouts({
filters: { layout: getLayout() },
limit: count,
offset: sortedArticles().length offset: sortedArticles().length
}) })
setIsLoadMoreButtonVisible(hasMore) setIsLoadMoreButtonVisible(hasMore)
restoreScrollPosition() restoreScrollPosition()
} }
onMount(async () => {
if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) {
loadMoreLayout(getLayout())
}
})
const title = createMemo(() => { const title = createMemo(() => {
const l = getLayout() const l = getLayout()
if (l === 'audio') return t('Audio') if (l === 'audio') return t('Audio')
@ -65,61 +60,79 @@ export const LayoutShoutsPage = (props: PageProps) => {
const pages = createMemo<Shout[][]>(() => const pages = createMemo<Shout[][]>(() =>
splitToPages(sortedArticles(), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE) splitToPages(sortedArticles(), PRERENDERED_ARTICLES_COUNT, LOAD_MORE_PAGE_SIZE)
) )
const isLoaded = createMemo(() => Boolean(sortedArticles()))
onMount(async () => { const isLoaded = createMemo(() => Boolean(props.layoutShouts))
if (!isLoaded()) {
await loadShouts({ filters: { layout: getLayout() }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) onMount(() => {
if (isLoaded()) {
return
}
loadMore(PRERENDERED_ARTICLES_COUNT + LOAD_MORE_PAGE_SIZE)
})
onMount(() => {
if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) {
loadMore(LOAD_MORE_PAGE_SIZE)
} }
}) })
onCleanup(() => resetSortedArticles()) createEffect((prevLayout) => {
if (prevLayout !== getLayout()) {
resetSortedArticles()
loadMore(PRERENDERED_ARTICLES_COUNT + LOAD_MORE_PAGE_SIZE)
}
return getLayout()
}, getLayout())
onCleanup(() => {
resetSortedArticles()
})
const handleLoadMoreClick = () => {
loadMore(LOAD_MORE_PAGE_SIZE)
}
return (
<PageLayout>
<Title>{title()}</Title>
<Show when={isLoaded()} fallback={<Loading />}>
<div class={styles.topicPage}>
<Show when={getLayout()}>
<div class="wide-container">
<h1>{title()}</h1>
</div>
const ModeSwitcher = () => (
<div class="wide-container"> <div class="wide-container">
<div class={clsx(styles.groupControls, 'row group__controls')}> <div class={clsx(styles.groupControls, 'row group__controls')}>
<div class="col-md-16"> <div class="col-md-16">
<ul class="view-switcher"> <ul class="view-switcher">
<li classList={{ 'view-switcher__item--selected': getLayout() === 'audio' }}> <li classList={{ 'view-switcher__item--selected': getLayout() === 'audio' }}>
<a href="/expo/audio">{t('Audio')}</a> <a href={getPagePath(router, 'expo', { layout: 'audio' })}>{t('Audio')}</a>
</li> </li>
<li classList={{ 'view-switcher__item--selected': getLayout() === 'video' }}> <li classList={{ 'view-switcher__item--selected': getLayout() === 'video' }}>
<a href="/expo/video">{t('Video')}</a> <a href={getPagePath(router, 'expo', { layout: 'video' })}>{t('Video')}</a>
</li> </li>
<li classList={{ 'view-switcher__item--selected': getLayout() === 'image' }}> <li classList={{ 'view-switcher__item--selected': getLayout() === 'image' }}>
<a href="/expo/image">{t('Artworks')}</a> <a href={getPagePath(router, 'expo', { layout: 'image' })}>{t('Artworks')}</a>
</li> </li>
<li classList={{ 'view-switcher__item--selected': getLayout() === 'literature' }}> <li classList={{ 'view-switcher__item--selected': getLayout() === 'literature' }}>
<a href="/expo/literature">{t('Literature')}</a> <a href={getPagePath(router, 'expo', { layout: 'literature' })}>{t('Literature')}</a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="col-md-8">
<div class="mode-switcher">
{`${t('Show')} `}
<span class="mode-switcher__control">{t('All posts')}</span>
</div> </div>
</div> </div>
</div>
</div>
)
return (
<PageLayout>
<Show when={isLoaded()} fallback={<Loading />}>
<div class={styles.topicPage}>
<Show when={getLayout() && Boolean(sortedArticles())}>
<div class="wide-container">
<h1>{title()}</h1>
</div>
<ModeSwitcher /> <Show when={sortedArticles().length > 0} fallback={<Loading />}>
<Row1 article={sortedArticles()[0]} /> <Row1 article={sortedArticles()[0]} />
<Row2 articles={sortedArticles().slice(1, 3)} /> <Row2 articles={sortedArticles().slice(1, 3)} />
<Slider title={title()}> <Slider title={title()}>
<For each={sortedArticles().slice(5, 11)}> <For each={sortedArticles().slice(5, 11)}>
{(a: Shout) => ( {(article) => (
<ArticleCard <ArticleCard
article={a} article={article}
settings={{ settings={{
additionalClass: 'swiper-slide', additionalClass: 'swiper-slide',
isFloorImportant: true, isFloorImportant: true,
@ -156,12 +169,13 @@ export const LayoutShoutsPage = (props: PageProps) => {
<Show when={isLoadMoreButtonVisible()}> <Show when={isLoadMoreButtonVisible()}>
<p class="load-more-container"> <p class="load-more-container">
<button class="button" onClick={() => loadMoreLayout(getLayout())}> <button class="button" onClick={handleLoadMoreClick}>
{t('Load more')} {t('Load more')}
</button> </button>
</p> </p>
</Show> </Show>
</Show> </Show>
</Show>
</div> </div>
</Show> </Show>
</PageLayout> </PageLayout>

View File

@ -1,6 +1,5 @@
// in a separate file to avoid circular dependencies // in a separate file to avoid circular dependencies
import type { Author, Chat, Shout, Topic } from '../graphql/types.gen' import type { Author, Chat, Shout, Topic } from '../graphql/types.gen'
import type { LayoutType } from '../stores/zine/layouts'
// all the things (she said) that could be passed from the server // all the things (she said) that could be passed from the server
export type PageProps = { export type PageProps = {
@ -15,7 +14,7 @@ export type PageProps = {
topic?: Topic topic?: Topic
allTopics?: Topic[] allTopics?: Topic[]
searchQuery?: string searchQuery?: string
layout?: LayoutType layout?: string // LayoutType
// other types? // other types?
searchResults?: Shout[] searchResults?: Shout[]
chats?: Chat[] chats?: Chat[]
@ -32,3 +31,5 @@ export type UploadFile = {
size: number size: number
file: File file: File
} }
export type LayoutType = 'article' | 'audio' | 'video' | 'image' | 'literature'

View File

@ -1,48 +0,0 @@
import type { Shout, LoadShoutsOptions } from '../../graphql/types.gen'
import { apiClient } from '../../utils/apiClient'
import { createSignal } from 'solid-js'
export type LayoutType = 'article' | 'audio' | 'video' | 'image' | 'literature'
const [sortedLayoutShouts, setSortedLayoutShouts] = createSignal<Map<LayoutType, Shout[]>>(new Map())
const addLayoutShouts = (layout: LayoutType, shouts: Shout[]) => {
setSortedLayoutShouts((prevSorted: Map<LayoutType, Shout[]>) => {
const siblings = prevSorted.get(layout)
if (siblings) {
const uniqued = [...new Set([...siblings, ...shouts])]
prevSorted.set(layout, uniqued)
}
return prevSorted
})
}
export const resetSortedLayoutShouts = () => {
setSortedLayoutShouts(new Map())
}
export const loadLayoutShoutsBy = async (options: LoadShoutsOptions): Promise<{ hasMore: boolean }> => {
const newLayoutShouts = await apiClient.getShouts({
...options,
limit: options.limit + 1
})
const hasMore = newLayoutShouts.length === options.limit + 1
if (hasMore) {
newLayoutShouts.splice(-1)
}
addLayoutShouts(options.filters.layout as LayoutType, newLayoutShouts)
return { hasMore }
}
export const useLayoutsStore = (layout: LayoutType, initialData: Shout[]) => {
addLayoutShouts(layout, initialData || [])
return {
addLayoutShouts,
sortedLayoutShouts,
loadLayoutShoutsBy
}
}

View File

@ -1,6 +1,7 @@
.allTopicsPage { .allTopicsPage {
.group { .group {
@include font-size(1.6rem); @include font-size(1.6rem);
margin: 3em 0 9.6rem; margin: 3em 0 9.6rem;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
@ -50,11 +51,12 @@
} }
.alphabet { .alphabet {
@include font-size(1.5rem);
color: rgba(0 0 0 / 20%); color: rgba(0 0 0 / 20%);
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
font-weight: 700; font-weight: 700;
@include font-size(1.5rem);
margin: 1.5em -3% 0 0; margin: 1.5em -3% 0 0;
li { li {
@ -66,6 +68,7 @@
.articlesCounter { .articlesCounter {
@include font-size(1.2rem); @include font-size(1.2rem);
margin-left: 0.5em; margin-left: 0.5em;
vertical-align: super; vertical-align: super;
} }

View File

@ -545,12 +545,14 @@ figure {
figcaption { figcaption {
@include font-size(1.2rem); @include font-size(1.2rem);
color: #9fa1a7; color: #9fa1a7;
} }
} }
.view-switcher { .view-switcher {
@include font-size(1.4rem); @include font-size(1.4rem);
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
font-weight: 500; font-weight: 500;
@ -828,6 +830,7 @@ figure {
.content-index { .content-index {
@include font-size(1.4rem); @include font-size(1.4rem);
line-height: 1.4; line-height: 1.4;
margin: 0 3.6rem 2em 0; margin: 0 3.6rem 2em 0;