Merge branch 'dev' of https://github.com/Discours/discoursio-webapp into feature/empty-feed

This commit is contained in:
kvakazyambra 2024-05-18 23:54:08 +03:00
commit 18a23ee0f8
5 changed files with 58 additions and 53 deletions

View File

@ -95,8 +95,8 @@ export const LoginForm = () => {
try { try {
const { errors } = await signIn({ email: email(), password: password() }) const { errors } = await signIn({ email: email(), password: password() })
console.error('[signIn errors]', errors)
if (errors?.length > 0) { if (errors?.length > 0) {
console.debug('[signIn] errors:', errors)
if ( if (
errors.some( errors.some(
(error) => (error) =>

View File

@ -45,7 +45,6 @@
.info { .info {
@include font-size(1.4rem); @include font-size(1.4rem);
border: none; border: none;
// display: flex; // display: flex;
@ -63,13 +62,11 @@
.title { .title {
@include font-size(2.2rem); @include font-size(2.2rem);
font-weight: bold; font-weight: bold;
} }
.description { .description {
@include font-size(1.6rem); @include font-size(1.6rem);
line-height: 1.4; line-height: 1.4;
margin: 0.8rem 0; margin: 0.8rem 0;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
@ -107,7 +104,6 @@
.title { .title {
@include font-size(1.4rem); @include font-size(1.4rem);
font-weight: 500; font-weight: 500;
line-height: 1em; line-height: 1em;
color: var(--blue-500); color: var(--blue-500);
@ -116,9 +112,7 @@
.description { .description {
color: var(--black-400); color: var(--black-400);
@include font-size(1.2rem); @include font-size(1.2rem);
font-weight: 500; font-weight: 500;
margin: 0; margin: 0;
} }

View File

@ -48,7 +48,7 @@ export const TopicBadge = (props: Props) => {
lang() === 'en' ? capitalize(props.topic.slug.replaceAll('-', ' ')) : props.topic.title lang() === 'en' ? capitalize(props.topic.slug.replaceAll('-', ' ')) : props.topic.title
return ( return (
<div class={clsx(styles.TopicBadge, props.subscriptionsMode)}> <div class={clsx(styles.TopicBadge, { [styles.TopicBadgeSubscriptionsMode]: props.subscriptionsMode })}>
<div class={styles.content}> <div class={styles.content}>
<div class={styles.basicInfo}> <div class={styles.basicInfo}>
<Show when={props.subscriptionsMode}> <Show when={props.subscriptionsMode}>

View File

@ -30,19 +30,19 @@ const ConnectContext = createContext<ConnectContextType>()
export const ConnectProvider = (props: { children: JSX.Element }) => { export const ConnectProvider = (props: { children: JSX.Element }) => {
const [messageHandlers, setHandlers] = createSignal<MessageHandler[]>([]) const [messageHandlers, setHandlers] = createSignal<MessageHandler[]>([])
// const [messages, setMessages] = createSignal<Array<SSEMessage>>([]);
const [connected, setConnected] = createSignal(false) const [connected, setConnected] = createSignal(false)
const { session } = useSession() const { session } = useSession()
const [retried, setRetried] = createSignal<number>(0)
const addHandler = (handler: MessageHandler) => { const addHandler = (handler: MessageHandler) => {
setHandlers((hhh) => [...hhh, handler]) setHandlers((hhh) => [...hhh, handler])
} }
const [retried, setRetried] = createSignal<number>(0)
createEffect(async () => { createEffect(async () => {
const token = session()?.access_token const token = session()?.access_token
if (token && !connected()) { if (token && !connected() && retried() <= RECONNECT_TIMES) {
console.info('[context.connect] init SSE connection') console.info('[context.connect] init SSE connection')
try {
await fetchEventSource('https://connect.discours.io', { await fetchEventSource('https://connect.discours.io', {
method: 'GET', method: 'GET',
headers: { headers: {
@ -52,31 +52,35 @@ export const ConnectProvider = (props: { children: JSX.Element }) => {
onmessage(event) { onmessage(event) {
const m: SSEMessage = JSON.parse(event.data || '{}') const m: SSEMessage = JSON.parse(event.data || '{}')
console.log('[context.connect] Received message:', m) console.log('[context.connect] Received message:', m)
// Iterate over all registered handlers and call them
messageHandlers().forEach((handler) => handler(m)) messageHandlers().forEach((handler) => handler(m))
}, },
async onopen(response) { onopen: (response) => {
console.log('[context.connect] SSE connection opened', response) console.log('[context.connect] SSE connection opened', response)
if (response.ok && response.headers.get('content-type') === EventStreamContentType) { if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
setConnected(true) setConnected(true)
} else if (response.status === 401) { setRetried(0)
throw new Error('SSE: cannot connect to real-time updates') return Promise.resolve()
} else {
setRetried((r) => r + 1)
throw new Error(`SSE: failed to connect ${retried()} times`)
} }
return Promise.reject(`SSE: cannot connect to real-time updates, status: ${response.status}`)
}, },
onclose() { onclose() {
console.log('[context.connect] SSE connection closed by server') console.log('[context.connect] SSE connection closed by server')
setConnected(false) setConnected(false)
}, if (retried() < RECONNECT_TIMES) {
onerror(err) { setRetried((r) => r + 1)
if (err.message === 'unauthorized' || retried() > RECONNECT_TIMES) {
throw err // rethrow to stop the operation
} }
}, },
onerror(err) {
console.error('[context.connect] SSE connection error:', err)
setConnected(false)
if (retried() < RECONNECT_TIMES) {
setRetried((r) => r + 1)
} else throw Error(err)
},
}) })
} catch (error) {
console.error('[context.connect] SSE connection failed:', error)
}
} }
}) })

View File

@ -1,4 +1,4 @@
import { Show, Suspense, createEffect, createMemo, createSignal, lazy, on, onMount } from 'solid-js' import { Show, Suspense, createEffect, createMemo, createSignal, lazy, on } from 'solid-js'
import { AuthGuard } from '../components/AuthGuard' import { AuthGuard } from '../components/AuthGuard'
import { Loading } from '../components/_shared/Loading' import { Loading } from '../components/_shared/Loading'
@ -7,7 +7,7 @@ import { useLocalize } from '../context/localize'
import { useSession } from '../context/session' import { useSession } from '../context/session'
import { apiClient } from '../graphql/client/core' import { apiClient } from '../graphql/client/core'
import { Shout } from '../graphql/schema/core.gen' import { Shout } from '../graphql/schema/core.gen'
import { router } from '../stores/router' import { router, useRouter } from '../stores/router'
import { redirectPage } from '@nanostores/router' import { redirectPage } from '@nanostores/router'
import { useSnackbar } from '../context/snackbar' import { useSnackbar } from '../context/snackbar'
@ -33,6 +33,7 @@ const getContentTypeTitle = (layout: LayoutType) => {
export const EditPage = () => { export const EditPage = () => {
const { t } = useLocalize() const { t } = useLocalize()
const { session } = useSession() const { session } = useSession()
const { page } = useRouter()
const snackbar = useSnackbar() const snackbar = useSnackbar()
const fail = async (error: string) => { const fail = async (error: string) => {
@ -45,12 +46,18 @@ export const EditPage = () => {
const [shoutId, setShoutId] = createSignal<number>(0) const [shoutId, setShoutId] = createSignal<number>(0)
const [shout, setShout] = createSignal<Shout>() const [shout, setShout] = createSignal<Shout>()
onMount(() => { createEffect(
const shoutId = window.location.pathname.split('/').pop() on(
page,
(p) => {
const shoutId = p?.path.split('/').pop()
const shoutIdFromUrl = Number.parseInt(shoutId ?? '0', 10) const shoutIdFromUrl = Number.parseInt(shoutId ?? '0', 10)
console.debug(`editing shout ${shoutIdFromUrl}`) console.debug(`editing shout ${shoutIdFromUrl}`)
if (shoutIdFromUrl) setShoutId(shoutIdFromUrl) if (shoutIdFromUrl) setShoutId(shoutIdFromUrl)
}) },
{ defer: true },
),
)
createEffect( createEffect(
on([session, shout, shoutId], async ([ses, sh, shid]) => { on([session, shout, shoutId], async ([ses, sh, shid]) => {