From 4a55271a79d4935e6e0d94c08900cb53927cdb2e Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 00:48:58 +0300 Subject: [PATCH 1/8] edit-hotfix --- src/pages/edit.page.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/pages/edit.page.tsx b/src/pages/edit.page.tsx index f729e50b..aaa08eee 100644 --- a/src/pages/edit.page.tsx +++ b/src/pages/edit.page.tsx @@ -48,14 +48,18 @@ export const EditPage = () => { createEffect( on( - page, + () => page(), (p) => { - const shoutId = p?.path.split('/').pop() - const shoutIdFromUrl = Number.parseInt(shoutId ?? '0', 10) - console.debug(`editing shout ${shoutIdFromUrl}`) - if (shoutIdFromUrl) setShoutId(shoutIdFromUrl) + if (p?.path) { + console.debug(p?.path) + const shoutId = p?.path.split('/').pop() + const shoutIdFromUrl = Number.parseInt(shoutId ?? '0', 10) + console.debug(`editing shout ${shoutIdFromUrl}`) + if (shoutIdFromUrl) { + setShoutId(shoutIdFromUrl) + } + } }, - { defer: true }, ), ) @@ -70,6 +74,7 @@ export const EditPage = () => { } } }), + { defer: true }, ) const title = createMemo(() => { From 135e0d215f922e262061864a41498b1fbae6f940 Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 00:55:30 +0300 Subject: [PATCH 2/8] error-catch --- src/components/Nav/AuthModal/LoginForm.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Nav/AuthModal/LoginForm.tsx b/src/components/Nav/AuthModal/LoginForm.tsx index 1a50aeda..25867cec 100644 --- a/src/components/Nav/AuthModal/LoginForm.tsx +++ b/src/components/Nav/AuthModal/LoginForm.tsx @@ -99,8 +99,7 @@ export const LoginForm = () => { console.debug('[signIn] errors:', errors) if ( errors.some( - (error) => - error.message.includes('bad user credentials') || error.message.includes('user not found'), + (error) => error.message.includes('bad user credentials') || error.message.includes('user not'), ) ) { setValidationErrors((prev) => ({ From 22f0c9052dfb0876b92c6d055283c74f933da095 Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 01:04:18 +0300 Subject: [PATCH 3/8] auth-errors-fix --- public/locales/en/translation.json | 3 ++- public/locales/ru/translation.json | 3 ++- src/components/Nav/AuthModal/LoginForm.tsx | 10 +++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index dea79bdb..72071723 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -417,6 +417,7 @@ "Username": "Username", "Userpic": "Userpic", "Users": "Users", + "User was not found": "User was not found", "Video format not supported": "Video format not supported", "Video": "Video", "Views": "Views", @@ -540,4 +541,4 @@ "Incorrect old password": "Incorrect old password", "Repeat new password": "Repeat new password", "Incorrect new password confirm": "Incorrect new password confirm" -} +} \ No newline at end of file diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index f9596f64..84006a9b 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -549,6 +549,7 @@ "topicKeywords": "{topic}, Discours.io, статьи, журналистика, исследования", "topics": "темы", "user already exist": "пользователь уже существует", + "User was not found": "Пользователь не найден", "verified": "уже подтверждён", "video": "видео", "view": "просмотр", @@ -567,4 +568,4 @@ "Incorrect old password": "Старый пароль не верен", "Repeat new password": "Повторите новый пароль", "Incorrect new password confirm": "Неверное подтверждение нового пароля" -} +} \ No newline at end of file diff --git a/src/components/Nav/AuthModal/LoginForm.tsx b/src/components/Nav/AuthModal/LoginForm.tsx index 25867cec..b33dabdc 100644 --- a/src/components/Nav/AuthModal/LoginForm.tsx +++ b/src/components/Nav/AuthModal/LoginForm.tsx @@ -96,18 +96,14 @@ export const LoginForm = () => { try { const { errors } = await signIn({ email: email(), password: password() }) if (errors?.length > 0) { - console.debug('[signIn] errors:', errors) - if ( - errors.some( - (error) => error.message.includes('bad user credentials') || error.message.includes('user not'), - ) - ) { + console.error('[signIn errors]', errors) + if (errors.some((error) => error.message.includes('user has not signed up email & password'))) { setValidationErrors((prev) => ({ ...prev, password: t('Something went wrong, check email and password'), })) } else if (errors.some((error) => error.message.includes('user not found'))) { - setSubmitError('Пользователь не найден') + setSubmitError(t('User was not found')) } else if (errors.some((error) => error.message.includes('email not verified'))) { setSubmitError(
From 59eaf3837da216a1b8ac7d13e00b0c80c4f6b2b1 Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 01:14:28 +0300 Subject: [PATCH 4/8] handle-auth-errors --- src/components/Nav/AuthModal/LoginForm.tsx | 29 ++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/components/Nav/AuthModal/LoginForm.tsx b/src/components/Nav/AuthModal/LoginForm.tsx index b33dabdc..dc5ffe54 100644 --- a/src/components/Nav/AuthModal/LoginForm.tsx +++ b/src/components/Nav/AuthModal/LoginForm.tsx @@ -96,27 +96,30 @@ export const LoginForm = () => { try { const { errors } = await signIn({ email: email(), password: password() }) if (errors?.length > 0) { - console.error('[signIn errors]', errors) - if (errors.some((error) => error.message.includes('user has not signed up email & password'))) { - setValidationErrors((prev) => ({ - ...prev, - password: t('Something went wrong, check email and password'), - })) - } else if (errors.some((error) => error.message.includes('user not found'))) { - setSubmitError(t('User was not found')) - } else if (errors.some((error) => error.message.includes('email not verified'))) { + console.warn('[signIn] errors: ', errors) + let msg = '' + if (errors.some((error) => error.message === 'user has not signed up email & password')) { + const password = t('Something went wrong, check email and password') + setValidationErrors((prev) => ({ ...prev, password })) + } else if (errors.some((error) => error.message === 'user not found')) { + msg = t('User was not found') + } else if (errors.some((error) => error.message === 'email not verified')) { + msg = t('This email is not verified') + } else { + msg = t('Error', errors[0].message) + } + + msg && setSubmitError(
- {t('This email is not verified')} + {msg} {'. '} {t('Send link again')}
, ) - } else { - setSubmitError(t('Error', errors[0].message)) - } + return } hideModal() From 38899ad8cb3aec26da62899a18f4c7402419b5a1 Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 01:18:55 +0300 Subject: [PATCH 5/8] login-validations-fixes --- src/components/Nav/AuthModal/LoginForm.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/Nav/AuthModal/LoginForm.tsx b/src/components/Nav/AuthModal/LoginForm.tsx index dc5ffe54..dc57565b 100644 --- a/src/components/Nav/AuthModal/LoginForm.tsx +++ b/src/components/Nav/AuthModal/LoginForm.tsx @@ -97,28 +97,27 @@ export const LoginForm = () => { const { errors } = await signIn({ email: email(), password: password() }) if (errors?.length > 0) { console.warn('[signIn] errors: ', errors) - let msg = '' + if (errors.some((error) => error.message === 'user has not signed up email & password')) { const password = t('Something went wrong, check email and password') setValidationErrors((prev) => ({ ...prev, password })) } else if (errors.some((error) => error.message === 'user not found')) { - msg = t('User was not found') + const email = t('User was not found') + setValidationErrors((prev) => ({ ...prev, email })) } else if (errors.some((error) => error.message === 'email not verified')) { - msg = t('This email is not verified') + const email = t('This email is not verified') + setValidationErrors((prev) => ({ ...prev, email })) } else { - msg = t('Error', errors[0].message) - } - - msg && setSubmitError(
- {msg} + {t('Error', errors[0].message)} {'. '} {t('Send link again')}
, ) + } return } From 319136474e710117771e6e69e0ae1a5546a02b1b Mon Sep 17 00:00:00 2001 From: kvakazyambra Date: Sun, 19 May 2024 01:38:56 +0300 Subject: [PATCH 6/8] Table of contents minor fixes --- public/locales/en/translation.json | 4 ++-- public/locales/ru/translation.json | 4 ++-- src/components/TableOfContents/TableOfContents.module.scss | 2 +- src/components/TableOfContents/TableOfContents.tsx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 72071723..29fed7a8 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -91,6 +91,7 @@ "Community Principles": "Community Principles", "Community values and rules of engagement for the open editorial team": "Community values and rules of engagement for the open editorial team", "Confirm": "Confirm", + "Contents": "Contents", "Contribute to free samizdat. Support Discours - an independent non-profit publication that works only for you. Become a pillar of the open newsroom": "Contribute to free samizdat. Support Discours - an independent non-profit publication that works only for you. Become a pillar of the open newsroom", "Cooperate": "Cooperate", "Copy link": "Copy link", @@ -470,7 +471,6 @@ "cancel": "cancel", "collections": "collections", "community": "community", - "contents": "contents", "delimiter": "delimiter", "discussion": "Discours", "dogma keywords": "Discours.io, dogma, editorial principles, code of ethics, journalism, community", @@ -541,4 +541,4 @@ "Incorrect old password": "Incorrect old password", "Repeat new password": "Repeat new password", "Incorrect new password confirm": "Incorrect new password confirm" -} \ No newline at end of file +} diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 84006a9b..91134e24 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -95,6 +95,7 @@ "Community Principles": "Принципы сообщества", "Community values and rules of engagement for the open editorial team": "Ценности сообщества и правила взаимодействия открытой редакции", "Confirm": "Подтвердить", + "Contents": "Оглавление", "Contribute to free samizdat. Support Discours - an independent non-profit publication that works only for you. Become a pillar of the open newsroom": "Внесите вклад в свободный самиздат. Поддержите Дискурс — независимое некоммерческое издание, которое работает только для вас. Станьте опорой открытой редакции", "Cooperate": "Соучаствовать", "Copy link": "Скопировать ссылку", @@ -492,7 +493,6 @@ "cancel": "отменить", "collections": "коллекции", "community": "сообщество", - "contents": "оглавление", "create_chat": "Создать чат", "create_group": "Создать группу", "delimiter": "разделитель", @@ -568,4 +568,4 @@ "Incorrect old password": "Старый пароль не верен", "Repeat new password": "Повторите новый пароль", "Incorrect new password confirm": "Неверное подтверждение нового пароля" -} \ No newline at end of file +} diff --git a/src/components/TableOfContents/TableOfContents.module.scss b/src/components/TableOfContents/TableOfContents.module.scss index 2e5fe4ac..8433e44d 100644 --- a/src/components/TableOfContents/TableOfContents.module.scss +++ b/src/components/TableOfContents/TableOfContents.module.scss @@ -157,7 +157,7 @@ color: #000; font-size: 14px; font-style: normal; - font-weight: 400; + font-weight: 500; line-height: 1.8rem; text-align: left; vertical-align: bottom; diff --git a/src/components/TableOfContents/TableOfContents.tsx b/src/components/TableOfContents/TableOfContents.tsx index 322aa925..d0a2de05 100644 --- a/src/components/TableOfContents/TableOfContents.tsx +++ b/src/components/TableOfContents/TableOfContents.tsx @@ -86,7 +86,7 @@ export const TableOfContents = (props: Props) => {
-

{t('contents')}

+

{t('Contents')}

    From 8f330ab914a835409b4f2a695aade286229fefee Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 01:41:50 +0300 Subject: [PATCH 7/8] multierror --- src/components/Nav/AuthModal/LoginForm.tsx | 51 ++++++++++++---------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/components/Nav/AuthModal/LoginForm.tsx b/src/components/Nav/AuthModal/LoginForm.tsx index dc57565b..925c8864 100644 --- a/src/components/Nav/AuthModal/LoginForm.tsx +++ b/src/components/Nav/AuthModal/LoginForm.tsx @@ -97,28 +97,35 @@ export const LoginForm = () => { const { errors } = await signIn({ email: email(), password: password() }) if (errors?.length > 0) { console.warn('[signIn] errors: ', errors) - - if (errors.some((error) => error.message === 'user has not signed up email & password')) { - const password = t('Something went wrong, check email and password') - setValidationErrors((prev) => ({ ...prev, password })) - } else if (errors.some((error) => error.message === 'user not found')) { - const email = t('User was not found') - setValidationErrors((prev) => ({ ...prev, email })) - } else if (errors.some((error) => error.message === 'email not verified')) { - const email = t('This email is not verified') - setValidationErrors((prev) => ({ ...prev, email })) - } else { - setSubmitError( -
    - {t('Error', errors[0].message)} - {'. '} - - {t('Send link again')} - -
    , - ) - } - + errors.forEach((error) => { + switch (error.message) { + case 'user has not signed up email & password': { + setValidationErrors((prev) => ({ + ...prev, + password: t('Something went wrong, check email and password'), + })) + break + } + case 'user not found': { + setValidationErrors((prev) => ({ ...prev, email: t('User was not found') })) + break + } + case 'email not verified': { + setValidationErrors((prev) => ({ ...prev, email: t('This email is not verified') })) + break + } + default: + setSubmitError( +
    + {t('Error', errors[0].message)} + {'. '} + + {t('Send link again')} + +
    , + ) + } + }) return } hideModal() From 9b76a52430980d3e5424655d2b7f07c6618a8bcf Mon Sep 17 00:00:00 2001 From: Untone Date: Sun, 19 May 2024 02:22:19 +0300 Subject: [PATCH 8/8] editor-autosave-fix --- src/components/Views/EditView/EditView.tsx | 63 +++++++++++----------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/components/Views/EditView/EditView.tsx b/src/components/Views/EditView/EditView.tsx index 1e8650b1..2148a3e4 100644 --- a/src/components/Views/EditView/EditView.tsx +++ b/src/components/Views/EditView/EditView.tsx @@ -2,7 +2,7 @@ import { clsx } from 'clsx' import deepEqual from 'fast-deep-equal' import { Accessor, Show, createMemo, createSignal, lazy, onCleanup, onMount } from 'solid-js' import { createStore } from 'solid-js/store' -import { throttle } from 'throttle-debounce' +import { debounce } from 'throttle-debounce' import { ShoutForm, useEditorContext } from '../../../context/editor' import { useLocalize } from '../../../context/localize' @@ -42,9 +42,8 @@ export const EMPTY_TOPIC: Topic = { slug: '', } -const THROTTLING_INTERVAL = 2000 -const AUTO_SAVE_INTERVAL = 5000 -const AUTO_SAVE_DELAY = 5000 +const AUTO_SAVE_DELAY = 3000 + const handleScrollTopButtonClick = (e) => { e.preventDefault() window.scrollTo({ @@ -104,6 +103,8 @@ export const EditView = (props: Props) => { return JSON.parse(form.media || '[]') }) + const [hasChanges, setHasChanges] = createSignal(false) + onMount(() => { const handleScroll = () => { setIsScrolled(window.scrollY > 0) @@ -113,7 +114,7 @@ export const EditView = (props: Props) => { onCleanup(() => { window.removeEventListener('scroll', handleScroll) }) - // eslint-disable-next-line unicorn/consistent-function-scoping + const handleBeforeUnload = (event) => { if (!deepEqual(prevForm, form)) { event.returnValue = t( @@ -127,8 +128,8 @@ export const EditView = (props: Props) => { }) const handleTitleInputChange = (value: string) => { - setForm('title', value) - setForm('slug', slugify(value)) + handleInputChange('title', value) + handleInputChange('slug', slugify(value)) if (value) { setFormErrors('title', '') } @@ -136,21 +137,21 @@ export const EditView = (props: Props) => { const handleAddMedia = (data) => { const newMedia = [...mediaItems(), ...data] - setForm('media', JSON.stringify(newMedia)) + handleInputChange('media', JSON.stringify(newMedia)) } const handleSortedMedia = (data) => { - setForm('media', JSON.stringify(data)) + handleInputChange('media', JSON.stringify(data)) } const handleMediaDelete = (index) => { const copy = [...mediaItems()] copy.splice(index, 1) - setForm('media', JSON.stringify(copy)) + handleInputChange('media', JSON.stringify(copy)) } const handleMediaChange = (index, value) => { const updated = mediaItems().map((item, idx) => (idx === index ? value : item)) - setForm('media', JSON.stringify(updated)) + handleInputChange('media', JSON.stringify(updated)) } const [baseAudioFields, setBaseAudioFields] = createSignal({ @@ -162,7 +163,7 @@ export const EditView = (props: Props) => { const handleBaseFieldsChange = (key, value) => { if (mediaItems().length > 0) { const updated = mediaItems().map((media) => ({ ...media, [key]: value })) - setForm('media', JSON.stringify(updated)) + handleInputChange('media', JSON.stringify(updated)) } else { setBaseAudioFields({ ...baseAudioFields(), [key]: value }) } @@ -182,34 +183,32 @@ export const EditView = (props: Props) => { } } - let autoSaveTimeOutId: number | string | NodeJS.Timeout - const autoSave = async () => { - const hasChanges = !deepEqual(form, prevForm) - const hasTopic = Boolean(form.mainTopic) - if (hasChanges || hasTopic) { + console.log('autoSave called') + if (hasChanges()) { console.debug('saving draft', form) setSaving(true) saveDraftToLocalStorage(form) await saveDraft(form) setPrevForm(clone(form)) - setTimeout(() => setSaving(false), AUTO_SAVE_DELAY) + setSaving(false) + setHasChanges(false) } } - // Throttle the autoSave function - const throttledAutoSave = throttle(THROTTLING_INTERVAL, autoSave) + const debouncedAutoSave = debounce(AUTO_SAVE_DELAY, autoSave) - const autoSaveRecursive = () => { - autoSaveTimeOutId = setTimeout(() => { - throttledAutoSave() - autoSaveRecursive() - }, AUTO_SAVE_INTERVAL) + const handleInputChange = (key, value) => { + console.log(`[handleInputChange] ${key}: ${value}`) + setForm(key, value) + setHasChanges(true) + debouncedAutoSave() } onMount(() => { - autoSaveRecursive() - onCleanup(() => clearTimeout(autoSaveTimeOutId)) + onCleanup(() => { + debouncedAutoSave.cancel() + }) }) const showSubtitleInput = () => { @@ -310,7 +309,7 @@ export const EditView = (props: Props) => { subtitleInput.current = el }} allowEnterKey={false} - value={(value) => setForm('subtitle', value || '')} + value={(value) => handleInputChange('subtitle', value || '')} class={styles.subtitleInput} placeholder={t('Subheader')} initialValue={form.subtitle || ''} @@ -324,7 +323,7 @@ export const EditView = (props: Props) => { smallHeight={true} placeholder={t('A short introduction to keep the reader interested')} initialContent={form.lead} - onChange={(value) => setForm('lead', value)} + onChange={(value) => handleInputChange('lead', value)} /> @@ -345,7 +344,7 @@ export const EditView = (props: Props) => { } isMultiply={false} fileType={'image'} - onUpload={(val) => setForm('coverImageUrl', val[0].url)} + onUpload={(val) => handleInputChange('coverImageUrl', val[0].url)} /> } > @@ -362,7 +361,7 @@ export const EditView = (props: Props) => {
    setForm('coverImageUrl', null)} + onClick={() => handleInputChange('coverImageUrl', null)} >
    @@ -408,7 +407,7 @@ export const EditView = (props: Props) => { setForm('body', body)} + onChange={(body) => handleInputChange('body', body)} />