From 363eead61bb7f7ce8319bf7e81388aba0d1b2a90 Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 21:00:48 +0400 Subject: [PATCH 01/11] chore: add missed keys --- .../SelectDictionaryVariant/ui/SelectDictionaryList.tsx | 2 ++ src/popup/widgets/note/NoteList.tsx | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryList.tsx b/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryList.tsx index 04d61df..968a213 100644 --- a/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryList.tsx +++ b/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryList.tsx @@ -24,6 +24,7 @@ export const SelectDictionaryList = () => { {languages.map((language) => ( @@ -34,6 +35,7 @@ export const SelectDictionaryList = () => { {languages.map((language) => { return ( diff --git a/src/popup/widgets/note/NoteList.tsx b/src/popup/widgets/note/NoteList.tsx index b347a01..6bc77da 100644 --- a/src/popup/widgets/note/NoteList.tsx +++ b/src/popup/widgets/note/NoteList.tsx @@ -21,6 +21,8 @@ import { EditIcon } from '@popup/shared/ui/icons/EditIcon' import { TLanguageCode, languageStore } from '@shared/entities/language' import { INote, noteStore } from '@shared/entities/note' +import styles from './styles.module.scss' + export const NoteList = () => { const ankiPort = useStore($ankiPort) const languages = useStore(languageStore.$languages) @@ -33,7 +35,7 @@ export const NoteList = () => { const closeEditNoteModal = () => setEditNote(null) return ( - <> +
{!ankiPort && } {languages.length ? ( <> @@ -41,6 +43,7 @@ export const NoteList = () => { {languages.map((language) => ( @@ -51,6 +54,7 @@ export const NoteList = () => { {languages.map((language) => { return ( @@ -59,6 +63,7 @@ export const NoteList = () => { {notes[language.value].map((note) => { return ( @@ -106,6 +111,6 @@ export const NoteList = () => { /> ) : null} - +
) } From da3e193b3c9887760d28dabd93b2b044b3abd5a9 Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:40:46 +0400 Subject: [PATCH 02/11] feat: add reset errors store function --- src/shared/entities/error/model/store.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/shared/entities/error/model/store.ts b/src/shared/entities/error/model/store.ts index f62853f..8443da3 100644 --- a/src/shared/entities/error/model/store.ts +++ b/src/shared/entities/error/model/store.ts @@ -11,7 +11,9 @@ export const $errors = atom([]) onMount($errors, () => { task(async () => { const getResult = await ErrorStorage.get() - getResult.data ? $errors.set([]) : $errors.set([getResult.error]) + getResult.data + ? $errors.set(getResult.data) + : $errors.set([getResult.error]) }) const listener = ErrorStorage.onChanged.addListener((changes) => { @@ -34,3 +36,8 @@ export const addError = async (error: TBaseError) => { ? $errors.set(newErrors) : $errors.set([setResult.error, ...newErrors]) } + +export const reset = async () => { + const setResult = await ErrorStorage.set([]) + setResult.data ? $errors.set([]) : $errors.set([setResult.error]) +} From 272c8867fa5e30492bc541503186c3cb7fa3aa80 Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:41:04 +0400 Subject: [PATCH 03/11] test: remove errors store from dictionary --- .../entities/dictionary/model/__tests__/store.test.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/shared/entities/dictionary/model/__tests__/store.test.ts b/src/shared/entities/dictionary/model/__tests__/store.test.ts index 34bc4cb..99484ce 100644 --- a/src/shared/entities/dictionary/model/__tests__/store.test.ts +++ b/src/shared/entities/dictionary/model/__tests__/store.test.ts @@ -2,8 +2,6 @@ import { waitFor } from '@tests/testUtils' import { allTasks, cleanStores, keepMount } from 'nanostores' import { afterEach, describe, expect, test, vi } from 'vitest' -import { $errors } from '@shared/entities/error/model/store' - import { chromeMockClearListeners } from '@shared/shared/browser/__mocks__/chrome' import { Result } from '@shared/shared/libs/operationResult' @@ -21,7 +19,6 @@ describe('dictionary store', () => { await chrome.storage.local.clear() cleanStores($dictionaries) $dictionaries.set(DICTIONARIES) - $errors.set([]) chromeMockClearListeners() vi.clearAllMocks() }) @@ -38,19 +35,17 @@ describe('dictionary store', () => { await allTasks() expect($dictionaries.get()).toEqual(newDictionaries) - expect($errors.get().length).toEqual(0) }) test('should set empty array and set error when can not get data from DictionaryStorage', async () => { vi.spyOn(DictionaryStorage, 'get').mockResolvedValueOnce( - Result.Error(error), + Result.Error(error, false), ) keepMount($dictionaries) await allTasks() expect($dictionaries.get()).toEqual(DICTIONARIES) - expect($errors.get().length).toEqual(1) }) }) From cd81a9c3ce4e96892e2426edb826a6d7c79a3a6e Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:44:31 +0400 Subject: [PATCH 04/11] chore: add translations --- public/_locales/en/messages.json | 24 +++++++++++++++++++ .../ui/FillFlashcardFormNotAvailable.tsx | 6 ++++- .../FillFlashcardForm/ui/styles.module.scss | 6 +++++ src/popup/shared/ui/Modal/index.tsx | 2 +- src/popup/widgets/settings/ui/Settings.tsx | 5 ++-- src/shared/entities/note/model/store.ts | 6 ++--- 6 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/popup/features/note/FillFlashcardForm/ui/styles.module.scss diff --git a/public/_locales/en/messages.json b/public/_locales/en/messages.json index a17aa37..52a81a8 100644 --- a/public/_locales/en/messages.json +++ b/public/_locales/en/messages.json @@ -70,6 +70,9 @@ "ERROR_CAN_NOT_FIND_NOTE_TO_EDIT": { "message": "Can't find note" }, + "EDIT_NOTE_SUCCESS": { + "message": "Your changes was succesfully saved" + }, "DELETE_NOTE": { "message": "Delete note $noteText$", "placeholders": { @@ -79,6 +82,12 @@ } } }, + "DELETE_NOTE_SUCCESS": { + "message": "Note was successfully deleted" + }, + "ADD_NOTE_SUCCESS": { + "message": "Note was successfully added" + }, "ERROR_CAN_NOT_FIND_NOTE_TO_DELETE": { "message": "Can't find note" }, @@ -156,5 +165,20 @@ }, "TOAST_BUTTON_OPEN_DETAILS": { "message": "Open details" + }, + "ERROR_LIST_NO_ITEMS": { + "message": "No logs" + }, + "FACING_PROBLEMS": { + "message": "Facing problems? Send logs to us" + }, + "FACING_PROBLEMS_HELP": { + "message": "Ask for help" + }, + "SETTINGS_OPEN": { + "message": "Settings" + }, + "CLEAR": { + "message": "Clear" } } \ No newline at end of file diff --git a/src/popup/features/note/FillFlashcardForm/ui/FillFlashcardFormNotAvailable.tsx b/src/popup/features/note/FillFlashcardForm/ui/FillFlashcardFormNotAvailable.tsx index b2495f2..3858377 100644 --- a/src/popup/features/note/FillFlashcardForm/ui/FillFlashcardFormNotAvailable.tsx +++ b/src/popup/features/note/FillFlashcardForm/ui/FillFlashcardFormNotAvailable.tsx @@ -1,5 +1,9 @@ import { browser } from '@popup/shared/browser' +import styles from './styles.module.scss' + export const FillFlashcardFormNotAvailable = () => ( - {browser.i18n.getMessage('FILL_ANKI_FORM_NOT_AVAILABLE')} + + {browser.i18n.getMessage('FILL_ANKI_FORM_NOT_AVAILABLE')} + ) diff --git a/src/popup/features/note/FillFlashcardForm/ui/styles.module.scss b/src/popup/features/note/FillFlashcardForm/ui/styles.module.scss new file mode 100644 index 0000000..59c5ba6 --- /dev/null +++ b/src/popup/features/note/FillFlashcardForm/ui/styles.module.scss @@ -0,0 +1,6 @@ +.alert { + display: block; + padding: var(--spacing-1); + background-color: var(--color-neutral-100); + border-radius: var(--radius-1); +} diff --git a/src/popup/shared/ui/Modal/index.tsx b/src/popup/shared/ui/Modal/index.tsx index 66460c2..1c1f69c 100644 --- a/src/popup/shared/ui/Modal/index.tsx +++ b/src/popup/shared/ui/Modal/index.tsx @@ -35,7 +35,7 @@ export const Modal = ({ open, children, onClose }: Props) => { className={styles['modal__close-btn']} onClick={onClose} startIcon={} - capture={browser.i18n.getMessage('CLOSE')} + aria-label={browser.i18n.getMessage('CLOSE')} > {children} , diff --git a/src/popup/widgets/settings/ui/Settings.tsx b/src/popup/widgets/settings/ui/Settings.tsx index b9dff0b..86c2a18 100644 --- a/src/popup/widgets/settings/ui/Settings.tsx +++ b/src/popup/widgets/settings/ui/Settings.tsx @@ -5,6 +5,7 @@ import { SelectLanguages } from '@popup/features/language/SelectLanguages' import { ErrorList } from '@popup/entities/error' +import { browser } from '@popup/shared/browser' import { Button } from '@popup/shared/ui/Button' import { Modal } from '@popup/shared/ui/Modal' import { Tab, TabPanel, Tabs, TabsList, a11yProps } from '@popup/shared/ui/Tabs' @@ -18,12 +19,12 @@ export const Settings = () => { return ( <> - )} - - - + + setShowDetails(false)}> + + + + )} + + ) +} diff --git a/src/popup/shared/ui/Alert/styles.module.scss b/src/popup/shared/ui/Alert/styles.module.scss new file mode 100644 index 0000000..5c874c5 --- /dev/null +++ b/src/popup/shared/ui/Alert/styles.module.scss @@ -0,0 +1,33 @@ +.alert { + display: flex; + flex-direction: column; + gap: var(--spacing-1); + padding: var(--spacing-2); + color: var(--text); + background-color: var(--background); + border-radius: var(--radius-1); + + &__title { + color: var(--title); + } + + &--variant { + &-success { + --title: var(--color-success-900); + --text: var(--color-success-700); + --background: var(--color-success-100); + } + + &-error { + --title: var(--color-error-900); + --text: var(--color-error-700); + --background: var(--color-error-100); + } + + &-info { + --title: var(--color-info-900); + --text: var(--color-info-700); + --background: var(--color-info-100); + } + } +} diff --git a/src/popup/shared/ui/Alert/types.ts b/src/popup/shared/ui/Alert/types.ts new file mode 100644 index 0000000..18724e1 --- /dev/null +++ b/src/popup/shared/ui/Alert/types.ts @@ -0,0 +1,9 @@ +import { ComponentChildren } from 'preact' + +export type TAlertType = 'error' | 'info' | 'success' +export interface IAlert { + title: string + message?: ComponentChildren + details?: Error | null + type: TAlertType +} From 95be8097faacb3819b58912fc88e74ff0b68f2f6 Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:48:11 +0400 Subject: [PATCH 07/11] chore: add result component --- src/popup/shared/ui/Result/index.tsx | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/popup/shared/ui/Result/index.tsx diff --git a/src/popup/shared/ui/Result/index.tsx b/src/popup/shared/ui/Result/index.tsx new file mode 100644 index 0000000..54f3332 --- /dev/null +++ b/src/popup/shared/ui/Result/index.tsx @@ -0,0 +1,28 @@ +import { TResult } from '@shared/shared/libs/operationResult' + +import { Alert } from '../Alert' + +export const Result = ({ result }: { result: TResult | null }) => { + if (!result) return null + return ( + <> + {result.data && ( + + )} + {result.error && ( + + )} + + ) +} From 7f4d65150f47d457195c49f089e5e93381c3eacf Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:49:13 +0400 Subject: [PATCH 08/11] chore: add error alert component --- .../entities/error/ui/ErrorAlert/index.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/popup/entities/error/ui/ErrorAlert/index.tsx diff --git a/src/popup/entities/error/ui/ErrorAlert/index.tsx b/src/popup/entities/error/ui/ErrorAlert/index.tsx new file mode 100644 index 0000000..6662990 --- /dev/null +++ b/src/popup/entities/error/ui/ErrorAlert/index.tsx @@ -0,0 +1,20 @@ +import { useStore } from '@nanostores/preact' + +import { browser } from '@popup/shared/browser' + +import { $errors } from '@shared/entities/error' + +export const ErrorAlert = () => { + const errors = useStore($errors) + + if (!errors.length) return null + + return ( + + {browser.i18n.getMessage('FACING_PROBLEMS')}
+ + {browser.i18n.getMessage('FACING_PROBLEMS_HELP')} + +
+ ) +} From 48d42bc0c6f88f924135497649296f6c790b96fe Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:49:45 +0400 Subject: [PATCH 09/11] chore: refine error list component --- .../entities/error/ui/ErrorCard/index.tsx | 13 ------- .../entities/error/ui/ErrorList/index.tsx | 34 ++++++++++++++----- .../error/ui/ErrorList/styles.module.scss | 11 ++++++ src/popup/entities/error/ui/index.ts | 1 + 4 files changed, 38 insertions(+), 21 deletions(-) delete mode 100644 src/popup/entities/error/ui/ErrorCard/index.tsx create mode 100644 src/popup/entities/error/ui/ErrorList/styles.module.scss diff --git a/src/popup/entities/error/ui/ErrorCard/index.tsx b/src/popup/entities/error/ui/ErrorCard/index.tsx deleted file mode 100644 index 50cde95..0000000 --- a/src/popup/entities/error/ui/ErrorCard/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { TBaseError } from '@shared/shared/libs/operationResult' - -interface Props { - error: TBaseError -} - -export const ErrorCard = ({ error }: Props) => { - return ( -
- {error.type} {error.error} -
- ) -} diff --git a/src/popup/entities/error/ui/ErrorList/index.tsx b/src/popup/entities/error/ui/ErrorList/index.tsx index fefbed7..59c84f7 100644 --- a/src/popup/entities/error/ui/ErrorList/index.tsx +++ b/src/popup/entities/error/ui/ErrorList/index.tsx @@ -1,19 +1,37 @@ import { useStore } from '@nanostores/preact' -import { $errors } from '@shared/entities/error' +import { browser } from '@popup/shared/browser' +import { Button } from '@popup/shared/ui/Button' -import { ErrorCard } from '../ErrorCard' +import { $errors, reset } from '@shared/entities/error' + +import styles from './styles.module.scss' export const ErrorList = () => { const errors = useStore($errors) + if (!errors.length) + return {browser.i18n.getMessage('ERROR_LIST_NO_ITEMS')} + return ( -
    -
  • - {errors.map((error) => ( - + <> + +
      + {errors.map((error, index) => ( +
    • + {error.type} + {error.error?.name} + {error.error?.message} + {error.error?.stack} +
    • ))} - -
    +
+ ) } diff --git a/src/popup/entities/error/ui/ErrorList/styles.module.scss b/src/popup/entities/error/ui/ErrorList/styles.module.scss new file mode 100644 index 0000000..d6d8e36 --- /dev/null +++ b/src/popup/entities/error/ui/ErrorList/styles.module.scss @@ -0,0 +1,11 @@ +.errors { + display: flex; + flex-direction: column; + gap: var(--spacing-2); + overflow-wrap: break-word; +} + +.clear-button { + margin-inline: auto 0; + margin-bottom: var(--spacing-2); +} diff --git a/src/popup/entities/error/ui/index.ts b/src/popup/entities/error/ui/index.ts index 0acb133..b788225 100644 --- a/src/popup/entities/error/ui/index.ts +++ b/src/popup/entities/error/ui/index.ts @@ -1 +1,2 @@ export { ErrorList } from './ErrorList' +export { ErrorAlert } from './ErrorAlert' From b4d0cdaef116f0522ce1a766115c99862f532d7a Mon Sep 17 00:00:00 2001 From: Alina Date: Sat, 13 Apr 2024 23:50:33 +0400 Subject: [PATCH 10/11] chore: remove toast usage --- src/__tests__/setupTests.ts | 9 -------- src/popup/app/Popup.tsx | 4 ++-- src/popup/entities/tab/index.ts | 7 +----- .../ui/SelectDictionaryVariant.tsx | 11 ++-------- .../SelectLanguages/ui/SelectLanguages.tsx | 18 ++++++++------- .../features/note/DeleteNote/ui/index.tsx | 6 ++--- src/popup/features/note/EditNote/ui/index.tsx | 22 +++++++++---------- src/popup/widgets/note/NoteList.tsx | 1 - 8 files changed, 28 insertions(+), 50 deletions(-) diff --git a/src/__tests__/setupTests.ts b/src/__tests__/setupTests.ts index 2215572..7cb7941 100644 --- a/src/__tests__/setupTests.ts +++ b/src/__tests__/setupTests.ts @@ -1,12 +1,3 @@ -import { vi } from 'vitest' - -import * as toastModule from '@popup/shared/ui/Toast' -import { getErrorToastMock } from '@popup/shared/ui/Toast/helpers/__mock__/getErrorToast' -import { addToastMock } from '@popup/shared/ui/Toast/model/__mock__/store' - import { chromeMock } from '@shared/shared/browser/__mocks__/chrome' global.chrome = chromeMock - -vi.spyOn(toastModule, 'getErrorToast').mockImplementation(getErrorToastMock) -vi.spyOn(toastModule, 'addToast').mockImplementation(addToastMock) diff --git a/src/popup/app/Popup.tsx b/src/popup/app/Popup.tsx index 66caaa0..c9c79cc 100644 --- a/src/popup/app/Popup.tsx +++ b/src/popup/app/Popup.tsx @@ -1,14 +1,14 @@ import { NoteList } from '@popup/widgets/note/NoteList' import { Settings } from '@popup/widgets/settings' -import { Toasts } from '@popup/shared/ui/Toast' +import { ErrorAlert } from '@popup/entities/error' export const Popup = () => { return (
+ -
) } diff --git a/src/popup/entities/tab/index.ts b/src/popup/entities/tab/index.ts index c7073cb..debb5fb 100644 --- a/src/popup/entities/tab/index.ts +++ b/src/popup/entities/tab/index.ts @@ -1,7 +1,6 @@ import { atom, onMount, task } from 'nanostores' import { browser } from '@popup/shared/browser' -import { addToast, getErrorToast } from '@popup/shared/ui/Toast' import { TTab } from '@shared/shared/browser/tabs' @@ -11,10 +10,6 @@ onMount($activeTab, () => { task(async () => { const getResult = await browser.tabs.getActiveTab() - if (getResult.data) { - $activeTab.set(getResult.data) - } else { - addToast(getErrorToast(getResult.error)) - } + getResult.data && $activeTab.set(getResult.data) }) }) diff --git a/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryVariant.tsx b/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryVariant.tsx index b85dc8e..08cecdb 100644 --- a/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryVariant.tsx +++ b/src/popup/features/dictionary/SelectDictionaryVariant/ui/SelectDictionaryVariant.tsx @@ -2,7 +2,6 @@ import { DictionaryCard } from '@popup/entities/dictionary' import { browser } from '@popup/shared/browser' import { Button } from '@popup/shared/ui/Button' -import { addToast } from '@popup/shared/ui/Toast' import { IDictionaryWithVariants, @@ -18,14 +17,8 @@ interface GroupProps { } export const SelectDictionaryVariant = ({ dictionary, lang }: GroupProps) => { - const onSelectVariant = async (variant: string) => { - const result = await dictionaryStore.selectVariant( - lang, - dictionary.id, - variant, - ) - - result.error && addToast({ title: result.error.type, type: 'error' }) + const onSelectVariant = (variant: string) => { + dictionaryStore.selectVariant(lang, dictionary.id, variant) } return ( diff --git a/src/popup/features/language/SelectLanguages/ui/SelectLanguages.tsx b/src/popup/features/language/SelectLanguages/ui/SelectLanguages.tsx index 6d4b80f..32766e6 100644 --- a/src/popup/features/language/SelectLanguages/ui/SelectLanguages.tsx +++ b/src/popup/features/language/SelectLanguages/ui/SelectLanguages.tsx @@ -1,12 +1,15 @@ import { useStore } from '@nanostores/preact' import { JSXInternal } from 'node_modules/preact/src/jsx' +import { useState } from 'preact/hooks' import { browser } from '@popup/shared/browser' import { Button } from '@popup/shared/ui/Button' -import { addToast, getErrorToast } from '@popup/shared/ui/Toast' +import { Result } from '@popup/shared/ui/Result' import { ILanguage } from '@shared/entities/language' +import { TResult } from '@shared/shared/libs/operationResult' + import { checkIsSelected, localStore, @@ -20,6 +23,7 @@ interface Props { } export const SelectLanguages = ({ languages }: Props) => { + const [result, setResult] = useState(null) useStore(localStore.languageCodes) const onSubmit: JSXInternal.SubmitEventHandler = async ( @@ -27,21 +31,17 @@ export const SelectLanguages = ({ languages }: Props) => { ) => { e.preventDefault() const result = await syncLocalStoreWithLanguageStore() - result.data && - addToast({ - type: 'success', - title: result.data, - }) - result.error && addToast(getErrorToast(result.error)) + setResult(result) } return (
-

+

{browser.i18n.getMessage('SELECT_LANGUAGES_FORM_TITLE')}

@@ -63,6 +63,8 @@ export const SelectLanguages = ({ languages }: Props) => { ))} + +