Merge pull request #297 from Discours/fix/404_page

WIP
This commit is contained in:
Kosta 2023-11-04 18:01:15 +02:00 committed by GitHub
commit d4e0d43a55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 5025 additions and 1832 deletions

View File

@ -1,6 +1,6 @@
{ {
"*.{js,ts,tsx,json,scss,css,html}": "prettier --write", "*.{js,mjs,ts,tsx,json,scss,css,html}": "prettier --write",
"package.json": "sort-package-json", "package.json": "sort-package-json",
"*.{scss,css}": "stylelint", "*.{scss,css}": "stylelint",
"*.{ts,tsx,js}": "eslint --fix" "*.{ts,tsx,js,mjs}": "eslint --fix"
} }

View File

@ -1,13 +1,13 @@
import { renderPage } from 'vite-plugin-ssr/server' import { renderPage } from 'vike/server'
export default async function handler(req, res) { export default async function handler(req, res) {
const { url, cookies } = req const { url, cookies } = req
const pageContext = await renderPage({ urlOriginal: url, cookies }) const pageContext = await renderPage({ urlOriginal: url, cookies })
const { httpResponse, errorWhileRendering } = pageContext const { httpResponse, errorWhileRendering, is404 } = pageContext
if (errorWhileRendering) { if (errorWhileRendering && !is404) {
console.error(errorWhileRendering) console.error(errorWhileRendering)
res.statusCode = 500 res.statusCode = 500
res.end() res.end()

5977
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
"version": "0.8.0", "version": "0.8.0",
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"type": "module",
"scripts": { "scripts": {
"build": "vite build", "build": "vite build",
"check": "npm run lint && npm run typecheck", "check": "npm run lint && npm run typecheck",
@ -38,11 +39,11 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.21.8", "@babel/core": "7.21.8",
"@graphql-codegen/cli": "3.2.2", "@graphql-codegen/cli": "5.0.0",
"@graphql-codegen/typescript": "3.0.4", "@graphql-codegen/typescript": "4.0.1",
"@graphql-codegen/typescript-operations": "3.0.4", "@graphql-codegen/typescript-operations": "4.0.1",
"@graphql-codegen/typescript-urql": "3.7.3", "@graphql-codegen/typescript-urql": "4.0.0",
"@graphql-codegen/urql-introspection": "2.2.1", "@graphql-codegen/urql-introspection": "3.0.0",
"@graphql-tools/url-loader": "7.17.18", "@graphql-tools/url-loader": "7.17.18",
"@graphql-typed-document-node/core": "3.2.0", "@graphql-typed-document-node/core": "3.2.0",
"@hocuspocus/provider": "2.0.6", "@hocuspocus/provider": "2.0.6",
@ -55,7 +56,7 @@
"@solid-primitives/share": "2.0.4", "@solid-primitives/share": "2.0.4",
"@solid-primitives/storage": "1.3.9", "@solid-primitives/storage": "1.3.9",
"@solid-primitives/upload": "0.0.110", "@solid-primitives/upload": "0.0.110",
"@solidjs/meta": "0.28.2", "@solidjs/meta": "0.29.1",
"@thisbeyond/solid-select": "0.14.0", "@thisbeyond/solid-select": "0.14.0",
"@tiptap/core": "2.0.3", "@tiptap/core": "2.0.3",
"@tiptap/extension-blockquote": "2.0.3", "@tiptap/extension-blockquote": "2.0.3",
@ -86,27 +87,27 @@
"@tiptap/extension-text": "2.0.3", "@tiptap/extension-text": "2.0.3",
"@tiptap/extension-underline": "2.0.3", "@tiptap/extension-underline": "2.0.3",
"@tiptap/extension-youtube": "2.0.3", "@tiptap/extension-youtube": "2.0.3",
"@types/js-cookie": "3.0.4", "@types/js-cookie": "3.0.5",
"@types/node": "20.1.1", "@types/node": "20.8.10",
"@typescript-eslint/eslint-plugin": "6.7.3", "@typescript-eslint/eslint-plugin": "6.9.1",
"@typescript-eslint/parser": "6.7.3", "@typescript-eslint/parser": "6.9.1",
"@urql/core": "3.2.2", "@urql/core": "3.2.2",
"@urql/devtools": "2.0.3", "@urql/devtools": "2.0.3",
"babel-preset-solid": "1.7.4", "babel-preset-solid": "1.8.4",
"bootstrap": "5.3.2", "bootstrap": "5.3.2",
"clsx": "2.0.0", "clsx": "2.0.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"debounce": "1.2.1", "debounce": "1.2.1",
"eslint": "8.50.0", "eslint": "8.53.0",
"eslint-config-stylelint": "20.0.0", "eslint-config-stylelint": "20.0.0",
"eslint-import-resolver-typescript": "3.6.1", "eslint-import-resolver-typescript": "3.6.1",
"eslint-plugin-import": "2.28.1", "eslint-plugin-import": "2.29.0",
"eslint-plugin-jest": "27.4.0", "eslint-plugin-jest": "27.6.0",
"eslint-plugin-jsx-a11y": "6.7.1", "eslint-plugin-jsx-a11y": "6.8.0",
"eslint-plugin-promise": "6.1.1", "eslint-plugin-promise": "6.1.1",
"eslint-plugin-solid": "0.13.0", "eslint-plugin-solid": "0.13.0",
"eslint-plugin-sonarjs": "0.21.0", "eslint-plugin-sonarjs": "0.23.0",
"eslint-plugin-unicorn": "48.0.1", "eslint-plugin-unicorn": "49.0.0",
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"graphql": "16.6.0", "graphql": "16.6.0",
"graphql-tag": "2.12.6", "graphql-tag": "2.12.6",
@ -117,7 +118,7 @@
"javascript-time-ago": "2.5.9", "javascript-time-ago": "2.5.9",
"jest": "29.7.0", "jest": "29.7.0",
"js-cookie": "3.0.5", "js-cookie": "3.0.5",
"lint-staged": "14.0.1", "lint-staged": "15.0.2",
"loglevel": "1.8.1", "loglevel": "1.8.1",
"loglevel-plugin-prefix": "0.8.4", "loglevel-plugin-prefix": "0.8.4",
"markdown-it": "13.0.1", "markdown-it": "13.0.1",
@ -127,30 +128,30 @@
"markdown-it-replace-link": "1.2.0", "markdown-it-replace-link": "1.2.0",
"nanostores": "0.7.4", "nanostores": "0.7.4",
"prettier": "3.0.3", "prettier": "3.0.3",
"prettier-eslint": "15.0.1", "prettier-eslint": "16.1.2",
"prosemirror-history": "1.3.0", "prosemirror-history": "1.3.0",
"prosemirror-trailing-node": "2.0.3", "prosemirror-trailing-node": "2.0.3",
"prosemirror-view": "1.30.2", "prosemirror-view": "1.30.2",
"rollup": "3.21.6", "rollup": "3.21.6",
"sass": "1.68.0", "sass": "1.69.5",
"solid-js": "1.7.5", "solid-js": "1.8.5",
"solid-popper": "0.3.0", "solid-popper": "0.3.0",
"solid-tiptap": "0.6.0", "solid-tiptap": "0.6.0",
"solid-transition-group": "0.2.2", "solid-transition-group": "0.2.3",
"sort-package-json": "2.6.0", "sort-package-json": "2.6.0",
"stylelint": "15.10.3", "stylelint": "15.11.0",
"stylelint-config-standard-scss": "11.0.0", "stylelint-config-standard-scss": "11.1.0",
"stylelint-order": "6.0.3", "stylelint-order": "6.0.3",
"stylelint-scss": "5.2.1", "stylelint-scss": "5.3.0",
"swiper": "9.4.1", "swiper": "9.4.1",
"typescript": "5.2.2", "typescript": "5.2.2",
"typograf": "7.1.0", "typograf": "7.1.0",
"uniqolor": "1.1.0", "uniqolor": "1.1.0",
"vite": "4.3.9", "vike": "0.4.144",
"vite": "4.5.0",
"vite-plugin-mkcert": "1.16.0", "vite-plugin-mkcert": "1.16.0",
"vite-plugin-sass-dts": "1.3.11", "vite-plugin-sass-dts": "1.3.11",
"vite-plugin-solid": "2.7.0", "vite-plugin-solid": "2.7.2",
"vite-plugin-ssr": "0.4.123",
"y-prosemirror": "1.2.1", "y-prosemirror": "1.2.1",
"yjs": "13.6.0" "yjs": "13.6.0"
}, },

View File

@ -1,11 +1,13 @@
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;
} }
h2 { h2 {
@include font-size(4rem); @include font-size(4rem);
line-height: 1.1; line-height: 1.1;
} }
@ -70,6 +72,7 @@ img {
&[data-float='left'], &[data-float='left'],
&[data-float='right'] { &[data-float='right'] {
@include font-size(2.2rem); @include font-size(2.2rem);
line-height: 1.4; line-height: 1.4;
} }
@ -92,9 +95,10 @@ img {
ta-sub, ta-sub,
ta-selection-frame, ta-selection-frame,
ta-border-sub { ta-border-sub {
@include font-size(1.4rem);
background: #f1f2f3; background: #f1f2f3;
display: block; display: block;
@include font-size(1.4rem);
margin: 3.2rem 0; margin: 3.2rem 0;
padding: 3.2rem; padding: 3.2rem;
@ -303,6 +307,7 @@ img {
.shoutStatsItem { .shoutStatsItem {
@include font-size(1.5rem); @include font-size(1.5rem);
align-items: center; align-items: center;
font-weight: 500; font-weight: 500;
display: flex; display: flex;
@ -398,7 +403,7 @@ img {
cursor: default; cursor: default;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
color: rgb(0 0 0 / 0.4); color: rgb(0 0 0 / 40%);
flex: 1 40%; flex: 1 40%;
justify-content: end; justify-content: end;
margin-right: 0; margin-right: 0;
@ -441,6 +446,7 @@ img {
.topicsList { .topicsList {
@include font-size(1.2rem); @include font-size(1.2rem);
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8;
letter-spacing: 0.08em; letter-spacing: 0.08em;
margin-top: 1.6rem; margin-top: 1.6rem;
@ -486,6 +492,7 @@ img {
.commentsHeader { .commentsHeader {
@include font-size(2.4rem); @include font-size(2.4rem);
margin-bottom: 1em; margin-bottom: 1em;
.newReactions { .newReactions {
@ -519,6 +526,7 @@ img {
button { button {
@include font-size(1.5rem); @include font-size(1.5rem);
border-radius: 0.8rem; border-radius: 0.8rem;
margin-right: 1.2rem; margin-right: 1.2rem;
padding: 0.9rem 1.2rem; padding: 0.9rem 1.2rem;
@ -600,13 +608,14 @@ a[data-toggle='tooltip'] {
width: 0; width: 0;
height: 0; height: 0;
border-style: solid; border-style: solid;
border-width: 4px 4px 0 4px; border-width: 4px 4px 0;
border-color: var(--black-500) transparent transparent transparent; border-color: var(--black-500) transparent transparent transparent;
} }
} }
.lead { .lead {
@include font-size(1.8rem); @include font-size(1.8rem);
font-weight: 600; font-weight: 600;
b, b,

View File

@ -51,7 +51,6 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 40px; width: 40px;
height: 40px; height: 40px;
background: #141414; background: #141414;
@ -108,7 +107,7 @@
position: relative; position: relative;
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;
border-bottom: 2px solid #cccccc; border-bottom: 2px solid #ccc;
} }
.progressFilled { .progressFilled {
@ -126,7 +125,6 @@
position: absolute; position: absolute;
bottom: -10px; bottom: -10px;
right: -8px; right: -8px;
width: 8px; width: 8px;
height: 8px; height: 8px;
border-radius: 50%; border-radius: 50%;
@ -140,7 +138,6 @@
padding-top: 14px; padding-top: 14px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-weight: 500; font-weight: 500;
font-size: 12px; font-size: 12px;
line-height: 16px; line-height: 16px;
@ -157,7 +154,7 @@ $vendors-track: ('::-webkit-slider-runnable-track', '::-moz-range-track', '::-ms
$vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thumb'); $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thumb');
.volume { .volume {
-webkit-appearance: none; appearance: none;
height: 19px; height: 19px;
float: left; float: left;
outline: none; outline: none;
@ -182,7 +179,7 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
@each $vendor in $vendors-thumb { @each $vendor in $vendors-thumb {
&#{$vendor} { &#{$vendor} {
position: relative; position: relative;
-webkit-appearance: none; appearance: none;
box-sizing: content-box; box-sizing: content-box;
width: 8px; width: 8px;
height: 8px; height: 8px;
@ -190,7 +187,7 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
border: 4px solid var(--default-color); border: 4px solid var(--default-color);
background-color: var(--background-color); background-color: var(--background-color);
cursor: pointer; cursor: pointer;
margin: -7px 0 0 0; margin: -7px 0 0;
} }
&:active#{$vendor} { &:active#{$vendor} {
transform: scale(1.2); transform: scale(1.2);
@ -201,6 +198,7 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
&::-moz-range-progress { &::-moz-range-progress {
background-color: var(--background-color); background-color: var(--background-color);
} }
&::-moz-focus-outer { &::-moz-focus-outer {
border: 0; border: 0;
} }
@ -209,7 +207,6 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
.playlist { .playlist {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
list-style-type: none; list-style-type: none;
margin: 32px 0 16px; margin: 32px 0 16px;
padding: 0; padding: 0;
@ -222,7 +219,6 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
.playlistItem { .playlistItem {
display: flex; display: flex;
align-items: center; align-items: center;
min-height: 56px; min-height: 56px;
padding: 16px 0; padding: 16px 0;
} }
@ -319,6 +315,7 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
&:not([disabled]):hover { &:not([disabled]):hover {
border-color: var(--background-color-invert); border-color: var(--background-color-invert);
background: var(--background-color-invert); background: var(--background-color-invert);
img { img {
filter: var(--icon-filter-hover); filter: var(--icon-filter-hover);
} }
@ -334,7 +331,7 @@ $vendors-thumb: ('::-webkit-slider-thumb', '::-moz-moz-range-thumb', '::-ms-thum
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
padding: 8px 0 24px 0; padding: 8px 0 24px;
.description, .description,
.lyrics { .lyrics {

View File

@ -5,10 +5,6 @@
position: relative; position: relative;
list-style: none; list-style: none;
& .comment {
margin-right: -1rem;
}
&.isNew { &.isNew {
border-radius: 6px; border-radius: 6px;
background: rgb(38 56 217 / 5%); background: rgb(38 56 217 / 5%);
@ -19,6 +15,8 @@
} }
.comment { .comment {
margin-right: -1rem;
&::before, &::before,
&::after { &::after {
content: ''; content: '';

View File

@ -1,8 +1,7 @@
.AuthorLink { .AuthorLink {
.link { .link {
display: inline-flex; display: inline-flex;
flex-direction: row; flex-flow: row nowrap;
flex-wrap: nowrap;
align-items: center; align-items: center;
gap: 1rem; gap: 1rem;
justify-content: center; justify-content: center;
@ -33,6 +32,7 @@
.link { .link {
gap: 0.5rem; gap: 0.5rem;
} }
.name { .name {
font-size: 1.2rem; font-size: 1.2rem;
margin: 0; margin: 0;
@ -43,6 +43,7 @@
.link { .link {
gap: 1rem; gap: 1rem;
} }
.name { .name {
font-size: 1.4rem; font-size: 1.4rem;
} }

View File

@ -22,6 +22,7 @@
.info { .info {
@include font-size(1.4rem); @include font-size(1.4rem);
border: none; border: none;
display: flex; display: flex;
flex: 0 calc(100% - 5.2rem); flex: 0 calc(100% - 5.2rem);

View File

@ -79,6 +79,7 @@
height: 40px; height: 40px;
width: 40px; width: 40px;
min-width: 40px; min-width: 40px;
.letters { .letters {
font-size: 1.2rem; font-size: 1.2rem;
} }

View File

@ -1,5 +1,6 @@
.aboutDiscours { .aboutDiscours {
@include font-size(1.6rem); @include font-size(1.6rem);
background: #fef2f2; background: #fef2f2;
font-weight: 500; font-weight: 500;
margin-bottom: 6.4rem; margin-bottom: 6.4rem;
@ -8,6 +9,7 @@
h4 { h4 {
@include font-size(4rem); @include font-size(4rem);
font-weight: bold; font-weight: bold;
line-height: 1.1; line-height: 1.1;
margin-bottom: 2rem; margin-bottom: 2rem;

View File

@ -5,6 +5,7 @@
.draggable { .draggable {
margin: 8px 0; margin: 8px 0;
padding: 8px 0; padding: 8px 0;
&:hover { &:hover {
background: var(--placeholder-color-semi); background: var(--placeholder-color-semi);
} }

View File

@ -13,7 +13,7 @@
z-index: 2; z-index: 2;
font-weight: 500; font-weight: 500;
transition: 0.6s ease-in-out; transition: 0.6s ease-in-out;
background: rgba(white, 0.3); background: rgb(255 255 255 / 30%);
backdrop-filter: blur(4px); backdrop-filter: blur(4px);
border: 1px solid var(--secondary-color); border: 1px solid var(--secondary-color);
left: 100%; left: 100%;

View File

@ -269,6 +269,7 @@ figure[data-type='capturedImage'] {
flex-direction: column-reverse; flex-direction: column-reverse;
} }
/* stylelint-disable-next-line selector-type-no-unknown */
footnote { footnote {
display: inline-flex; display: inline-flex;
position: relative; position: relative;
@ -276,7 +277,7 @@ footnote {
width: 0.8rem; width: 0.8rem;
height: 1em; height: 1em;
&:before { &::before {
content: ''; content: '';
position: absolute; position: absolute;
width: 10px; width: 10px;

View File

@ -9,6 +9,7 @@
.simplifiedEditorField { .simplifiedEditorField {
@include font-size(1.4rem); @include font-size(1.4rem);
min-height: 100px; min-height: 100px;
.emptyNode:first-child::before { .emptyNode:first-child::before {
@ -92,7 +93,7 @@
} }
&.isFocused { &.isFocused {
//background: red; // background: red;
.controls { .controls {
opacity: 1; opacity: 1;
bottom: 0; bottom: 0;
@ -111,7 +112,7 @@
&.bordered { &.bordered {
box-sizing: border-box; box-sizing: border-box;
padding: 16px 12px 6px 12px; padding: 16px 12px 6px;
border-radius: 2px; border-radius: 2px;
border: 2px solid var(--black-100); border: 2px solid var(--black-100);
background: var(--white-500); background: var(--white-500);

View File

@ -79,6 +79,7 @@ export const Footnote = Node.create({
}, },
deleteFootnote: deleteFootnote:
() => () =>
// eslint-disable-next-line unicorn/consistent-function-scoping
({ tr, state }) => { ({ tr, state }) => {
const { selection } = state const { selection } = state
const { $from, $to } = selection const { $from, $to } = selection

View File

@ -134,9 +134,10 @@
} }
.shoutDate { .shoutDate {
@include font-size(1.2rem);
color: #9fa1a7; color: #9fa1a7;
font-weight: 500; font-weight: 500;
@include font-size(1.2rem);
} }
.shoutDetails { .shoutDetails {
@ -155,6 +156,7 @@
.shoutCardTitle { .shoutCardTitle {
@include font-size(2.2rem); @include font-size(2.2rem);
font-weight: 700; font-weight: 700;
line-height: 1.2; line-height: 1.2;
margin-bottom: 0.8rem; margin-bottom: 0.8rem;
@ -175,6 +177,7 @@
.shoutCardTitlesContainerFeedMode & { .shoutCardTitlesContainerFeedMode & {
@include font-size(3.2rem); @include font-size(3.2rem);
line-height: 1.1; line-height: 1.1;
} }
} }
@ -188,6 +191,7 @@
.shoutCardSubtitle { .shoutCardSubtitle {
@include font-size(1.8rem); @include font-size(1.8rem);
color: #141414; color: #141414;
font-weight: 400; font-weight: 400;
line-height: 1.3; line-height: 1.3;
@ -399,9 +403,10 @@
.shoutCardWithCover { .shoutCardWithCover {
aspect-ratio: 16/9; aspect-ratio: 16/9;
//padding: 0 2.4rem;
width: 100%; width: 100%;
// padding: 0 2.4rem;
@include media-breakpoint-down(xl) { @include media-breakpoint-down(xl) {
aspect-ratio: auto; aspect-ratio: auto;
height: 100%; height: 100%;
@ -707,6 +712,7 @@
.shoutCardTitle, .shoutCardTitle,
.shoutCardSubtitle { .shoutCardSubtitle {
@include font-size(1.8rem); @include font-size(1.8rem);
display: inline; display: inline;
} }

View File

@ -158,7 +158,7 @@ export const ArticleCard = (props: ArticleCardProps) => {
[styles.shoutCardTitlesContainerFeedMode]: props.settings?.isFeedMode [styles.shoutCardTitlesContainerFeedMode]: props.settings?.isFeedMode
})} })}
> >
<a href={`/${props.article.slug || ''}`}> <a href={getPagePath(router, 'article', { slug: props.article.slug })}>
<div class={styles.shoutCardTitle}> <div class={styles.shoutCardTitle}>
<span class={styles.shoutCardLinkWrapper}> <span class={styles.shoutCardLinkWrapper}>
<span class={styles.shoutCardLinkContainer}>{title}</span> <span class={styles.shoutCardLinkContainer}>{title}</span>

View File

@ -125,6 +125,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

@ -1,5 +1,6 @@
.Search { .Search {
flex: 1; flex: 1;
.field { .field {
position: relative; position: relative;
background: #fff; background: #fff;

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;
@ -94,13 +95,14 @@
color: var(--default-color-invert) !important; color: var(--default-color-invert) !important;
&:hover { &:hover {
color: rgb(255, 255, 255, 0.6) !important; color: rgb(255 255 255 / 60%) !important;
} }
} }
} }
.authActions { .authActions {
@include font-size(1.5rem); @include font-size(1.5rem);
margin-top: 1.6rem; margin-top: 1.6rem;
text-align: center; text-align: center;

View File

@ -3,6 +3,7 @@
.confirmModalTitle { .confirmModalTitle {
@include font-size(3.2rem); @include font-size(3.2rem);
font-weight: 700; font-weight: 700;
color: var(--default-color); color: var(--default-color);
text-align: center; text-align: center;

View File

@ -128,10 +128,11 @@
.mainNavigation { .mainNavigation {
font-size: 1.4rem !important; font-size: 1.4rem !important;
// margin: 0 0 0 -0.4rem !important;
opacity: 1; opacity: 1;
transition: opacity 0.3s; transition: opacity 0.3s;
// margin: 0 0 0 -0.4rem !important;
@include media-breakpoint-down(lg) { @include media-breakpoint-down(lg) {
background: var(--background-color); background: var(--background-color);
bottom: 0; bottom: 0;
@ -294,9 +295,10 @@
.burgerContainer { .burgerContainer {
box-sizing: content-box; box-sizing: content-box;
display: inline-flex; display: inline-flex;
// float: right;
padding-left: 0; padding-left: 0;
// float: right;
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
padding-left: divide($container-padding-x, 2); padding-left: divide($container-padding-x, 2);
} }

View File

@ -1,5 +1,6 @@
.navigationHeader { .navigationHeader {
@include font-size(1.8rem); @include font-size(1.8rem);
font-weight: bold; font-weight: bold;
margin-top: 1.1em; margin-top: 1.1em;
} }

View File

@ -8,8 +8,6 @@
border-radius: 16px; border-radius: 16px;
padding: 16px; padding: 16px;
background-color: var(--yellow-50); background-color: var(--yellow-50);
// TODO: check markup
// font-weight: 700;
line-height: 20px; line-height: 20px;
cursor: pointer; cursor: pointer;
transition: background-color 100ms; transition: background-color 100ms;

View File

@ -100,8 +100,7 @@ $transition-duration: 200ms;
} }
.periodTitle { .periodTitle {
// TODO: check markup margin: 32px 0 16px;
margin: 32px 0 16px 0;
color: var(--black-400); color: var(--black-400);
font-size: 12px; font-size: 12px;
font-weight: 500; font-weight: 500;

View File

@ -56,6 +56,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;
@ -84,6 +85,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;

View File

@ -23,7 +23,6 @@
min-width: 64px; min-width: 64px;
font-size: 17px; font-size: 17px;
padding: 8px 16px; padding: 8px 16px;
background: var(--background-color-invert); background: var(--background-color-invert);
color: var(--default-color-invert); color: var(--default-color-invert);
border: none; border: none;

View File

@ -36,11 +36,12 @@
} }
.info { .info {
@include font-size(1.4rem);
border: none; border: none;
display: flex; display: flex;
flex: 0 calc(100% - 5.2rem); flex: 0 calc(100% - 5.2rem);
flex-direction: column; flex-direction: column;
@include font-size(1.4rem);
margin-bottom: 1rem; margin-bottom: 1rem;
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {

View File

@ -1,4 +1,4 @@
import { createEffect, createMemo, createSignal, For, onMount, Show } from 'solid-js' import { createEffect, createMemo, createSignal, For, Show } from 'solid-js'
import type { Author } from '../../graphql/types.gen' import type { Author } from '../../graphql/types.gen'
import { setAuthorsSort, useAuthorsStore } from '../../stores/zine/authors' import { setAuthorsSort, useAuthorsStore } from '../../stores/zine/authors'
import { useRouter } from '../../stores/router' import { useRouter } from '../../stores/router'

View File

@ -87,6 +87,7 @@
.alphabet { .alphabet {
@include font-size(1.5rem); @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;
@ -106,6 +107,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

@ -1,4 +1,4 @@
import { createEffect, createMemo, createSignal, For, onMount, Show } from 'solid-js' import { createEffect, createMemo, createSignal, For, Show } from 'solid-js'
import type { Topic } from '../../graphql/types.gen' import type { Topic } from '../../graphql/types.gen'
import { setTopicsSort, useTopicsStore } from '../../stores/zine/topics' import { setTopicsSort, useTopicsStore } from '../../stores/zine/topics'

View File

@ -83,8 +83,8 @@
max-height 0.5s, max-height 0.5s,
margin-bottom 0s 0.3s; margin-bottom 0s 0.3s;
&:after { &::after {
background-image: linear-gradient(to top, #fff, rgb(255 255 255 / 0.8), rgb(255 255 255 / 0)); background-image: linear-gradient(to top, #fff, rgb(255 255 255 / 80%), rgb(255 255 255 / 0%));
bottom: 0; bottom: 0;
content: ''; content: '';
display: block; display: block;
@ -99,7 +99,7 @@
max-height: 200em; max-height: 200em;
margin-bottom: -2em; margin-bottom: -2em;
&:after { &::after {
display: none; display: none;
} }
} }

View File

@ -50,10 +50,11 @@
.additionalInput { .additionalInput {
@include font-size(1.4rem); @include font-size(1.4rem);
-moz-appearance: textfield; appearance: textfield;
&::-webkit-outer-spin-button, &::-webkit-outer-spin-button,
&::-webkit-inner-spin-button { &::-webkit-inner-spin-button {
-webkit-appearance: none; appearance: none;
margin: 0; margin: 0;
} }
@ -223,7 +224,7 @@
border-radius: 50%; border-radius: 50%;
top: 4px; top: 4px;
right: 4px; right: 4px;
background-color: rgba(black, 0.5); background-color: rgb(0 0 0 / 50%);
cursor: pointer; cursor: pointer;
display: none; display: none;
} }

View File

@ -1,12 +1,13 @@
.Expo { .Expo {
display: block; display: block;
background: #fef2f2; background: #fef2f2;
padding: 0 0 4rem 0; padding: 0 0 4rem;
min-height: 100vh; min-height: 100vh;
.navigation { .navigation {
padding: 0 0; padding: 0;
} }
.showMore { .showMore {
display: flex; display: flex;
width: 100%; width: 100%;

View File

@ -9,6 +9,7 @@
.feedNavigation { .feedNavigation {
@include font-size(1.6rem); @include font-size(1.6rem);
font-weight: 500; font-weight: 500;
h4 { h4 {
@ -51,6 +52,7 @@
h4 { h4 {
@include font-size(2.2rem); @include font-size(2.2rem);
font-weight: bold; font-weight: bold;
margin-bottom: 2rem; margin-bottom: 2rem;
} }
@ -131,7 +133,7 @@
} }
&:hover { &:hover {
&:before { &::before {
background-image: url(/icons/knowledge-base-bullet-hover.svg); background-image: url(/icons/knowledge-base-bullet-hover.svg);
} }
} }
@ -170,6 +172,7 @@
a { a {
border: none; border: none;
padding-bottom: 0.2em; padding-bottom: 0.2em;
&:hover * { &:hover * {
background: var(--background-color-invert); background: var(--background-color-invert);
} }

View File

@ -14,7 +14,6 @@ import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll'
import { splitToPages } from '../../utils/splitToPages' import { splitToPages } from '../../utils/splitToPages'
import { clsx } from 'clsx' import { clsx } from 'clsx'
import { Row1 } from '../Feed/Row1' import { Row1 } from '../Feed/Row1'
import { ArticleCard } from '../Feed/ArticleCard'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
import { ArticleCardSwiper } from '../_shared/SolidSwiper/ArticleCardSwiper' import { ArticleCardSwiper } from '../_shared/SolidSwiper/ArticleCardSwiper'

View File

@ -1,6 +1,6 @@
.DropArea { .DropArea {
.field { .field {
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

@ -29,6 +29,7 @@
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
.tiny & { .tiny & {
width: 18px; width: 18px;
height: 18px; height: 18px;

View File

@ -1,4 +1,4 @@
import { createEffect, createSignal, For, Show, on, JSXElement } from 'solid-js' import { createEffect, createSignal, For, Show, on } from 'solid-js'
import { MediaItem, UploadedFile } from '../../../pages/types' import { MediaItem, UploadedFile } from '../../../pages/types'
import { Icon } from '../Icon' import { Icon } from '../Icon'
import { Popover } from '../Popover' import { Popover } from '../Popover'

View File

@ -30,13 +30,16 @@ $navigation-reserve: 32px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
a { a {
color: var(--default-color-invert); color: var(--default-color-invert);
border-color: var(--default-color-invert); border-color: var(--default-color-invert);
} }
.container { .container {
margin: auto; margin: auto;
//max-width: 800px;
// max-width: 800px;
position: relative; position: relative;
padding: 24px 0; padding: 24px 0;
display: flex; display: flex;
@ -108,7 +111,7 @@ $navigation-reserve: 32px;
position: absolute; position: absolute;
top: 16px; top: 16px;
right: 16px; right: 16px;
background: rgba(var(--default-color), 0.3); background: rgb(var(--default-color) 0.3);
cursor: pointer; cursor: pointer;
z-index: 12; z-index: 12;
display: none; display: none;
@ -213,15 +216,17 @@ $navigation-reserve: 32px;
.source { .source {
@include font-size(1.2rem); @include font-size(1.2rem);
color: var(--secondary-color); color: var(--secondary-color);
} }
.body { .body {
@include font-size(1.7rem); @include font-size(1.7rem);
margin-top: 24px; margin-top: 24px;
@include media-breakpoint-up(md) { @include media-breakpoint-up(md) {
//margin-left: calc((100% + 130px) * 0.15); // margin-left: calc((100% + 130px) * 0.15);
margin-left: calc(15% + 24px); margin-left: calc(15% + 24px);
} }
} }

View File

@ -4,105 +4,109 @@ export type InputMaybe<T> = Maybe<T>
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] } export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] }
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> } export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> }
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> } export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> }
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never }
export type Incremental<T> =
| T
| { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }
/** All built-in and custom scalars, mapped to their actual values */ /** All built-in and custom scalars, mapped to their actual values */
export type Scalars = { export type Scalars = {
ID: string ID: { input: string; output: string }
String: string String: { input: string; output: string }
Boolean: boolean Boolean: { input: boolean; output: boolean }
Int: number Int: { input: number; output: number }
Float: number Float: { input: number; output: number }
DateTime: any DateTime: { input: any; output: any }
} }
export type AuthResult = { export type AuthResult = {
error?: Maybe<Scalars['String']> error?: Maybe<Scalars['String']['output']>
token?: Maybe<Scalars['String']> token?: Maybe<Scalars['String']['output']>
user?: Maybe<User> user?: Maybe<User>
} }
export type Author = { export type Author = {
about?: Maybe<Scalars['String']> about?: Maybe<Scalars['String']['output']>
bio?: Maybe<Scalars['String']> bio?: Maybe<Scalars['String']['output']>
caption?: Maybe<Scalars['String']> caption?: Maybe<Scalars['String']['output']>
createdAt?: Maybe<Scalars['DateTime']> createdAt?: Maybe<Scalars['DateTime']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
lastSeen?: Maybe<Scalars['DateTime']> lastSeen?: Maybe<Scalars['DateTime']['output']>
links?: Maybe<Array<Maybe<Scalars['String']>>> links?: Maybe<Array<Maybe<Scalars['String']['output']>>>
name: Scalars['String'] name: Scalars['String']['output']
roles?: Maybe<Array<Maybe<Role>>> roles?: Maybe<Array<Maybe<Role>>>
slug: Scalars['String'] slug: Scalars['String']['output']
stat?: Maybe<AuthorStat> stat?: Maybe<AuthorStat>
userpic?: Maybe<Scalars['String']> userpic?: Maybe<Scalars['String']['output']>
} }
export type AuthorStat = { export type AuthorStat = {
commented?: Maybe<Scalars['Int']> commented?: Maybe<Scalars['Int']['output']>
followers?: Maybe<Scalars['Int']> followers?: Maybe<Scalars['Int']['output']>
followings?: Maybe<Scalars['Int']> followings?: Maybe<Scalars['Int']['output']>
rating?: Maybe<Scalars['Int']> rating?: Maybe<Scalars['Int']['output']>
shouts?: Maybe<Scalars['Int']> shouts?: Maybe<Scalars['Int']['output']>
} }
export type AuthorsBy = { export type AuthorsBy = {
createdAt?: InputMaybe<Scalars['DateTime']> createdAt?: InputMaybe<Scalars['DateTime']['input']>
days?: InputMaybe<Scalars['Int']> days?: InputMaybe<Scalars['Int']['input']>
lastSeen?: InputMaybe<Scalars['DateTime']> lastSeen?: InputMaybe<Scalars['DateTime']['input']>
name?: InputMaybe<Scalars['String']> name?: InputMaybe<Scalars['String']['input']>
order?: InputMaybe<Scalars['String']> order?: InputMaybe<Scalars['String']['input']>
slug?: InputMaybe<Scalars['String']> slug?: InputMaybe<Scalars['String']['input']>
stat?: InputMaybe<Scalars['String']> stat?: InputMaybe<Scalars['String']['input']>
topic?: InputMaybe<Scalars['String']> topic?: InputMaybe<Scalars['String']['input']>
} }
export type Chat = { export type Chat = {
admins?: Maybe<Array<Maybe<Scalars['Int']>>> admins?: Maybe<Array<Maybe<Scalars['Int']['output']>>>
createdAt: Scalars['Int'] createdAt: Scalars['Int']['output']
createdBy: Scalars['Int'] createdBy: Scalars['Int']['output']
description?: Maybe<Scalars['String']> description?: Maybe<Scalars['String']['output']>
id: Scalars['String'] id: Scalars['String']['output']
members?: Maybe<Array<Maybe<ChatMember>>> members?: Maybe<Array<Maybe<ChatMember>>>
messages?: Maybe<Array<Maybe<Message>>> messages?: Maybe<Array<Maybe<Message>>>
private?: Maybe<Scalars['Boolean']> private?: Maybe<Scalars['Boolean']['output']>
title?: Maybe<Scalars['String']> title?: Maybe<Scalars['String']['output']>
unread?: Maybe<Scalars['Int']> unread?: Maybe<Scalars['Int']['output']>
updatedAt: Scalars['Int'] updatedAt: Scalars['Int']['output']
users?: Maybe<Array<Maybe<Scalars['Int']>>> users?: Maybe<Array<Maybe<Scalars['Int']['output']>>>
} }
export type ChatInput = { export type ChatInput = {
description?: InputMaybe<Scalars['String']> description?: InputMaybe<Scalars['String']['input']>
id: Scalars['String'] id: Scalars['String']['input']
title?: InputMaybe<Scalars['String']> title?: InputMaybe<Scalars['String']['input']>
} }
export type ChatMember = { export type ChatMember = {
id: Scalars['Int'] id: Scalars['Int']['output']
lastSeen?: Maybe<Scalars['DateTime']> lastSeen?: Maybe<Scalars['DateTime']['output']>
name: Scalars['String'] name: Scalars['String']['output']
online?: Maybe<Scalars['Boolean']> online?: Maybe<Scalars['Boolean']['output']>
slug: Scalars['String'] slug: Scalars['String']['output']
userpic?: Maybe<Scalars['String']> userpic?: Maybe<Scalars['String']['output']>
} }
export type Collection = { export type Collection = {
amount?: Maybe<Scalars['Int']> amount?: Maybe<Scalars['Int']['output']>
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
createdBy: User createdBy: User
desc?: Maybe<Scalars['String']> desc?: Maybe<Scalars['String']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
publishedAt?: Maybe<Scalars['DateTime']> publishedAt?: Maybe<Scalars['DateTime']['output']>
slug: Scalars['String'] slug: Scalars['String']['output']
title: Scalars['String'] title: Scalars['String']['output']
} }
export type Community = { export type Community = {
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
createdBy: User createdBy: User
desc?: Maybe<Scalars['String']> desc?: Maybe<Scalars['String']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
name: Scalars['String'] name: Scalars['String']['output']
pic: Scalars['String'] pic: Scalars['String']['output']
slug: Scalars['String'] slug: Scalars['String']['output']
} }
export enum FollowingEntity { export enum FollowingEntity {
@ -113,35 +117,35 @@ export enum FollowingEntity {
} }
export type LoadShoutsFilters = { export type LoadShoutsFilters = {
author?: InputMaybe<Scalars['String']> author?: InputMaybe<Scalars['String']['input']>
body?: InputMaybe<Scalars['String']> body?: InputMaybe<Scalars['String']['input']>
days?: InputMaybe<Scalars['Int']> days?: InputMaybe<Scalars['Int']['input']>
excludeLayout?: InputMaybe<Scalars['String']> excludeLayout?: InputMaybe<Scalars['String']['input']>
layout?: InputMaybe<Scalars['String']> layout?: InputMaybe<Scalars['String']['input']>
reacted?: InputMaybe<Scalars['Boolean']> reacted?: InputMaybe<Scalars['Boolean']['input']>
title?: InputMaybe<Scalars['String']> title?: InputMaybe<Scalars['String']['input']>
topic?: InputMaybe<Scalars['String']> topic?: InputMaybe<Scalars['String']['input']>
visibility?: InputMaybe<Scalars['String']> visibility?: InputMaybe<Scalars['String']['input']>
} }
export type LoadShoutsOptions = { export type LoadShoutsOptions = {
filters?: InputMaybe<LoadShoutsFilters> filters?: InputMaybe<LoadShoutsFilters>
limit: Scalars['Int'] limit: Scalars['Int']['input']
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
order_by?: InputMaybe<Scalars['String']> order_by?: InputMaybe<Scalars['String']['input']>
order_by_desc?: InputMaybe<Scalars['Boolean']> order_by_desc?: InputMaybe<Scalars['Boolean']['input']>
with_author_captions?: InputMaybe<Scalars['Boolean']> with_author_captions?: InputMaybe<Scalars['Boolean']['input']>
} }
export type Message = { export type Message = {
author: Scalars['Int'] author: Scalars['Int']['output']
body: Scalars['String'] body: Scalars['String']['output']
chatId: Scalars['String'] chatId: Scalars['String']['output']
createdAt: Scalars['Int'] createdAt: Scalars['Int']['output']
id: Scalars['Int'] id: Scalars['Int']['output']
replyTo?: Maybe<Scalars['Int']> replyTo?: Maybe<Scalars['Int']['output']>
seen?: Maybe<Scalars['Boolean']> seen?: Maybe<Scalars['Boolean']['output']>
updatedAt?: Maybe<Scalars['Int']> updatedAt?: Maybe<Scalars['Int']['output']>
} }
export enum MessageStatus { export enum MessageStatus {
@ -151,12 +155,12 @@ export enum MessageStatus {
} }
export type MessagesBy = { export type MessagesBy = {
author?: InputMaybe<Scalars['String']> author?: InputMaybe<Scalars['String']['input']>
body?: InputMaybe<Scalars['String']> body?: InputMaybe<Scalars['String']['input']>
chat?: InputMaybe<Scalars['String']> chat?: InputMaybe<Scalars['String']['input']>
days?: InputMaybe<Scalars['Int']> days?: InputMaybe<Scalars['Int']['input']>
order?: InputMaybe<Scalars['String']> order?: InputMaybe<Scalars['String']['input']>
stat?: InputMaybe<Scalars['String']> stat?: InputMaybe<Scalars['String']['input']>
} }
export type Mutation = { export type Mutation = {
@ -189,18 +193,18 @@ export type Mutation = {
} }
export type MutationConfirmEmailArgs = { export type MutationConfirmEmailArgs = {
token: Scalars['String'] token: Scalars['String']['input']
} }
export type MutationCreateChatArgs = { export type MutationCreateChatArgs = {
members: Array<InputMaybe<Scalars['Int']>> members: Array<InputMaybe<Scalars['Int']['input']>>
title?: InputMaybe<Scalars['String']> title?: InputMaybe<Scalars['String']['input']>
} }
export type MutationCreateMessageArgs = { export type MutationCreateMessageArgs = {
body: Scalars['String'] body: Scalars['String']['input']
chat: Scalars['String'] chat: Scalars['String']['input']
replyTo?: InputMaybe<Scalars['Int']> replyTo?: InputMaybe<Scalars['Int']['input']>
} }
export type MutationCreateReactionArgs = { export type MutationCreateReactionArgs = {
@ -216,59 +220,59 @@ export type MutationCreateTopicArgs = {
} }
export type MutationDeleteChatArgs = { export type MutationDeleteChatArgs = {
chatId: Scalars['String'] chatId: Scalars['String']['input']
} }
export type MutationDeleteMessageArgs = { export type MutationDeleteMessageArgs = {
chatId: Scalars['String'] chatId: Scalars['String']['input']
id: Scalars['Int'] id: Scalars['Int']['input']
} }
export type MutationDeleteReactionArgs = { export type MutationDeleteReactionArgs = {
id: Scalars['Int'] id: Scalars['Int']['input']
} }
export type MutationDeleteShoutArgs = { export type MutationDeleteShoutArgs = {
shout_id: Scalars['Int'] shout_id: Scalars['Int']['input']
} }
export type MutationDestroyTopicArgs = { export type MutationDestroyTopicArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
} }
export type MutationFollowArgs = { export type MutationFollowArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
what: FollowingEntity what: FollowingEntity
} }
export type MutationMarkAsReadArgs = { export type MutationMarkAsReadArgs = {
chatId: Scalars['String'] chatId: Scalars['String']['input']
ids: Array<InputMaybe<Scalars['Int']>> ids: Array<InputMaybe<Scalars['Int']['input']>>
} }
export type MutationMarkNotificationAsReadArgs = { export type MutationMarkNotificationAsReadArgs = {
notification_id: Scalars['Int'] notification_id: Scalars['Int']['input']
} }
export type MutationRateUserArgs = { export type MutationRateUserArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
value: Scalars['Int'] value: Scalars['Int']['input']
} }
export type MutationRegisterUserArgs = { export type MutationRegisterUserArgs = {
email: Scalars['String'] email: Scalars['String']['input']
name?: InputMaybe<Scalars['String']> name?: InputMaybe<Scalars['String']['input']>
password?: InputMaybe<Scalars['String']> password?: InputMaybe<Scalars['String']['input']>
} }
export type MutationSendLinkArgs = { export type MutationSendLinkArgs = {
email: Scalars['String'] email: Scalars['String']['input']
lang?: InputMaybe<Scalars['String']> lang?: InputMaybe<Scalars['String']['input']>
template?: InputMaybe<Scalars['String']> template?: InputMaybe<Scalars['String']['input']>
} }
export type MutationUnfollowArgs = { export type MutationUnfollowArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
what: FollowingEntity what: FollowingEntity
} }
@ -277,9 +281,9 @@ export type MutationUpdateChatArgs = {
} }
export type MutationUpdateMessageArgs = { export type MutationUpdateMessageArgs = {
body: Scalars['String'] body: Scalars['String']['input']
chatId: Scalars['String'] chatId: Scalars['String']['input']
id: Scalars['Int'] id: Scalars['Int']['input']
} }
export type MutationUpdateProfileArgs = { export type MutationUpdateProfileArgs = {
@ -287,13 +291,13 @@ export type MutationUpdateProfileArgs = {
} }
export type MutationUpdateReactionArgs = { export type MutationUpdateReactionArgs = {
id: Scalars['Int'] id: Scalars['Int']['input']
reaction: ReactionInput reaction: ReactionInput
} }
export type MutationUpdateShoutArgs = { export type MutationUpdateShoutArgs = {
publish?: InputMaybe<Scalars['Boolean']> publish?: InputMaybe<Scalars['Boolean']['input']>
shout_id: Scalars['Int'] shout_id: Scalars['Int']['input']
shout_input?: InputMaybe<ShoutInput> shout_input?: InputMaybe<ShoutInput>
} }
@ -307,13 +311,13 @@ export type MySubscriptionsQueryResult = {
} }
export type Notification = { export type Notification = {
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
data?: Maybe<Scalars['String']> data?: Maybe<Scalars['String']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
occurrences: Scalars['Int'] occurrences: Scalars['Int']['output']
reaction?: Maybe<Scalars['Int']> reaction?: Maybe<Scalars['Int']['output']>
seen: Scalars['Boolean'] seen: Scalars['Boolean']['output']
shout?: Maybe<Scalars['Int']> shout?: Maybe<Scalars['Int']['output']>
type: NotificationType type: NotificationType
} }
@ -323,40 +327,40 @@ export enum NotificationType {
} }
export type NotificationsQueryParams = { export type NotificationsQueryParams = {
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type NotificationsQueryResult = { export type NotificationsQueryResult = {
notifications: Array<Maybe<Notification>> notifications: Array<Maybe<Notification>>
totalCount: Scalars['Int'] totalCount: Scalars['Int']['output']
totalUnreadCount: Scalars['Int'] totalUnreadCount: Scalars['Int']['output']
} }
export type Operation = { export type Operation = {
id: Scalars['Int'] id: Scalars['Int']['output']
name: Scalars['String'] name: Scalars['String']['output']
} }
export type Permission = { export type Permission = {
operation: Scalars['Int'] operation: Scalars['Int']['output']
resource: Scalars['Int'] resource: Scalars['Int']['output']
} }
export type ProfileInput = { export type ProfileInput = {
about?: InputMaybe<Scalars['String']> about?: InputMaybe<Scalars['String']['input']>
bio?: InputMaybe<Scalars['String']> bio?: InputMaybe<Scalars['String']['input']>
links?: InputMaybe<Array<InputMaybe<Scalars['String']>>> links?: InputMaybe<Array<InputMaybe<Scalars['String']['input']>>>
name?: InputMaybe<Scalars['String']> name?: InputMaybe<Scalars['String']['input']>
slug?: InputMaybe<Scalars['String']> slug?: InputMaybe<Scalars['String']['input']>
userpic?: InputMaybe<Scalars['String']> userpic?: InputMaybe<Scalars['String']['input']>
} }
export type Query = { export type Query = {
authorsAll: Array<Maybe<Author>> authorsAll: Array<Maybe<Author>>
getAuthor?: Maybe<Author> getAuthor?: Maybe<Author>
getTopic?: Maybe<Topic> getTopic?: Maybe<Topic>
isEmailUsed: Scalars['Boolean'] isEmailUsed: Scalars['Boolean']['output']
loadAuthorsBy: Array<Maybe<Author>> loadAuthorsBy: Array<Maybe<Author>>
loadChats: Result loadChats: Result
loadDrafts: Array<Maybe<Shout>> loadDrafts: Array<Maybe<Shout>>
@ -367,7 +371,7 @@ export type Query = {
loadRecipients: Result loadRecipients: Result
loadShout?: Maybe<Shout> loadShout?: Maybe<Shout>
loadShouts: Array<Maybe<Shout>> loadShouts: Array<Maybe<Shout>>
markdownBody: Scalars['String'] markdownBody: Scalars['String']['output']
myFeed?: Maybe<Array<Maybe<Shout>>> myFeed?: Maybe<Array<Maybe<Shout>>>
searchMessages: Result searchMessages: Result
searchRecipients: Result searchRecipients: Result
@ -383,32 +387,32 @@ export type Query = {
} }
export type QueryGetAuthorArgs = { export type QueryGetAuthorArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
} }
export type QueryGetTopicArgs = { export type QueryGetTopicArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
} }
export type QueryIsEmailUsedArgs = { export type QueryIsEmailUsedArgs = {
email: Scalars['String'] email: Scalars['String']['input']
} }
export type QueryLoadAuthorsByArgs = { export type QueryLoadAuthorsByArgs = {
by?: InputMaybe<AuthorsBy> by?: InputMaybe<AuthorsBy>
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type QueryLoadChatsArgs = { export type QueryLoadChatsArgs = {
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type QueryLoadMessagesByArgs = { export type QueryLoadMessagesByArgs = {
by: MessagesBy by: MessagesBy
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type QueryLoadNotificationsArgs = { export type QueryLoadNotificationsArgs = {
@ -417,18 +421,18 @@ export type QueryLoadNotificationsArgs = {
export type QueryLoadReactionsByArgs = { export type QueryLoadReactionsByArgs = {
by: ReactionBy by: ReactionBy
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type QueryLoadRecipientsArgs = { export type QueryLoadRecipientsArgs = {
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type QueryLoadShoutArgs = { export type QueryLoadShoutArgs = {
shout_id?: InputMaybe<Scalars['Int']> shout_id?: InputMaybe<Scalars['Int']['input']>
slug?: InputMaybe<Scalars['String']> slug?: InputMaybe<Scalars['String']['input']>
} }
export type QueryLoadShoutsArgs = { export type QueryLoadShoutsArgs = {
@ -436,7 +440,7 @@ export type QueryLoadShoutsArgs = {
} }
export type QueryMarkdownBodyArgs = { export type QueryMarkdownBodyArgs = {
body: Scalars['String'] body: Scalars['String']['input']
} }
export type QueryMyFeedArgs = { export type QueryMyFeedArgs = {
@ -445,85 +449,85 @@ export type QueryMyFeedArgs = {
export type QuerySearchMessagesArgs = { export type QuerySearchMessagesArgs = {
by: MessagesBy by: MessagesBy
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
} }
export type QuerySearchRecipientsArgs = { export type QuerySearchRecipientsArgs = {
limit?: InputMaybe<Scalars['Int']> limit?: InputMaybe<Scalars['Int']['input']>
offset?: InputMaybe<Scalars['Int']> offset?: InputMaybe<Scalars['Int']['input']>
query: Scalars['String'] query: Scalars['String']['input']
} }
export type QuerySignInArgs = { export type QuerySignInArgs = {
email: Scalars['String'] email: Scalars['String']['input']
lang?: InputMaybe<Scalars['String']> lang?: InputMaybe<Scalars['String']['input']>
password?: InputMaybe<Scalars['String']> password?: InputMaybe<Scalars['String']['input']>
} }
export type QueryTopicsByAuthorArgs = { export type QueryTopicsByAuthorArgs = {
author: Scalars['String'] author: Scalars['String']['input']
} }
export type QueryTopicsByCommunityArgs = { export type QueryTopicsByCommunityArgs = {
community: Scalars['String'] community: Scalars['String']['input']
} }
export type QueryTopicsRandomArgs = { export type QueryTopicsRandomArgs = {
amount?: InputMaybe<Scalars['Int']> amount?: InputMaybe<Scalars['Int']['input']>
} }
export type QueryUserFollowedAuthorsArgs = { export type QueryUserFollowedAuthorsArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
} }
export type QueryUserFollowedTopicsArgs = { export type QueryUserFollowedTopicsArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
} }
export type QueryUserFollowersArgs = { export type QueryUserFollowersArgs = {
slug: Scalars['String'] slug: Scalars['String']['input']
} }
export type Rating = { export type Rating = {
rater: Scalars['String'] rater: Scalars['String']['output']
value: Scalars['Int'] value: Scalars['Int']['output']
} }
export type Reaction = { export type Reaction = {
body?: Maybe<Scalars['String']> body?: Maybe<Scalars['String']['output']>
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
createdBy: User createdBy: User
deletedAt?: Maybe<Scalars['DateTime']> deletedAt?: Maybe<Scalars['DateTime']['output']>
deletedBy?: Maybe<User> deletedBy?: Maybe<User>
id: Scalars['Int'] id: Scalars['Int']['output']
kind: ReactionKind kind: ReactionKind
old_id?: Maybe<Scalars['String']> old_id?: Maybe<Scalars['String']['output']>
old_thread?: Maybe<Scalars['String']> old_thread?: Maybe<Scalars['String']['output']>
range?: Maybe<Scalars['String']> range?: Maybe<Scalars['String']['output']>
replyTo?: Maybe<Scalars['Int']> replyTo?: Maybe<Scalars['Int']['output']>
shout: Shout shout: Shout
stat?: Maybe<Stat> stat?: Maybe<Stat>
updatedAt?: Maybe<Scalars['DateTime']> updatedAt?: Maybe<Scalars['DateTime']['output']>
} }
export type ReactionBy = { export type ReactionBy = {
comment?: InputMaybe<Scalars['Boolean']> comment?: InputMaybe<Scalars['Boolean']['input']>
createdBy?: InputMaybe<Scalars['String']> createdBy?: InputMaybe<Scalars['String']['input']>
days?: InputMaybe<Scalars['Int']> days?: InputMaybe<Scalars['Int']['input']>
search?: InputMaybe<Scalars['String']> search?: InputMaybe<Scalars['String']['input']>
shout?: InputMaybe<Scalars['String']> shout?: InputMaybe<Scalars['String']['input']>
shouts?: InputMaybe<Array<InputMaybe<Scalars['String']>>> shouts?: InputMaybe<Array<InputMaybe<Scalars['String']['input']>>>
sort?: InputMaybe<Scalars['String']> sort?: InputMaybe<Scalars['String']['input']>
topic?: InputMaybe<Scalars['String']> topic?: InputMaybe<Scalars['String']['input']>
} }
export type ReactionInput = { export type ReactionInput = {
body?: InputMaybe<Scalars['String']> body?: InputMaybe<Scalars['String']['input']>
kind: ReactionKind kind: ReactionKind
range?: InputMaybe<Scalars['String']> range?: InputMaybe<Scalars['String']['input']>
replyTo?: InputMaybe<Scalars['Int']> replyTo?: InputMaybe<Scalars['Int']['input']>
shout: Scalars['Int'] shout: Scalars['Int']['input']
} }
export enum ReactionKind { export enum ReactionKind {
@ -552,14 +556,14 @@ export enum ReactionStatus {
} }
export type ReactionUpdating = { export type ReactionUpdating = {
error?: Maybe<Scalars['String']> error?: Maybe<Scalars['String']['output']>
reaction?: Maybe<Reaction> reaction?: Maybe<Reaction>
status?: Maybe<ReactionStatus> status?: Maybe<ReactionStatus>
} }
export type Resource = { export type Resource = {
id: Scalars['Int'] id: Scalars['Int']['output']
name: Scalars['String'] name: Scalars['String']['output']
} }
export type Result = { export type Result = {
@ -569,7 +573,7 @@ export type Result = {
chats?: Maybe<Array<Maybe<Chat>>> chats?: Maybe<Array<Maybe<Chat>>>
communities?: Maybe<Array<Maybe<Community>>> communities?: Maybe<Array<Maybe<Community>>>
community?: Maybe<Community> community?: Maybe<Community>
error?: Maybe<Scalars['String']> error?: Maybe<Scalars['String']['output']>
members?: Maybe<Array<Maybe<ChatMember>>> members?: Maybe<Array<Maybe<ChatMember>>>
message?: Maybe<Message> message?: Maybe<Message>
messages?: Maybe<Array<Maybe<Message>>> messages?: Maybe<Array<Maybe<Message>>>
@ -577,121 +581,121 @@ export type Result = {
reactions?: Maybe<Array<Maybe<Reaction>>> reactions?: Maybe<Array<Maybe<Reaction>>>
shout?: Maybe<Shout> shout?: Maybe<Shout>
shouts?: Maybe<Array<Maybe<Shout>>> shouts?: Maybe<Array<Maybe<Shout>>>
slugs?: Maybe<Array<Maybe<Scalars['String']>>> slugs?: Maybe<Array<Maybe<Scalars['String']['output']>>>
topic?: Maybe<Topic> topic?: Maybe<Topic>
topics?: Maybe<Array<Maybe<Topic>>> topics?: Maybe<Array<Maybe<Topic>>>
} }
export type Role = { export type Role = {
community: Scalars['String'] community: Scalars['String']['output']
desc?: Maybe<Scalars['String']> desc?: Maybe<Scalars['String']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
name: Scalars['String'] name: Scalars['String']['output']
permissions: Array<Permission> permissions: Array<Permission>
} }
export type Shout = { export type Shout = {
authors?: Maybe<Array<Maybe<Author>>> authors?: Maybe<Array<Maybe<Author>>>
body: Scalars['String'] body: Scalars['String']['output']
community?: Maybe<Scalars['String']> community?: Maybe<Scalars['String']['output']>
cover?: Maybe<Scalars['String']> cover?: Maybe<Scalars['String']['output']>
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
deletedAt?: Maybe<Scalars['DateTime']> deletedAt?: Maybe<Scalars['DateTime']['output']>
deletedBy?: Maybe<User> deletedBy?: Maybe<User>
description?: Maybe<Scalars['String']> description?: Maybe<Scalars['String']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
lang?: Maybe<Scalars['String']> lang?: Maybe<Scalars['String']['output']>
layout?: Maybe<Scalars['String']> layout?: Maybe<Scalars['String']['output']>
lead?: Maybe<Scalars['String']> lead?: Maybe<Scalars['String']['output']>
mainTopic?: Maybe<Scalars['String']> mainTopic?: Maybe<Scalars['String']['output']>
media?: Maybe<Scalars['String']> media?: Maybe<Scalars['String']['output']>
publishedAt?: Maybe<Scalars['DateTime']> publishedAt?: Maybe<Scalars['DateTime']['output']>
slug: Scalars['String'] slug: Scalars['String']['output']
stat?: Maybe<Stat> stat?: Maybe<Stat>
subtitle?: Maybe<Scalars['String']> subtitle?: Maybe<Scalars['String']['output']>
title?: Maybe<Scalars['String']> title?: Maybe<Scalars['String']['output']>
topics?: Maybe<Array<Maybe<Topic>>> topics?: Maybe<Array<Maybe<Topic>>>
updatedAt?: Maybe<Scalars['DateTime']> updatedAt?: Maybe<Scalars['DateTime']['output']>
updatedBy?: Maybe<User> updatedBy?: Maybe<User>
versionOf?: Maybe<Scalars['String']> versionOf?: Maybe<Scalars['String']['output']>
visibility?: Maybe<Scalars['String']> visibility?: Maybe<Scalars['String']['output']>
} }
export type ShoutInput = { export type ShoutInput = {
authors?: InputMaybe<Array<InputMaybe<Scalars['String']>>> authors?: InputMaybe<Array<InputMaybe<Scalars['String']['input']>>>
body?: InputMaybe<Scalars['String']> body?: InputMaybe<Scalars['String']['input']>
community?: InputMaybe<Scalars['Int']> community?: InputMaybe<Scalars['Int']['input']>
cover?: InputMaybe<Scalars['String']> cover?: InputMaybe<Scalars['String']['input']>
description?: InputMaybe<Scalars['String']> description?: InputMaybe<Scalars['String']['input']>
layout?: InputMaybe<Scalars['String']> layout?: InputMaybe<Scalars['String']['input']>
lead?: InputMaybe<Scalars['String']> lead?: InputMaybe<Scalars['String']['input']>
mainTopic?: InputMaybe<TopicInput> mainTopic?: InputMaybe<TopicInput>
media?: InputMaybe<Scalars['String']> media?: InputMaybe<Scalars['String']['input']>
slug?: InputMaybe<Scalars['String']> slug?: InputMaybe<Scalars['String']['input']>
subtitle?: InputMaybe<Scalars['String']> subtitle?: InputMaybe<Scalars['String']['input']>
title?: InputMaybe<Scalars['String']> title?: InputMaybe<Scalars['String']['input']>
topics?: InputMaybe<Array<InputMaybe<TopicInput>>> topics?: InputMaybe<Array<InputMaybe<TopicInput>>>
} }
export type Stat = { export type Stat = {
commented?: Maybe<Scalars['Int']> commented?: Maybe<Scalars['Int']['output']>
ranking?: Maybe<Scalars['Int']> ranking?: Maybe<Scalars['Int']['output']>
rating?: Maybe<Scalars['Int']> rating?: Maybe<Scalars['Int']['output']>
reacted?: Maybe<Scalars['Int']> reacted?: Maybe<Scalars['Int']['output']>
viewed?: Maybe<Scalars['Int']> viewed?: Maybe<Scalars['Int']['output']>
} }
export type Token = { export type Token = {
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
expiresAt?: Maybe<Scalars['DateTime']> expiresAt?: Maybe<Scalars['DateTime']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
ownerId: Scalars['Int'] ownerId: Scalars['Int']['output']
usedAt?: Maybe<Scalars['DateTime']> usedAt?: Maybe<Scalars['DateTime']['output']>
value: Scalars['String'] value: Scalars['String']['output']
} }
export type Topic = { export type Topic = {
body?: Maybe<Scalars['String']> body?: Maybe<Scalars['String']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
oid?: Maybe<Scalars['String']> oid?: Maybe<Scalars['String']['output']>
pic?: Maybe<Scalars['String']> pic?: Maybe<Scalars['String']['output']>
slug: Scalars['String'] slug: Scalars['String']['output']
stat?: Maybe<TopicStat> stat?: Maybe<TopicStat>
title?: Maybe<Scalars['String']> title?: Maybe<Scalars['String']['output']>
} }
export type TopicInput = { export type TopicInput = {
body?: InputMaybe<Scalars['String']> body?: InputMaybe<Scalars['String']['input']>
id?: InputMaybe<Scalars['Int']> id?: InputMaybe<Scalars['Int']['input']>
pic?: InputMaybe<Scalars['String']> pic?: InputMaybe<Scalars['String']['input']>
slug: Scalars['String'] slug: Scalars['String']['input']
title?: InputMaybe<Scalars['String']> title?: InputMaybe<Scalars['String']['input']>
} }
export type TopicStat = { export type TopicStat = {
authors: Scalars['Int'] authors: Scalars['Int']['output']
followers: Scalars['Int'] followers: Scalars['Int']['output']
shouts: Scalars['Int'] shouts: Scalars['Int']['output']
} }
export type User = { export type User = {
about?: Maybe<Scalars['String']> about?: Maybe<Scalars['String']['output']>
bio?: Maybe<Scalars['String']> bio?: Maybe<Scalars['String']['output']>
communities?: Maybe<Array<Maybe<Scalars['Int']>>> communities?: Maybe<Array<Maybe<Scalars['Int']['output']>>>
createdAt: Scalars['DateTime'] createdAt: Scalars['DateTime']['output']
email?: Maybe<Scalars['String']> email?: Maybe<Scalars['String']['output']>
emailConfirmed?: Maybe<Scalars['Boolean']> emailConfirmed?: Maybe<Scalars['Boolean']['output']>
id: Scalars['Int'] id: Scalars['Int']['output']
lastSeen?: Maybe<Scalars['DateTime']> lastSeen?: Maybe<Scalars['DateTime']['output']>
links?: Maybe<Array<Maybe<Scalars['String']>>> links?: Maybe<Array<Maybe<Scalars['String']['output']>>>
muted?: Maybe<Scalars['Boolean']> muted?: Maybe<Scalars['Boolean']['output']>
name?: Maybe<Scalars['String']> name?: Maybe<Scalars['String']['output']>
oauth?: Maybe<Scalars['String']> oauth?: Maybe<Scalars['String']['output']>
oid?: Maybe<Scalars['String']> oid?: Maybe<Scalars['String']['output']>
password?: Maybe<Scalars['String']> password?: Maybe<Scalars['String']['output']>
ratings?: Maybe<Array<Maybe<Rating>>> ratings?: Maybe<Array<Maybe<Rating>>>
slug: Scalars['String'] slug: Scalars['String']['output']
updatedAt?: Maybe<Scalars['DateTime']> updatedAt?: Maybe<Scalars['DateTime']['output']>
username: Scalars['String'] username: Scalars['String']['output']
userpic?: Maybe<Scalars['String']> userpic?: Maybe<Scalars['String']['output']>
} }

View File

@ -1,14 +1,14 @@
import type { PageContext } from '../renderer/types' import type { PageContext } from '../renderer/types'
import type { PageProps } from './types' import type { PageProps } from './types'
import { apiClient } from '../utils/apiClient' import { apiClient } from '../utils/apiClient'
import { RenderErrorPage } from 'vite-plugin-ssr/RenderErrorPage' import { render } from 'vike/abort'
export const onBeforeRender = async (pageContext: PageContext) => { export const onBeforeRender = async (pageContext: PageContext) => {
const { slug } = pageContext.routeParams const { slug } = pageContext.routeParams
const article = await apiClient.getShoutBySlug(slug) const article = await apiClient.getShoutBySlug(slug)
if (!article) { if (!article) {
throw RenderErrorPage({ pageContext: {} }) throw render(404, '/404')
} }
const pageProps: PageProps = { article } const pageProps: PageProps = { article }

View File

@ -3,11 +3,12 @@ import type { Shout } from '../graphql/types.gen'
import { PageLayout } from '../components/_shared/PageLayout' import { PageLayout } from '../components/_shared/PageLayout'
import type { PageProps } from './types' import type { PageProps } from './types'
import { loadShout, useArticlesStore } from '../stores/zine/articles' import { loadShout, useArticlesStore } from '../stores/zine/articles'
import { useRouter } from '../stores/router' import { router, useRouter } from '../stores/router'
import { Loading } from '../components/_shared/Loading' import { Loading } from '../components/_shared/Loading'
import { ReactionsProvider } from '../context/reactions' import { ReactionsProvider } from '../context/reactions'
import { FullArticle } from '../components/Article/FullArticle' import { FullArticle } from '../components/Article/FullArticle'
import { setPageLoadManagerPromise } from '../utils/pageLoadManager' import { setPageLoadManagerPromise } from '../utils/pageLoadManager'
import { redirectPage } from '@nanostores/router'
export const ArticlePage = (props: PageProps) => { export const ArticlePage = (props: PageProps) => {
const shouts = props.article ? [props.article] : [] const shouts = props.article ? [props.article] : []
@ -28,6 +29,10 @@ export const ArticlePage = (props: PageProps) => {
const loadShoutPromise = loadShout(slug()) const loadShoutPromise = loadShout(slug())
setPageLoadManagerPromise(loadShoutPromise) setPageLoadManagerPromise(loadShoutPromise)
await loadShoutPromise await loadShoutPromise
if (!article()) {
redirectPage(router, 'fourOuFour')
}
} }
}) })

View File

@ -7,22 +7,22 @@ import { useRouter } from '../stores/router'
import { AuthGuard } from '../components/AuthGuard' import { AuthGuard } from '../components/AuthGuard'
import { LoadShoutsOptions } from '../graphql/types.gen' import { LoadShoutsOptions } from '../graphql/types.gen'
const handleFeedLoadShouts = (options: LoadShoutsOptions) => {
return loadShouts({
...options,
filters: { visibility: 'community' }
})
}
const handleMyFeedLoadShouts = (options: LoadShoutsOptions) => {
return loadMyFeed(options)
}
export const FeedPage = () => { export const FeedPage = () => {
onCleanup(() => resetSortedArticles()) onCleanup(() => resetSortedArticles())
const { page } = useRouter() const { page } = useRouter()
const handleFeedLoadShouts = (options: LoadShoutsOptions) => {
return loadShouts({
...options,
filters: { visibility: 'community' }
})
}
const handleMyFeedLoadShouts = (options: LoadShoutsOptions) => {
return loadMyFeed(options)
}
createEffect( createEffect(
on( on(
() => page().route, () => page().route,

View File

@ -1,9 +1,9 @@
import { App } from '../components/App' import { App } from '../components/App'
import { hydrate } from 'solid-js/web' import { hydrate } from 'solid-js/web'
import type { PageContextBuiltInClientWithClientRouting } from 'vite-plugin-ssr/types' import type { PageContextBuiltInClientWithClientRouting } from 'vike/types'
import type { PageContext } from './types' import type { PageContext } from './types'
import { MetaProvider } from '@solidjs/meta' import { MetaProvider } from '@solidjs/meta'
import i18next, { use as useI18next } from 'i18next' import i18next from 'i18next'
import ICU from 'i18next-icu' import ICU from 'i18next-icu'
import HttpApi from 'i18next-http-backend' import HttpApi from 'i18next-http-backend'
import * as Sentry from '@sentry/browser' import * as Sentry from '@sentry/browser'
@ -30,14 +30,17 @@ export const render = async (pageContext: PageContextBuiltInClientWithClientRout
}) })
} }
useI18next(HttpApi) // eslint-disable-next-line import/no-named-as-default-member
await i18next.use(ICU).init({ await i18next
// debug: true, .use(HttpApi)
supportedLngs: ['ru', 'en'], .use(ICU)
fallbackLng: lng, .init({
lng, // debug: true,
load: 'languageOnly' supportedLngs: ['ru', 'en'],
}) fallbackLng: lng,
lng,
load: 'languageOnly'
})
const isIOSorMacOSorAndroid = /iphone|ipad|ipod|macintosh|android/i.test(navigator.userAgent) const isIOSorMacOSorAndroid = /iphone|ipad|ipod|macintosh|android/i.test(navigator.userAgent)

View File

@ -1,9 +1,9 @@
import { generateHydrationScript, renderToString } from 'solid-js/web' import { generateHydrationScript, getAssets, renderToString } from 'solid-js/web'
import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr/server' import { escapeInject, dangerouslySkipEscape } from 'vike/server'
import { App } from '../components/App' import { App } from '../components/App'
import { initRouter } from '../stores/router' import { initRouter } from '../stores/router'
import type { PageContext } from './types' import type { PageContext } from './types'
import { MetaProvider, renderTags } from '@solidjs/meta' import { MetaProvider } from '@solidjs/meta'
import i18next from 'i18next' import i18next from 'i18next'
import ru from '../../public/locales/ru/translation.json' import ru from '../../public/locales/ru/translation.json'
import en from '../../public/locales/en/translation.json' import en from '../../public/locales/en/translation.json'
@ -12,8 +12,6 @@ import ICU from 'i18next-icu'
export const passToClient = ['pageProps', 'lng', 'documentProps', 'is404'] export const passToClient = ['pageProps', 'lng', 'documentProps', 'is404']
const metaTags = []
const getLng = (pageContext: PageContext): Language => { const getLng = (pageContext: PageContext): Language => {
const { urlParsed, cookies } = pageContext const { urlParsed, cookies } = pageContext
@ -45,6 +43,7 @@ export const render = async (pageContext: PageContext) => {
} }
}) })
} else if (i18next.language !== lng) { } else if (i18next.language !== lng) {
// eslint-disable-next-line import/no-named-as-default-member
await i18next.changeLanguage(lng) await i18next.changeLanguage(lng)
} }
@ -57,7 +56,7 @@ export const render = async (pageContext: PageContext) => {
pageContext.lng = lng pageContext.lng = lng
const rootContent = renderToString(() => ( const rootContent = renderToString(() => (
<MetaProvider tags={metaTags}> <MetaProvider>
<App {...pageContext.pageProps} /> <App {...pageContext.pageProps} />
</MetaProvider> </MetaProvider>
)) ))
@ -65,7 +64,7 @@ export const render = async (pageContext: PageContext) => {
return escapeInject`<!DOCTYPE html> return escapeInject`<!DOCTYPE html>
<html lang="${lng}"> <html lang="${lng}">
<head> <head>
${dangerouslySkipEscape(renderTags(metaTags))} ${dangerouslySkipEscape(getAssets())}
${dangerouslySkipEscape(generateHydrationScript())} ${dangerouslySkipEscape(generateHydrationScript())}
</head> </head>
<body> <body>

View File

@ -1,4 +1,4 @@
// this file is required by vite-plugin-ssr to show something after an error occurred // this file is required by vike to show something after an error occurred
// it's empty because error handling logic lives in _default.page.server.tsx and _default.page.client.tsx // it's empty because error handling logic lives in _default.page.server.tsx and _default.page.client.tsx
// eslint-disable-next-line unicorn/no-empty-file // eslint-disable-next-line unicorn/no-empty-file

View File

@ -1,8 +1,8 @@
import type { PageContextBuiltIn } from 'vite-plugin-ssr/types'
import type { PageProps } from '../pages/types' import type { PageProps } from '../pages/types'
import type { Component } from 'solid-js' import type { Component } from 'solid-js'
import { PageContextBuiltInClientWithClientRouting } from 'vike/dist/esm/types'
export type PageContext = PageContextBuiltIn & { export type PageContext = PageContextBuiltInClientWithClientRouting & {
Page: (pageProps: PageProps) => Component Page: (pageProps: PageProps) => Component
pageProps: PageProps pageProps: PageProps
lng: string lng: string

View File

@ -119,6 +119,9 @@ const addSortedArticles = (articles: Shout[]) => {
export const loadShout = async (slug: string): Promise<void> => { export const loadShout = async (slug: string): Promise<void> => {
const newArticle = await apiClient.getShoutBySlug(slug) const newArticle = await apiClient.getShoutBySlug(slug)
if (!newArticle) {
return
}
addArticles([newArticle]) addArticles([newArticle])
const newArticleIndex = sortedArticles().findIndex((s) => s.id === newArticle.id) const newArticleIndex = sortedArticles().findIndex((s) => s.id === newArticle.id)
if (newArticleIndex >= 0) { if (newArticleIndex >= 0) {

View File

@ -17,7 +17,7 @@
--link-hover-background: #000; --link-hover-background: #000;
--secondary-color: #85878a; --secondary-color: #85878a;
--placeholder-color: #9fa1a7; --placeholder-color: #9fa1a7;
--placeholder-color-semi: rgba(159, 169, 167, 0.2); --placeholder-color-semi: rgb(159 169 167 / 20%);
--danger-color: #d00820; --danger-color: #d00820;
--lightgray-color: rgb(84 16 17 / 6%); --lightgray-color: rgb(84 16 17 / 6%);
--font: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, oxygen, ubuntu, cantarell, 'Open Sans', --font: -apple-system, blinkmacsystemfont, 'Segoe UI', roboto, oxygen, ubuntu, cantarell, 'Open Sans',
@ -28,6 +28,7 @@
--icon-filter-hover: invert(1); --icon-filter-hover: invert(1);
--editor-bubble-menu-background: #fff; --editor-bubble-menu-background: #fff;
--blue-link: #2638d9; --blue-link: #2638d9;
// names from figma // names from figma
--black-50: #f7f7f8; --black-50: #f7f7f8;
--black-100: #e9e9ee; --black-100: #e9e9ee;
@ -53,6 +54,7 @@
--icon-filter: invert(1); --icon-filter: invert(1);
--icon-filter-hover: invert(0); --icon-filter-hover: invert(0);
--editor-bubble-menu-background: #444; --editor-bubble-menu-background: #444;
// names from figma // names from figma
--black-50: #080807; --black-50: #080807;
--black-100: #161611; --black-100: #161611;
@ -146,11 +148,13 @@ h2 {
h1 { h1 {
@include font-size(4.8rem); @include font-size(4.8rem);
line-height: 1.1; line-height: 1.1;
} }
h2 { h2 {
@include font-size(4rem); @include font-size(4rem);
line-height: 1.1; line-height: 1.1;
margin-bottom: 0.5em; margin-bottom: 0.5em;
margin-top: 1.5em; margin-top: 1.5em;
@ -158,6 +162,7 @@ h2 {
h3 { h3 {
@include font-size(3.2rem); @include font-size(3.2rem);
line-height: 1.1; line-height: 1.1;
margin-bottom: 0.5em; margin-bottom: 0.5em;
} }
@ -289,6 +294,7 @@ button {
.button--light { .button--light {
@include font-size(1.5rem); @include font-size(1.5rem);
background-color: #f6f6f6; background-color: #f6f6f6;
border-radius: 0.8rem; border-radius: 0.8rem;
color: #000; color: #000;
@ -586,13 +592,16 @@ figure {
figcaption { figcaption {
color: rgb(0 0 0 / 60%); color: rgb(0 0 0 / 60%);
@include font-size(1.2rem); @include font-size(1.2rem);
line-height: 1.5; line-height: 1.5;
} }
} }
.view-switcher { .view-switcher {
@include font-size(1.4rem); @include font-size(1.4rem);
display: flex; display: flex;
font-weight: 500; font-weight: 500;
list-style: none; list-style: none;
@ -810,8 +819,7 @@ figure {
#root { #root {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-content: space-between; place-content: space-between space-between;
justify-content: space-between;
min-height: 100vh; min-height: 100vh;
} }
@ -901,6 +909,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;
@ -987,6 +996,7 @@ details {
.description { .description {
@include font-size(1.4rem); @include font-size(1.4rem);
color: rgba(0 0 0 / 40%); color: rgba(0 0 0 / 40%);
.pretty-form__item + & { .pretty-form__item + & {
@ -1024,11 +1034,12 @@ details {
iframe { iframe {
border: none; border: none;
color: rgba(255, 255, 255, 0); color: rgb(255 255 255 / 0%);
} }
.lead { .lead {
@include font-size(2rem); @include font-size(2rem);
font-weight: bold; font-weight: bold;
line-height: 1.5; line-height: 1.5;
} }

View File

@ -310,9 +310,9 @@ export const apiClient = {
}) })
.toPromise() .toPromise()
if (resp.error) { // if (resp.error) {
console.error(resp) // console.error(resp)
} // }
return resp.data.loadShout return resp.data.loadShout
}, },

View File

@ -1,4 +1,4 @@
// /:slug -> /@slug // /:slug -> /@slug
// https://vite-plugin-ssr.com/routing // https://vike.dev/routing
// https://www.npmjs.com/package/@nanostores/router // https://www.npmjs.com/package/@nanostores/router
export const getServerRoute = (clientRoute: string) => clientRoute.replaceAll(':', '@') export const getServerRoute = (clientRoute: string) => clientRoute.replaceAll(':', '@')

View File

@ -1,6 +1,6 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import solidPlugin from 'vite-plugin-solid' import solidPlugin from 'vite-plugin-solid'
import ssrPlugin from 'vite-plugin-ssr/plugin' import ssrPlugin from 'vike/plugin'
import sassDts from 'vite-plugin-sass-dts' import sassDts from 'vite-plugin-sass-dts'
import mkcert from 'vite-plugin-mkcert' import mkcert from 'vite-plugin-mkcert'