From 748bd206d1666e56382be388d87d649ae39fe413 Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 16:03:47 +0300 Subject: [PATCH 01/31] small-fixes --- src/components/Nav/Header/Link.tsx | 4 ++-- src/context/editor.tsx | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Nav/Header/Link.tsx b/src/components/Nav/Header/Link.tsx index c041c4d0..6bf639b5 100644 --- a/src/components/Nav/Header/Link.tsx +++ b/src/components/Nav/Header/Link.tsx @@ -17,11 +17,11 @@ type Props = { export const Link = (props: Props) => { const { page } = useRouter() - const isSelected = page().route === props.routeName + const isSelected = page()?.route === props.routeName return (
  • { export const EditorProvider = (props: { children: JSX.Element }) => { const { t } = useLocalize() const { page } = useRouter() + const { author } = useSession() const { showSnackbar } = useSnackbar() const [isEditorPanelVisible, setIsEditorPanelVisible] = createSignal(false) const editorRef: { current: () => Editor } = { current: null } @@ -132,7 +134,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { lead: formToUpdate.lead, description: formToUpdate.description, cover: formToUpdate.coverImageUrl, - media: formToUpdate.media, + media: formToUpdate.media }, publish, }) From 20e4e985f52b1f977577d61fa8a0fde187f787f5 Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 16:25:25 +0300 Subject: [PATCH 02/31] fmt --- src/components/Nav/AuthModal/RegisterForm.tsx | 11 ++++++----- src/components/Nav/AuthModal/SendResetLinkForm.tsx | 10 ++++++++-- src/context/editor.tsx | 4 ++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/components/Nav/AuthModal/RegisterForm.tsx b/src/components/Nav/AuthModal/RegisterForm.tsx index fd3b2467..a21818b1 100644 --- a/src/components/Nav/AuthModal/RegisterForm.tsx +++ b/src/components/Nav/AuthModal/RegisterForm.tsx @@ -152,9 +152,10 @@ export const RegisterForm = () => { ...prev, email: ( <> - {t('This email is registered')}. {t('You can')}{' '} + {t('This email is registered')} + {'. '} changeSearchParams({ mode: 'send-reset-link' })}> - {t('Set the new password').toLocaleLowerCase()} + {t('Set the new password')} ), @@ -196,7 +197,7 @@ export const RegisterForm = () => { disabled={Boolean(emailStatus())} placeholder={t('Full name')} autocomplete="one-time-code" - onInput={(event) => handleNameInput(event.currentTarget.value)} + onChange={(event) => handleNameInput(event.currentTarget.value)} /> @@ -227,8 +228,8 @@ export const RegisterForm = () => { setPasswordError(err)} - onInput={(value) => setPassword(value)} + errorMessage={(err) => !emailStatus() && setPasswordError(err)} + onInput={(value) => setPassword(emailStatus() ? '' : value)} />
    diff --git a/src/components/Nav/AuthModal/SendResetLinkForm.tsx b/src/components/Nav/AuthModal/SendResetLinkForm.tsx index b1880d9d..d3583791 100644 --- a/src/components/Nav/AuthModal/SendResetLinkForm.tsx +++ b/src/components/Nav/AuthModal/SendResetLinkForm.tsx @@ -1,7 +1,7 @@ import type { AuthModalSearchParams } from './types' import { clsx } from 'clsx' -import { JSX, Show, createSignal } from 'solid-js' +import { JSX, Show, createSignal, onMount } from 'solid-js' import { useLocalize } from '../../../context/localize' import { useSession } from '../../../context/session' @@ -72,6 +72,12 @@ export const SendResetLinkForm = () => { } } + onMount(() => { + if (email()) { + console.info('[SendResetLinkForm] email detected') + } + }) + return (
    { type="email" value={email()} placeholder={t('Email')} - onInput={(event) => handleEmailInput(event.currentTarget.value)} + onChange={(event) => handleEmailInput(event.currentTarget.value)} /> diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 73e4bde1..8e8556f0 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -12,8 +12,8 @@ import { addArticles } from '../stores/zine/articles' import { slugify } from '../utils/slugify' import { useLocalize } from './localize' -import { useSnackbar } from './snackbar' import { useSession } from './session' +import { useSnackbar } from './snackbar' type WordCounter = { characters: number @@ -134,7 +134,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { lead: formToUpdate.lead, description: formToUpdate.description, cover: formToUpdate.coverImageUrl, - media: formToUpdate.media + media: formToUpdate.media, }, publish, }) From 6fa6076f9f911cbb467c785ab65ca922cbc2fdeb Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 17:22:11 +0300 Subject: [PATCH 03/31] editor-context-fixes --- src/context/editor.tsx | 47 ++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 8e8556f0..5700ed05 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -12,7 +12,6 @@ import { addArticles } from '../stores/zine/articles' import { slugify } from '../utils/slugify' import { useLocalize } from './localize' -import { useSession } from './session' import { useSnackbar } from './snackbar' type WordCounter = { @@ -40,7 +39,7 @@ type EditorContextType = { wordCounter: Accessor form: ShoutForm formErrors: Record - editorRef: { current: () => Editor } + editorRef: { current: () => Editor | null } saveShout: (form: ShoutForm) => Promise saveDraft: (form: ShoutForm) => Promise saveDraftToLocalStorage: (form: ShoutForm) => void @@ -73,7 +72,7 @@ const saveDraftToLocalStorage = (formToSave: ShoutForm) => { localStorage.setItem(`shout-${formToSave.shoutId}`, JSON.stringify(formToSave)) } const getDraftFromLocalStorage = (shoutId: number) => { - return JSON.parse(localStorage.getItem(`shout-${shoutId}`)) + return JSON.parse(localStorage.getItem(`shout-${shoutId}`) || '') } const removeDraftFromLocalStorage = (shoutId: number) => { @@ -81,14 +80,19 @@ const removeDraftFromLocalStorage = (shoutId: number) => { } export const EditorProvider = (props: { children: JSX.Element }) => { - const { t } = useLocalize() + const localize = useLocalize() const { page } = useRouter() - const { author } = useSession() - const { showSnackbar } = useSnackbar() + const snackbar = useSnackbar() const [isEditorPanelVisible, setIsEditorPanelVisible] = createSignal(false) - const editorRef: { current: () => Editor } = { current: null } - const [form, setForm] = createStore(null) - const [formErrors, setFormErrors] = createStore>(null) + const editorRef: { current: () => Editor | null } = { current: () => null } + const [form, setForm] = createStore({ + body: '', + slug: '', + shoutId: 0, + title: '', + selectedTopics: [], + }) + const [formErrors, setFormErrors] = createStore({} as Record) const [wordCounter, setWordCounter] = createSignal({ characters: 0, words: 0, @@ -97,13 +101,16 @@ export const EditorProvider = (props: { children: JSX.Element }) => { const countWords = (value) => setWordCounter(value) const validate = () => { if (!form.title) { - setFormErrors('title', t('Please, set the article title')) + setFormErrors('title', localize?.t('Please, set the article title') || '') return false } - const parsedMedia = JSON.parse(form.media) + const parsedMedia = JSON.parse(form.media || '') if (form.layout === 'video' && !parsedMedia[0]) { - showSnackbar({ type: 'error', body: t('Looks like you forgot to upload the video') }) + snackbar?.showSnackbar({ + type: 'error', + body: localize?.t('Looks like you forgot to upload the video'), + }) return false } @@ -112,7 +119,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { const validateSettings = () => { if (form.selectedTopics.length === 0) { - setFormErrors('selectedTopics', t('Required')) + setFormErrors('selectedTopics', localize?.t('Required') || '') return false } @@ -145,11 +152,11 @@ export const EditorProvider = (props: { children: JSX.Element }) => { toggleEditorPanel() } - if (page().route === 'edit' && !validate()) { + if (page()?.route === 'edit' && !validate()) { return } - if (page().route === 'editSettings' && !validateSettings()) { + if (page()?.route === 'editSettings' && !validateSettings()) { return } @@ -164,7 +171,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } } catch (error) { console.error('[saveShout]', error) - showSnackbar({ type: 'error', body: t('Error') }) + snackbar?.showSnackbar({ type: 'error', body: localize?.t('Error') || '' }) } } @@ -177,7 +184,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { toggleEditorPanel() } - if (page().route === 'edit') { + if (page()?.route === 'edit') { if (!validate()) { return } @@ -199,7 +206,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { openPage(router, 'feed') } catch (error) { console.error('[publishShout]', error) - showSnackbar({ type: 'error', body: t('Error') }) + snackbar?.showSnackbar({ type: 'error', body: localize?.t('Error') || '' }) } } @@ -217,7 +224,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } } catch (error) { console.error('[publishShoutById]', error) - showSnackbar({ type: 'error', body: t('Error') }) + snackbar?.showSnackbar({ type: 'error', body: localize?.t('Error') }) } } @@ -228,7 +235,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { }) return true } catch { - showSnackbar({ type: 'error', body: t('Error') }) + snackbar?.showSnackbar({ type: 'error', body: localize?.t('Error') || '' }) return false } } From 002ffe64fc0fb7153e2d6566a8d486560d9fe28e Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 17:28:57 +0300 Subject: [PATCH 04/31] parse-tolerate --- src/components/Article/FullArticle.tsx | 2 +- src/context/connect.tsx | 2 +- src/context/editor.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index a8c54c98..0582010d 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -135,7 +135,7 @@ export const FullArticle = (props: Props) => { const media = createMemo(() => { try { - return JSON.parse(props.article.media) + return JSON.parse(props.article?.media || "[]") } catch { return [] } diff --git a/src/context/connect.tsx b/src/context/connect.tsx index d10d0695..41e1cab6 100644 --- a/src/context/connect.tsx +++ b/src/context/connect.tsx @@ -50,7 +50,7 @@ export const ConnectProvider = (props: { children: JSX.Element }) => { Authorization: token, }, onmessage(event) { - const m: SSEMessage = JSON.parse(event.data) + const m: SSEMessage = JSON.parse(event.data || "{}") console.log('[context.connect] Received message:', m) // Iterate over all registered handlers and call them diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 5700ed05..9d40ec50 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -72,7 +72,7 @@ const saveDraftToLocalStorage = (formToSave: ShoutForm) => { localStorage.setItem(`shout-${formToSave.shoutId}`, JSON.stringify(formToSave)) } const getDraftFromLocalStorage = (shoutId: number) => { - return JSON.parse(localStorage.getItem(`shout-${shoutId}`) || '') + return JSON.parse(localStorage.getItem(`shout-${shoutId}`) || '{}') } const removeDraftFromLocalStorage = (shoutId: number) => { @@ -105,7 +105,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { return false } - const parsedMedia = JSON.parse(form.media || '') + const parsedMedia = JSON.parse(form.media || '[]') if (form.layout === 'video' && !parsedMedia[0]) { snackbar?.showSnackbar({ type: 'error', From e32e3d31ea4ad8ed2c03dad39acf4d739d96277f Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 17:31:08 +0300 Subject: [PATCH 05/31] fmt --- src/components/Article/FullArticle.tsx | 2 +- src/context/connect.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 0582010d..9d3f8c9d 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -135,7 +135,7 @@ export const FullArticle = (props: Props) => { const media = createMemo(() => { try { - return JSON.parse(props.article?.media || "[]") + return JSON.parse(props.article?.media || '[]') } catch { return [] } diff --git a/src/context/connect.tsx b/src/context/connect.tsx index 41e1cab6..dfd8d549 100644 --- a/src/context/connect.tsx +++ b/src/context/connect.tsx @@ -50,7 +50,7 @@ export const ConnectProvider = (props: { children: JSX.Element }) => { Authorization: token, }, onmessage(event) { - const m: SSEMessage = JSON.parse(event.data || "{}") + const m: SSEMessage = JSON.parse(event.data || '{}') console.log('[context.connect] Received message:', m) // Iterate over all registered handlers and call them From 3a6faa65a83785950a8286489d67586c1efd8874 Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 17:40:10 +0300 Subject: [PATCH 06/31] tolerate-fails-more --- src/components/Article/FullArticle.tsx | 2 +- src/components/Feed/ArticleCard/ArticleCard.tsx | 2 +- src/context/editor.tsx | 2 +- src/utils/sortby.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 9d3f8c9d..ab14f1e6 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -77,7 +77,7 @@ export const FullArticle = (props: Props) => { const { t, formatDate, lang } = useLocalize() const { author, isAuthenticated, requireAuthentication } = useSession() - const formattedDate = createMemo(() => formatDate(new Date(props.article.published_at * 1000))) + const formattedDate = createMemo(() => formatDate(new Date((props.article?.published_at || 0) * 1000))) const canEdit = () => props.article.authors?.some((a) => Boolean(a) && a?.slug === author()?.slug) const mainTopic = createMemo(() => { diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 31743db2..58f69cdf 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -117,7 +117,7 @@ export const ArticleCard = (props: ArticleCardProps) => { const { title, subtitle } = getTitleAndSubtitle(props.article) const formattedDate = createMemo(() => - props.article.published_at ? formatDate(new Date(props.article.published_at * 1000)) : '', + props.article?.published_at ? formatDate(new Date(props.article.published_at * 1000)) : '', ) const canEdit = () => diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 9d40ec50..d2f1b82b 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -164,7 +164,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { const shout = await updateShout(formToSave, { publish: false }) removeDraftFromLocalStorage(formToSave.shoutId) - if (shout.published_at) { + if (shout?.published_at) { openPage(router, 'article', { slug: shout.slug }) } else { openPage(router, 'drafts') diff --git a/src/utils/sortby.ts b/src/utils/sortby.ts index 7566f577..9cd2182d 100644 --- a/src/utils/sortby.ts +++ b/src/utils/sortby.ts @@ -7,7 +7,7 @@ export const byCreated = (a: Shout | Reaction, b: Shout | Reaction) => { } export const byPublished = (a: Shout, b: Shout) => { - return a.published_at - b.published_at + return (a?.published_at || 0) - (b?.published_at || 0) } export const byLength = ( From 0dd2736dd518be3ddd6f92828d62b17bee166c5f Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 18:03:01 +0300 Subject: [PATCH 07/31] catch-response-on-update --- .../Views/PublishSettings/PublishSettings.tsx | 8 ++--- src/context/editor.tsx | 31 ++++++++++++++----- src/graphql/client/core.ts | 4 +-- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/components/Views/PublishSettings/PublishSettings.tsx b/src/components/Views/PublishSettings/PublishSettings.tsx index 7bc52d56..78dcdfbe 100644 --- a/src/components/Views/PublishSettings/PublishSettings.tsx +++ b/src/components/Views/PublishSettings/PublishSettings.tsx @@ -70,10 +70,10 @@ export const PublishSettings = (props: Props) => { return { coverImageUrl: props.form?.coverImageUrl, mainTopic: props.form?.mainTopic || EMPTY_TOPIC, - slug: props.form?.slug, - title: props.form?.title, - subtitle: props.form?.subtitle, - description: composeDescription(), + slug: props.form?.slug || '', + title: props.form?.title || '', + subtitle: props.form?.subtitle || '', + description: composeDescription() || '', selectedTopics: [], } }) diff --git a/src/context/editor.tsx b/src/context/editor.tsx index d2f1b82b..da11f919 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -161,7 +161,11 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } try { - const shout = await updateShout(formToSave, { publish: false }) + const { shout, error } = await updateShout(formToSave, { publish: false }) + if (error) { + snackbar?.showSnackbar({ type: 'error', body: localize?.t(error) || '' }) + return + } removeDraftFromLocalStorage(formToSave.shoutId) if (shout?.published_at) { @@ -176,24 +180,33 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } const saveDraft = async (draftForm: ShoutForm) => { - await updateShout(draftForm, { publish: false }) + const { error } = await updateShout(draftForm, { publish: false }) + if (error) { + snackbar?.showSnackbar({ type: 'error', body: localize?.t(error) || '' }) + return + } } const publishShout = async (formToPublish: ShoutForm) => { - if (isEditorPanelVisible()) { + const editorPanelVisible = isEditorPanelVisible() + const pageRoute = page()?.route + + if (editorPanelVisible) { toggleEditorPanel() } - if (page()?.route === 'edit') { + if (pageRoute === 'edit') { if (!validate()) { return } - await updateShout(formToPublish, { publish: false }) - const slug = slugify(form.title) setForm('slug', slug) openPage(router, 'editSettings', { shoutId: form.shoutId.toString() }) + const { error } = await updateShout(formToPublish, { publish: false }) + if (error) { + snackbar?.showSnackbar({ type: 'error', body: localize?.t(error) || '' }) + } return } @@ -202,7 +215,11 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } try { - await updateShout(formToPublish, { publish: true }) + const { error } = await updateShout(formToPublish, { publish: true }) + if (error) { + snackbar?.showSnackbar({ type: 'error', body: localize?.t(error) || '' }) + return + } openPage(router, 'feed') } catch (error) { console.error('[publishShout]', error) diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index c80fe931..edf40567 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -157,12 +157,12 @@ export const apiClient = { shout_id: number shout_input?: ShoutInput publish: boolean - }): Promise => { + }): Promise => { const response = await apiClient.private .mutation(updateArticle, { shout_id, shout_input, publish }) .toPromise() console.debug('[graphql.client.core] updateArticle:', response.data) - return response.data.update_shout.shout + return response.data.update_shout }, deleteShout: async (params: MutationDelete_ShoutArgs): Promise => { const response = await apiClient.private.mutation(deleteShout, params).toPromise() From 560739627ad4f48dd6de861e990ea99aaf42b080 Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 18:13:54 +0300 Subject: [PATCH 08/31] more-defined --- src/components/Views/EditView/EditView.tsx | 4 ++-- src/components/Views/PublishSettings/PublishSettings.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Views/EditView/EditView.tsx b/src/components/Views/EditView/EditView.tsx index 4e862696..1969e338 100644 --- a/src/components/Views/EditView/EditView.tsx +++ b/src/components/Views/EditView/EditView.tsx @@ -307,10 +307,10 @@ export const EditView = (props: Props) => { subtitleInput.current = el }} allowEnterKey={false} - value={(value) => setForm('subtitle', value)} + value={(value) => setForm('subtitle', value || '')} class={styles.subtitleInput} placeholder={t('Subheader')} - initialValue={form.subtitle} + initialValue={form.subtitle || ''} maxLength={MAX_HEADER_LIMIT} /> diff --git a/src/components/Views/PublishSettings/PublishSettings.tsx b/src/components/Views/PublishSettings/PublishSettings.tsx index 78dcdfbe..47a2dee4 100644 --- a/src/components/Views/PublishSettings/PublishSettings.tsx +++ b/src/components/Views/PublishSettings/PublishSettings.tsx @@ -100,7 +100,7 @@ export const PublishSettings = (props: Props) => { const handleTopicSelectChange = (newSelectedTopics) => { if ( props.form.selectedTopics.length === 0 || - newSelectedTopics.every((topic) => topic.id !== props.form.mainTopic.id) + newSelectedTopics.every((topic) => topic.id !== props.form.mainTopic?.id) ) { setSettingsForm((prev) => { return { @@ -176,7 +176,7 @@ export const PublishSettings = (props: Props) => {
    {settingsForm.mainTopic.title}
    {settingsForm.title}
    -
    {settingsForm.subtitle}
    +
    {settingsForm.subtitle || ''}
    {author()?.name}
    @@ -203,7 +203,7 @@ export const PublishSettings = (props: Props) => { variant="bordered" fieldName={t('Subheader')} placeholder={t('Come up with a subtitle for your story')} - initialValue={settingsForm.subtitle} + initialValue={settingsForm.subtitle || ''} value={(value) => setSettingsForm('subtitle', value)} allowEnterKey={false} maxLength={100} From 3f7679710f0021f555dcadf7bbd0049eb0d42360 Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 18:44:56 +0300 Subject: [PATCH 09/31] minor --- public/locales/ru/translation.json | 1 + .../Feed/ArticleCard/ArticleCard.tsx | 37 ++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index bcdc7e2c..716bf306 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -529,6 +529,7 @@ "repeat": "повторить", "resend confirmation link": "отправить ссылку ещё раз", "shout": "пост", + "shout not found": "публикация не найдена", "shoutsWithCount": "{count} {count, plural, one {пост} few {поста} other {постов}}", "sign in": "войти", "sign up or sign in": "зарегистрироваться или войти", diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 58f69cdf..92ecb5f1 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -23,7 +23,7 @@ import stylesHeader from '../../Nav/Header/Header.module.scss' import styles from './ArticleCard.module.scss' export type ArticleCardProps = { - // TODO: refactor this, please +// TODO: refactor this, please settings?: { noicon?: boolean noimage?: boolean @@ -67,7 +67,7 @@ const getTitleAndSubtitle = ( subtitle: string } => { let title = article.title - let subtitle = article.subtitle + let subtitle: string = article.subtitle || '' if (!subtitle) { let tt = article.title?.split('. ') || [] @@ -79,7 +79,7 @@ const getTitleAndSubtitle = ( if (tt && tt.length > 1) { const sep = article.title?.replace(tt[0], '').split(' ', 1)[0] title = tt[0] + (sep === '.' || sep === ':' ? '' : sep) - subtitle = capitalize(article.title?.replace(tt[0] + sep, ''), true) + subtitle = capitalize(article.title?.replace(tt[0] + sep, ''), true) || '' } } @@ -131,6 +131,7 @@ export const ArticleCard = (props: ArticleCardProps) => { scrollTo: 'comments', }) } + return (
    { [aspectRatio()]: props.withAspectRatio, })} > + {/* Cover Image */} + {/* Cover Image Container */}
    {
    + + {/* Shout Card Content */}
    + {/* Shout Card Icon */} { + {/* Main Topic */} { /> + {/* Title and Subtitle */}
    {
    + + {/* Details */} + {/* Author and Date */}
    - {(a: Author) => { - return ( - - ) - }} + {(a: Author) => ( + + )}
    @@ -244,6 +253,8 @@ export const ArticleCard = (props: ArticleCardProps) => {
    + + {/* Description */}
    From c2035b801af2f1921427df86af80821bc872e1e7 Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 17 Feb 2024 21:57:02 +0300 Subject: [PATCH 10/31] update-fixxd --- src/components/Feed/ArticleCard/ArticleCard.tsx | 4 ++-- src/context/editor.tsx | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 92ecb5f1..760ce1e3 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -23,7 +23,7 @@ import stylesHeader from '../../Nav/Header/Header.module.scss' import styles from './ArticleCard.module.scss' export type ArticleCardProps = { -// TODO: refactor this, please + // TODO: refactor this, please settings?: { noicon?: boolean noimage?: boolean @@ -192,7 +192,7 @@ export const ArticleCard = (props: ArticleCardProps) => { diff --git a/src/context/editor.tsx b/src/context/editor.tsx index da11f919..40f21d2d 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -229,10 +229,15 @@ export const EditorProvider = (props: { children: JSX.Element }) => { const publishShoutById = async (shout_id: number) => { try { - const newShout = await apiClient.updateArticle({ + const { shout: newShout, error } = await apiClient.updateArticle({ shout_id, publish: true, }) + if (error) { + console.error(error) + snackbar?.showSnackbar({ type: 'error', body: error }) + return + } if (newShout) { addArticles([newShout]) openPage(router, 'feed') From 9b7079def57226fa2bedf59ac14658c80ea1cd52 Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 4 Mar 2024 18:06:40 +0300 Subject: [PATCH 11/31] naming-fix --- src/components/Feed/ArticleCard/ArticleCard.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 70841971..a22db42d 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -70,16 +70,16 @@ const getTitleAndSubtitle = ( let subtitle: string = article.subtitle || '' if (!subtitle) { - let tt = article.title?.split('. ') || [] + let titleParts = article.title?.split('. ') || [] - if (tt?.length === 1) { - tt = article.title?.split(/{!|\?|:|;}\s/) || [] + if (titleParts?.length === 1) { + titleParts = article.title?.split(/{!|\?|:|;}\s/) || [] } - if (tt && tt.length > 1) { - const sep = article.title?.replace(tt[0], '').split(' ', 1)[0] - title = tt[0] + (sep === '.' || sep === ':' ? '' : sep) - subtitle = capitalize(article.title?.replace(tt[0] + sep, ''), true) || '' + if (titleParts && titleParts.length > 1) { + const sep = article.title?.replace(titleParts[0], '').split(' ', 1)[0] + title = titleParts[0] + (sep === '.' || sep === ':' ? '' : sep) + subtitle = capitalize(article.title?.replace(titleParts[0] + sep, ''), true) || '' } } From f8bf3d86a0c1b61138650f7dfa1ef4d64f05012a Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 5 Mar 2024 16:01:47 +0300 Subject: [PATCH 12/31] edit-access+redirect --- src/components/Inbox/DialogAvatar.tsx | 5 ++++- src/graphql/client/core.ts | 7 +++++++ src/pages/edit.page.tsx | 12 ++++++++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/components/Inbox/DialogAvatar.tsx b/src/components/Inbox/DialogAvatar.tsx index 875cdc98..1e2d68e4 100644 --- a/src/components/Inbox/DialogAvatar.tsx +++ b/src/components/Inbox/DialogAvatar.tsx @@ -51,7 +51,10 @@ const DialogAvatar = (props: Props) => { {nameFirstLetter()}
    }>
    diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index 753f2f86..e8a2aaf7 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -210,6 +210,13 @@ export const apiClient = { return resp.data.get_shout }, + getMyShout: async (shout_id: number) => { + const resp = await apiClient.private.query(shoutLoad, { shout_id }).toPromise() + if (resp.error) console.error(resp) + + return resp.data.get_shout + }, + getShouts: async (options: LoadShoutsOptions) => { const resp = await publicGraphQLClient.query(shoutsLoadBy, { options }).toPromise() if (resp.error) console.error(resp) diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index 031eedf4..f4b7fd00 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -7,8 +7,10 @@ import { useLocalize } from '../context/localize' import { apiClient } from '../graphql/client/core' import { Shout } from '../graphql/schema/core.gen' import { useRouter } from '../stores/router' +import { router } from '../stores/router' import { LayoutType } from './types' +import { redirectPage } from "@nanostores/router"; const EditView = lazy(() => import('../components/Views/EditView/EditView')) @@ -21,8 +23,14 @@ export const EditPage = () => { const [shout, setShout] = createSignal(null) onMount(async () => { - const loadedShout = await apiClient.getShoutById(shoutId()) - setShout(loadedShout) + const loadedShout = await apiClient.getMyShout(shoutId()) + console.log(loadedShout) + if (loadedShout) { + setShout(loadedShout) + } + else { + redirectPage(router, 'drafts') + } }) const title = createMemo(() => { From 4ed15f405e9ab51cae334f53c60e1cb252dca734 Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 5 Mar 2024 16:07:14 +0300 Subject: [PATCH 13/31] access+userpic-fix --- public/locales/en/translation.json | 1 + public/locales/ru/translation.json | 1 + src/components/Inbox/DialogAvatar.tsx | 13 +++++++++---- src/pages/edit.page.tsx | 8 +++++--- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 5dfd02bb..cc47cdd3 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -378,6 +378,7 @@ "There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?": "There are unsaved changes in your profile settings. Are you sure you want to leave the page without saving?", "There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?": "There are unsaved changes in your publishing settings. Are you sure you want to leave the page without saving?", "This comment has not yet been rated": "This comment has not yet been rated", + "This content is not published yet": "This content is not published yet", "This email is": "This email is", "This email is not verified": "This email is not verified", "This email is verified": "This email is verified", diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 573b313c..1c6e5596 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -148,6 +148,7 @@ "Enter the code or click the link from email to confirm": "Введите код из письма или пройдите по ссылке в письме для подтверждения регистрации", "Enter your new password": "Введите новый пароль", "Enter": "Войти", + "This content is not published yet": "Содержимое ещё не опубликовано", "Error": "Ошибка", "Please give us your email address": "Пожалуйста, укажите свою почту, чтобы получить ссылку для сброса пароля", "Experience": "Личный опыт", diff --git a/src/components/Inbox/DialogAvatar.tsx b/src/components/Inbox/DialogAvatar.tsx index 1e2d68e4..d34067d6 100644 --- a/src/components/Inbox/DialogAvatar.tsx +++ b/src/components/Inbox/DialogAvatar.tsx @@ -51,10 +51,15 @@ const DialogAvatar = (props: Props) => { {nameFirstLetter()}}>
    diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index f4b7fd00..c2aa7b4b 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -9,13 +9,15 @@ import { Shout } from '../graphql/schema/core.gen' import { useRouter } from '../stores/router' import { router } from '../stores/router' +import { redirectPage } from '@nanostores/router' +import { useSnackbar } from '../context/snackbar' import { LayoutType } from './types' -import { redirectPage } from "@nanostores/router"; const EditView = lazy(() => import('../components/Views/EditView/EditView')) export const EditPage = () => { const { page } = useRouter() + const snackbar = useSnackbar() const { t } = useLocalize() const shoutId = createMemo(() => Number((page().params as Record<'shoutId', string>).shoutId)) @@ -27,8 +29,8 @@ export const EditPage = () => { console.log(loadedShout) if (loadedShout) { setShout(loadedShout) - } - else { + } else { + await snackbar?.showSnackbar({ type: 'error', body: t('This content is not published yet') }) redirectPage(router, 'drafts') } }) From 2d7fd38d82d0b56df6b64abf78037ec839ccef68 Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 5 Mar 2024 16:44:51 +0300 Subject: [PATCH 14/31] get-my-shout --- src/graphql/client/core.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index e8a2aaf7..569885bb 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -199,16 +199,11 @@ export const apiClient = { console.debug('[graphql.client.core] authorsLoadBy:', resp) return resp.data.load_authors_by }, + getShoutBySlug: async (slug: string) => { const resp = await publicGraphQLClient.query(shoutLoad, { slug }).toPromise() return resp.data.get_shout }, - getShoutById: async (shout_id: number) => { - const resp = await publicGraphQLClient.query(shoutLoad, { shout_id }).toPromise() - if (resp.error) console.error(resp) - - return resp.data.get_shout - }, getMyShout: async (shout_id: number) => { const resp = await apiClient.private.query(shoutLoad, { shout_id }).toPromise() From dc719120b252a53f96e6f258169834008edcb819 Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 5 Mar 2024 18:20:47 +0300 Subject: [PATCH 15/31] debug-update-shout --- src/context/editor.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 40f21d2d..1fe675e1 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -127,6 +127,10 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } const updateShout = async (formToUpdate: ShoutForm, { publish }: { publish: boolean }) => { + if (!formToUpdate.shoutId) { + console.error(formToUpdate) + return {"error": "not enought data"} + } return await apiClient.updateArticle({ shout_id: formToUpdate.shoutId, shout_input: { @@ -228,6 +232,10 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } const publishShoutById = async (shout_id: number) => { + if (!shout_id) { + console.error(`shout_id is ${shout_id}`) + return + } try { const { shout: newShout, error } = await apiClient.updateArticle({ shout_id, From 449154bd1bf7b2ededfdffc9e074c2e3056f5505 Mon Sep 17 00:00:00 2001 From: Untone Date: Tue, 5 Mar 2024 18:52:34 +0300 Subject: [PATCH 16/31] get-shouts-drafts --- src/graphql/client/core.ts | 2 +- src/graphql/query/core/articles-load-drafts.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index 569885bb..008915f3 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -177,7 +177,7 @@ export const apiClient = { getDrafts: async (): Promise => { const response = await apiClient.private.query(draftsLoad, {}).toPromise() console.debug('[graphql.client.core] getDrafts:', response) - return response.data.load_shouts_drafts + return response.data.get_shouts_drafts }, createReaction: async (input: ReactionInput) => { const response = await apiClient.private.mutation(reactionCreate, { reaction: input }).toPromise() diff --git a/src/graphql/query/core/articles-load-drafts.ts b/src/graphql/query/core/articles-load-drafts.ts index af33cf9a..ae425df4 100644 --- a/src/graphql/query/core/articles-load-drafts.ts +++ b/src/graphql/query/core/articles-load-drafts.ts @@ -2,7 +2,7 @@ import { gql } from '@urql/core' export default gql` query LoadDraftsQuery { - load_shouts_drafts { + get_shouts_drafts { id title subtitle @@ -23,6 +23,13 @@ export default gql` followers } } + created_by { + id + name + slug + pic + created_at + } authors { id name @@ -35,7 +42,6 @@ export default gql` featured_at stat { viewed - rating commented } From ce6687408992fa6e8367eccc395693a17ef0f5eb Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 10:30:07 +0300 Subject: [PATCH 17/31] no-created-by-unwrap --- src/graphql/client/core.ts | 6 +-- src/graphql/query/core/article-my.ts | 50 +++++++++++++++++++ .../query/core/articles-load-drafts.ts | 7 --- 3 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 src/graphql/query/core/article-my.ts diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index 008915f3..f376390e 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -30,6 +30,7 @@ import unfollowMutation from '../mutation/core/unfollow' import shoutLoad from '../query/core/article-load' import shoutsLoadBy from '../query/core/articles-load-by' import draftsLoad from '../query/core/articles-load-drafts' +import getMyShout from '../query/core/article-my' import myFeed from '../query/core/articles-load-feed' import loadShoutsTopRandom from '../query/core/articles-load-random-top' import articlesLoadRandomTopic from '../query/core/articles-load-random-topic' @@ -41,7 +42,6 @@ import authorFollows from '../query/core/author-follows' import authorId from '../query/core/author-id' import authorsAll from '../query/core/authors-all' import authorsLoadBy from '../query/core/authors-load-by' -import mySubscriptions from '../query/core/my-followed' import reactionsLoadBy from '../query/core/reactions-load-by' import topicBySlug from '../query/core/topic-by-slug' import topicsAll from '../query/core/topics-all' @@ -206,10 +206,10 @@ export const apiClient = { }, getMyShout: async (shout_id: number) => { - const resp = await apiClient.private.query(shoutLoad, { shout_id }).toPromise() + const resp = await apiClient.private.query(getMyShout, { shout_id }).toPromise() if (resp.error) console.error(resp) - return resp.data.get_shout + return resp.data.get_my_shout }, getShouts: async (options: LoadShoutsOptions) => { diff --git a/src/graphql/query/core/article-my.ts b/src/graphql/query/core/article-my.ts new file mode 100644 index 00000000..1399efe0 --- /dev/null +++ b/src/graphql/query/core/article-my.ts @@ -0,0 +1,50 @@ +import { gql } from '@urql/core' + +export default gql` + query GetMyShout($shout_id: Int!) { + get_my_shout(shout_id: $shout_id) { + id + title + lead + description + subtitle + slug + layout + cover + cover_caption + body + media + updated_by { + id + name + slug + pic + created_at + } + # community + main_topic + topics { + id + title + body + slug + stat { + shouts + authors + followers + } + } + authors { + id + name + slug + pic + created_at + } + created_at + updated_at + published_at + featured_at + } + } +` diff --git a/src/graphql/query/core/articles-load-drafts.ts b/src/graphql/query/core/articles-load-drafts.ts index ae425df4..f81d0a2f 100644 --- a/src/graphql/query/core/articles-load-drafts.ts +++ b/src/graphql/query/core/articles-load-drafts.ts @@ -23,13 +23,6 @@ export default gql` followers } } - created_by { - id - name - slug - pic - created_at - } authors { id name From 5b97ea374630933687ef7fac303b9500341555bf Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 12:04:33 +0300 Subject: [PATCH 18/31] delete-reaction-fix --- src/context/editor.tsx | 2 +- src/context/reactions.tsx | 9 ++++++++- src/graphql/client/core.ts | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 1fe675e1..da9fe026 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -129,7 +129,7 @@ export const EditorProvider = (props: { children: JSX.Element }) => { const updateShout = async (formToUpdate: ShoutForm, { publish }: { publish: boolean }) => { if (!formToUpdate.shoutId) { console.error(formToUpdate) - return {"error": "not enought data"} + return { error: 'not enought data' } } return await apiClient.updateArticle({ shout_id: formToUpdate.shoutId, diff --git a/src/context/reactions.tsx b/src/context/reactions.tsx index f23c5044..a9ba2a10 100644 --- a/src/context/reactions.tsx +++ b/src/context/reactions.tsx @@ -5,6 +5,8 @@ import { createStore, reconcile } from 'solid-js/store' import { apiClient } from '../graphql/client/core' import { Reaction, ReactionBy, ReactionInput, ReactionKind } from '../graphql/schema/core.gen' +import { useLocalize } from './localize' +import { useSnackbar } from './snackbar' type ReactionsContextType = { reactionEntities: Record @@ -30,6 +32,8 @@ export function useReactions() { export const ReactionsProvider = (props: { children: JSX.Element }) => { const [reactionEntities, setReactionEntities] = createStore>({}) + const { t } = useLocalize() + const { showSnackbar } = useSnackbar() const loadReactionsBy = async ({ by, @@ -81,7 +85,10 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { const deleteReaction = async (reaction_id: number): Promise => { if (reaction_id) { - await apiClient.destroyReaction(reaction_id) + const { error } = await apiClient.destroyReaction(reaction_id) + if (error) { + await showSnackbar({ type: 'error', body: t(error) }) + } setReactionEntities({ [reaction_id]: undefined, }) diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index f376390e..6f42efc3 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -28,9 +28,9 @@ import reactionDestroy from '../mutation/core/reaction-destroy' import reactionUpdate from '../mutation/core/reaction-update' import unfollowMutation from '../mutation/core/unfollow' import shoutLoad from '../query/core/article-load' +import getMyShout from '../query/core/article-my' import shoutsLoadBy from '../query/core/articles-load-by' import draftsLoad from '../query/core/articles-load-drafts' -import getMyShout from '../query/core/article-my' import myFeed from '../query/core/articles-load-feed' import loadShoutsTopRandom from '../query/core/articles-load-random-top' import articlesLoadRandomTopic from '../query/core/articles-load-random-topic' From e2c98ded5e37a182bfaa34d2b801decf451a5990 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 12:49:06 +0300 Subject: [PATCH 19/31] reaction-error-handling --- src/context/reactions.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/context/reactions.tsx b/src/context/reactions.tsx index a9ba2a10..78c1e676 100644 --- a/src/context/reactions.tsx +++ b/src/context/reactions.tsx @@ -57,7 +57,8 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { } const createReaction = async (input: ReactionInput): Promise => { - const reaction = await apiClient.createReaction(input) + const {error, reaction} = await apiClient.createReaction(input) + if (error) await showSnackbar({type: 'error', body: t(error)}) if (!reaction) return const changes = { [reaction.id]: reaction, @@ -96,8 +97,9 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { } const updateReaction = async (input: ReactionInput): Promise => { - const reaction = await apiClient.updateReaction(input) - setReactionEntities(reaction.id, reaction) + const {error, reaction} = await apiClient.updateReaction(input) + if (error) await showSnackbar({type: 'error', body: t(error)}) + if (reaction) setReactionEntities(reaction.id, reaction) return reaction } From 57a9fe42a8493b9072e730ae1f1c8239b10386a6 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 12:56:00 +0300 Subject: [PATCH 20/31] bypass-linter --- src/context/reactions.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/context/reactions.tsx b/src/context/reactions.tsx index 78c1e676..6e0e6756 100644 --- a/src/context/reactions.tsx +++ b/src/context/reactions.tsx @@ -57,8 +57,8 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { } const createReaction = async (input: ReactionInput): Promise => { - const {error, reaction} = await apiClient.createReaction(input) - if (error) await showSnackbar({type: 'error', body: t(error)}) + const { error, reaction } = await apiClient.createReaction(input) + if (error) await showSnackbar({ type: 'error', body: t(error) }) if (!reaction) return const changes = { [reaction.id]: reaction, @@ -97,8 +97,8 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { } const updateReaction = async (input: ReactionInput): Promise => { - const {error, reaction} = await apiClient.updateReaction(input) - if (error) await showSnackbar({type: 'error', body: t(error)}) + const { error, reaction } = await apiClient.updateReaction(input) + if (error) await showSnackbar({ type: 'error', body: t(error) }) if (reaction) setReactionEntities(reaction.id, reaction) return reaction } From 136ecda3b194ab3bb26ae924d153a253d674213b Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 13:57:39 +0300 Subject: [PATCH 21/31] topics-comments --- src/graphql/query/core/topics-all.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graphql/query/core/topics-all.ts b/src/graphql/query/core/topics-all.ts index ecbbb188..aea60b64 100644 --- a/src/graphql/query/core/topics-all.ts +++ b/src/graphql/query/core/topics-all.ts @@ -13,6 +13,7 @@ export default gql` shouts authors followers + comments # viewed } } From e252ce464bacce526b3b35ed7c44b9e335707968 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 15:53:51 +0300 Subject: [PATCH 22/31] fmt --- src/components/Topic/TopicBadge/TopicBadge.tsx | 12 +++++++----- src/pages/edit.page.tsx | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/Topic/TopicBadge/TopicBadge.tsx b/src/components/Topic/TopicBadge/TopicBadge.tsx index f4767986..c2679b1e 100644 --- a/src/components/Topic/TopicBadge/TopicBadge.tsx +++ b/src/components/Topic/TopicBadge/TopicBadge.tsx @@ -115,15 +115,17 @@ export const TopicBadge = (props: Props) => {
    - {t('shoutsWithCount', {count: props.topic?.stat?.shouts})} - {t('authorsWithCount', {count: props.topic?.stat?.authors})} + {t('shoutsWithCount', { count: props.topic?.stat?.shouts })} + {t('authorsWithCount', { count: props.topic?.stat?.authors })} - {t('FollowersWithCount', {count: props.topic?.stat?.followers})} + {t('FollowersWithCount', { count: props.topic?.stat?.followers })} - {t('CommentsWithCount', {count: props.topic?.stat?.comments ?? 0})} + + {t('CommentsWithCount', { count: props.topic?.stat?.comments ?? 0 })} +
    - + ) } diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index c2aa7b4b..0feb07e1 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -25,13 +25,13 @@ export const EditPage = () => { const [shout, setShout] = createSignal(null) onMount(async () => { - const loadedShout = await apiClient.getMyShout(shoutId()) + const { shout: loadedShout, error } = await apiClient.getMyShout(shoutId()) console.log(loadedShout) - if (loadedShout) { - setShout(loadedShout) - } else { + if (error) { await snackbar?.showSnackbar({ type: 'error', body: t('This content is not published yet') }) redirectPage(router, 'drafts') + } else { + setShout(loadedShout) } }) From af0c7fa712b54bcb5b4f9e849c807ab5c042864d Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 16:01:46 +0300 Subject: [PATCH 23/31] get-my-shout-fix --- src/graphql/query/core/article-my.ts | 75 +++++++++++++++------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/graphql/query/core/article-my.ts b/src/graphql/query/core/article-my.ts index 1399efe0..dcd41ea2 100644 --- a/src/graphql/query/core/article-my.ts +++ b/src/graphql/query/core/article-my.ts @@ -3,48 +3,51 @@ import { gql } from '@urql/core' export default gql` query GetMyShout($shout_id: Int!) { get_my_shout(shout_id: $shout_id) { - id - title - lead - description - subtitle - slug - layout - cover - cover_caption - body - media - updated_by { - id - name - slug - pic - created_at - } - # community - main_topic - topics { + error + shout { id title + lead + description + subtitle + slug + layout + cover + cover_caption body - slug - stat { - shouts - authors - followers + media + updated_by { + id + name + slug + pic + created_at + } + # community + main_topic + topics { + id + title + body + slug + stat { + shouts + authors + followers + } + } + authors { + id + name + slug + pic + created_at } - } - authors { - id - name - slug - pic created_at + updated_at + published_at + featured_at } - created_at - updated_at - published_at - featured_at } } ` From d7f00cd9622a303fe3bee7085ec96aec1d91c52f Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 6 Mar 2024 22:16:55 +0300 Subject: [PATCH 24/31] query-fix --- src/graphql/client/core.ts | 1 + src/graphql/query/core/article-load.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index 2da62514..a45d1345 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -207,6 +207,7 @@ export const apiClient = { }, getMyShout: async (shout_id: number) => { + await apiClient.private const resp = await apiClient.private.query(getMyShout, { shout_id }).toPromise() if (resp.error) console.error(resp) diff --git a/src/graphql/query/core/article-load.ts b/src/graphql/query/core/article-load.ts index f6965dcb..96605467 100644 --- a/src/graphql/query/core/article-load.ts +++ b/src/graphql/query/core/article-load.ts @@ -1,8 +1,8 @@ import { gql } from '@urql/core' export default gql` - query LoadShoutQuery($slug: String, $shout_id: Int) { - get_shout(slug: $slug, shout_id: $shout_id) { + query LoadShoutQuery($slug: String!) { + get_shout(slug: $slug) { id title lead From 41e40ada9b63a18d05e25c6b849f2895389149e5 Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Thu, 7 Mar 2024 10:20:50 +0300 Subject: [PATCH 25/31] Comment delete message --- public/locales/en/translation.json | 3 ++- public/locales/ru/translation.json | 3 ++- src/components/Article/Comment/Comment.tsx | 13 +++++++++---- src/context/reactions.tsx | 16 ++++++++-------- src/graphql/client/core.ts | 3 +-- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 25a18e64..b021d2ce 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -525,5 +525,6 @@ "video": "video", "view": "view", "viewsWithCount": "{count} {count, plural, one {view} other {views}}", - "yesterday": "yesterday" + "yesterday": "yesterday", + "Failed to delete comment": "Failed to delete comment" } diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 5ad79f28..33643991 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -552,5 +552,6 @@ "video": "видео", "view": "просмотр", "viewsWithCount": "{count} {count, plural, one {просмотр} few {просмотрa} other {просмотров}}", - "yesterday": "вчера" + "yesterday": "вчера", + "Failed to delete comment": "Не удалось удалить комментарий" } diff --git a/src/components/Article/Comment/Comment.tsx b/src/components/Article/Comment/Comment.tsx index a0fee501..d66e1767 100644 --- a/src/components/Article/Comment/Comment.tsx +++ b/src/components/Article/Comment/Comment.tsx @@ -64,14 +64,19 @@ export const Comment = (props: Props) => { }) if (isConfirmed) { - await deleteReaction(props.comment.id) - // TODO: Учесть то что deleteReaction может вернуть error - if (props.onDelete) { + const { error } = await deleteReaction(props.comment.id) + const notificationType = error ? 'error' : 'success' + const notificationMessage = error + ? t('Failed to delete comment') + : t('Comment successfully deleted') + await showSnackbar({ type: notificationType, body: notificationMessage }) + + if (!error && props.onDelete) { props.onDelete(props.comment.id) } - await showSnackbar({ body: t('Comment successfully deleted') }) } } catch (error) { + await showSnackbar({ body: 'error' }) console.error('[deleteReaction]', error) } } diff --git a/src/context/reactions.tsx b/src/context/reactions.tsx index 6e0e6756..2adbe2ef 100644 --- a/src/context/reactions.tsx +++ b/src/context/reactions.tsx @@ -21,7 +21,7 @@ type ReactionsContextType = { }) => Promise createReaction: (reaction: ReactionInput) => Promise updateReaction: (reaction: ReactionInput) => Promise - deleteReaction: (id: number) => Promise + deleteReaction: (id: number) => Promise<{ error: string }> } const ReactionsContext = createContext() @@ -84,15 +84,15 @@ export const ReactionsProvider = (props: { children: JSX.Element }) => { setReactionEntities(changes) } - const deleteReaction = async (reaction_id: number): Promise => { + const deleteReaction = async (reaction_id: number): Promise<{ error: string; reaction?: string }> => { if (reaction_id) { - const { error } = await apiClient.destroyReaction(reaction_id) - if (error) { - await showSnackbar({ type: 'error', body: t(error) }) + const result = await apiClient.destroyReaction(reaction_id) + if (!result.error) { + setReactionEntities({ + [reaction_id]: undefined, + }) } - setReactionEntities({ - [reaction_id]: undefined, - }) + return result } } diff --git a/src/graphql/client/core.ts b/src/graphql/client/core.ts index a45d1345..4cbe81c2 100644 --- a/src/graphql/client/core.ts +++ b/src/graphql/client/core.ts @@ -135,7 +135,6 @@ export const apiClient = { user?: string }): Promise => { const response = await publicGraphQLClient.query(authorFollows, params).toPromise() - console.log('!!! response:', response) return response.data.get_author_follows }, @@ -188,7 +187,7 @@ export const apiClient = { destroyReaction: async (reaction_id: number) => { const response = await apiClient.private.mutation(reactionDestroy, { reaction_id }).toPromise() console.debug('[graphql.client.core] destroyReaction:', response) - return response.data.delete_reaction.reaction + return response.data.delete_reaction }, updateReaction: async (reaction: ReactionInput) => { const response = await apiClient.private.mutation(reactionUpdate, { reaction }).toPromise() From a59ee6260cffb8ed8277f76a243c1d440a261352 Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 7 Mar 2024 13:03:19 +0300 Subject: [PATCH 26/31] create-fx-fix --- src/pages/edit.page.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index 0feb07e1..8ed436a5 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -1,4 +1,4 @@ -import { Show, Suspense, createMemo, createSignal, lazy, onMount } from 'solid-js' +import { Show, Suspense, createEffect, createMemo, createSignal, lazy, on, onMount } from 'solid-js' import { AuthGuard } from '../components/AuthGuard' import { Loading } from '../components/_shared/Loading' @@ -24,16 +24,18 @@ export const EditPage = () => { const [shout, setShout] = createSignal(null) - onMount(async () => { - const { shout: loadedShout, error } = await apiClient.getMyShout(shoutId()) - console.log(loadedShout) - if (error) { - await snackbar?.showSnackbar({ type: 'error', body: t('This content is not published yet') }) - redirectPage(router, 'drafts') - } else { - setShout(loadedShout) - } - }) + createEffect( + on(shoutId, async (shout_id) => { + const { shout: loadedShout, error } = await apiClient.getMyShout(shout_id) + console.log(loadedShout) + if (error) { + await snackbar?.showSnackbar({ type: 'error', body: t('This content is not published yet') }) + redirectPage(router, 'drafts') + } else { + setShout(loadedShout) + } + }), + ) const title = createMemo(() => { if (!shout()) { From 0b905eb635c3b9da2ba5cf661260782a860bce0f Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 7 Mar 2024 13:14:22 +0300 Subject: [PATCH 27/31] merged-2 --- src/pages/edit.page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index 8ed436a5..bd2a8666 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -34,7 +34,7 @@ export const EditPage = () => { } else { setShout(loadedShout) } - }), + }, { defer: true }), ) const title = createMemo(() => { From db7825fab82647a71e24b790ecc5c8154d36432c Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 7 Mar 2024 13:58:12 +0300 Subject: [PATCH 28/31] onmount-fix --- src/pages/edit.page.tsx | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index bd2a8666..551e5254 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -1,4 +1,4 @@ -import { Show, Suspense, createEffect, createMemo, createSignal, lazy, on, onMount } from 'solid-js' +import { Show, Suspense, createMemo, createSignal, lazy, onMount } from 'solid-js' import { AuthGuard } from '../components/AuthGuard' import { Loading } from '../components/_shared/Loading' @@ -20,12 +20,9 @@ export const EditPage = () => { const snackbar = useSnackbar() const { t } = useLocalize() - const shoutId = createMemo(() => Number((page().params as Record<'shoutId', string>).shoutId)) - const [shout, setShout] = createSignal(null) - - createEffect( - on(shoutId, async (shout_id) => { + const loadMyShout = async (shout_id: number) => { + if (shout_id) { const { shout: loadedShout, error } = await apiClient.getMyShout(shout_id) console.log(loadedShout) if (error) { @@ -34,8 +31,19 @@ export const EditPage = () => { } else { setShout(loadedShout) } - }, { defer: true }), - ) + } + } + + onMount(async () => { + const shout_id = window.location.pathname.split('/').pop() + if (shout_id) { + try { + await loadMyShout(parseInt(shout_id, 10)) + } catch(e) { + console.error(e) + } + } + }) const title = createMemo(() => { if (!shout()) { From 2280a776b36fb2f8a7aaf1dee5d4627c1ec81d8f Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Thu, 7 Mar 2024 15:13:52 +0300 Subject: [PATCH 29/31] Improve draft saving process in EditView --- src/components/Views/EditView/EditView.tsx | 6 ++++-- src/context/editor.tsx | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/Views/EditView/EditView.tsx b/src/components/Views/EditView/EditView.tsx index 1969e338..3ef489ca 100644 --- a/src/components/Views/EditView/EditView.tsx +++ b/src/components/Views/EditView/EditView.tsx @@ -64,10 +64,11 @@ export const EditView = (props: Props) => { getDraftFromLocalStorage, } = useEditorContext() const shoutTopics = props.shout.topics || [] - const draft = getDraftFromLocalStorage(props.shout.id) + // TODO: проверить сохранение черновика в local storage (не работает) + const draft = getDraftFromLocalStorage(props.shout.id) if (draft) { - setForm(draft) + setForm(Object.keys(draft).length !== 0 ? draft : { shoutId: props.shout.id }); } else { setForm({ slug: props.shout.slug, @@ -179,6 +180,7 @@ export const EditView = (props: Props) => { let autoSaveTimeOutId: number | string | NodeJS.Timeout + //TODO: add throttle const autoSaveRecursive = () => { autoSaveTimeOutId = setTimeout(async () => { const hasChanges = !deepEqual(form, prevForm) diff --git a/src/context/editor.tsx b/src/context/editor.tsx index da9fe026..5369df88 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -184,8 +184,10 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } const saveDraft = async (draftForm: ShoutForm) => { + console.log("!!! draftForm:", draftForm); const { error } = await updateShout(draftForm, { publish: false }) if (error) { + console.log("!!! error:", error); snackbar?.showSnackbar({ type: 'error', body: localize?.t(error) || '' }) return } From 248d06decd41b8f1b81fe22028a95bc8db95b74b Mon Sep 17 00:00:00 2001 From: ilya-bkv Date: Thu, 7 Mar 2024 15:14:58 +0300 Subject: [PATCH 30/31] cleanup code --- src/components/Nav/AuthModal/RegisterForm.tsx | 1 - src/context/editor.tsx | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/components/Nav/AuthModal/RegisterForm.tsx b/src/components/Nav/AuthModal/RegisterForm.tsx index 48744474..56f272ac 100644 --- a/src/components/Nav/AuthModal/RegisterForm.tsx +++ b/src/components/Nav/AuthModal/RegisterForm.tsx @@ -48,7 +48,6 @@ export const RegisterForm = () => { } const handleSubmit = async (event: Event) => { - console.log('!!! handleSubmit:', handleSubmit) event.preventDefault() if (passwordError()) { setValidationErrors((errors) => ({ ...errors, password: passwordError() })) diff --git a/src/context/editor.tsx b/src/context/editor.tsx index 5369df88..da9fe026 100644 --- a/src/context/editor.tsx +++ b/src/context/editor.tsx @@ -184,10 +184,8 @@ export const EditorProvider = (props: { children: JSX.Element }) => { } const saveDraft = async (draftForm: ShoutForm) => { - console.log("!!! draftForm:", draftForm); const { error } = await updateShout(draftForm, { publish: false }) if (error) { - console.log("!!! error:", error); snackbar?.showSnackbar({ type: 'error', body: localize?.t(error) || '' }) return } From b31d0deed419b3a09d34521ee247a3b899520c90 Mon Sep 17 00:00:00 2001 From: Untone Date: Thu, 7 Mar 2024 15:31:09 +0300 Subject: [PATCH 31/31] merged --- .gitignore | 1 + src/components/Views/EditView/EditView.tsx | 2 +- src/pages/edit.page.tsx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 60d6161e..6dca0a65 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ bun.lockb /blob-report/ /playwright/.cache/ /plawright-report/ +target \ No newline at end of file diff --git a/src/components/Views/EditView/EditView.tsx b/src/components/Views/EditView/EditView.tsx index 3ef489ca..83da483d 100644 --- a/src/components/Views/EditView/EditView.tsx +++ b/src/components/Views/EditView/EditView.tsx @@ -68,7 +68,7 @@ export const EditView = (props: Props) => { // TODO: проверить сохранение черновика в local storage (не работает) const draft = getDraftFromLocalStorage(props.shout.id) if (draft) { - setForm(Object.keys(draft).length !== 0 ? draft : { shoutId: props.shout.id }); + setForm(Object.keys(draft).length !== 0 ? draft : { shoutId: props.shout.id }) } else { setForm({ slug: props.shout.slug, diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index 551e5254..ef33f712 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -39,7 +39,7 @@ export const EditPage = () => { if (shout_id) { try { await loadMyShout(parseInt(shout_id, 10)) - } catch(e) { + } catch (e) { console.error(e) } }