diff --git a/web/.prettierrc b/web/.prettierrc index e72916e077..2de8b82540 100644 --- a/web/.prettierrc +++ b/web/.prettierrc @@ -3,7 +3,16 @@ "trailingComma": "none", "singleQuote": true, "printWidth": 80, - "importOrder": ["^[./]"], + "importOrder": [ + "^components", + "^context", + "^hooks", + "^lib", + "^pages", + "^services", + "^utils", + "^[./]" + ], "importOrderSeparation": true, "importOrderSortSpecifiers": true, "plugins": [ diff --git a/web/jest.config.ts b/web/jest.config.ts index 87458e8874..f6980134c5 100644 --- a/web/jest.config.ts +++ b/web/jest.config.ts @@ -1,4 +1,5 @@ export default { preset: 'ts-jest', - testEnvironment: 'jsdom' + testEnvironment: 'jsdom', + moduleDirectories: ['node_modules', 'src'] } diff --git a/web/src/components/Sidebar.tsx b/web/src/components/Sidebar.tsx index a6fbbfdcdc..e9d41c2fdc 100644 --- a/web/src/components/Sidebar.tsx +++ b/web/src/components/Sidebar.tsx @@ -6,8 +6,9 @@ import { import { ReactElement, useEffect, useState } from 'react' import { NavLink } from 'react-router-dom' -import { getInfo } from '../services/info' -import { browserVersion } from '../utils/info' +import { getInfo } from 'services/info' + +import { browserVersion } from 'utils/info' export default function Sidebar() { const navItems: [string, string, ReactElement][] = [ diff --git a/web/src/components/emails/DraftEmailsTabs.tsx b/web/src/components/emails/DraftEmailsTabs.tsx index 4e3d42a9b0..05237f8eea 100644 --- a/web/src/components/emails/DraftEmailsTabs.tsx +++ b/web/src/components/emails/DraftEmailsTabs.tsx @@ -1,6 +1,6 @@ import { useContext } from 'react' -import { DraftEmailsContext } from '../../contexts/DraftEmailContext' +import { DraftEmailsContext } from 'contexts/DraftEmailContext' export default function DraftEmailsTabs() { const draftEmailsContext = useContext(DraftEmailsContext) diff --git a/web/src/components/emails/EmailDraft.tsx b/web/src/components/emails/EmailDraft.tsx index e1c30bb8b0..858375720b 100644 --- a/web/src/components/emails/EmailDraft.tsx +++ b/web/src/components/emails/EmailDraft.tsx @@ -4,10 +4,11 @@ */ import { MinusIcon, XMarkIcon } from '@heroicons/react/20/solid' -import { DraftEmail } from '../../contexts/DraftEmailContext' -import EmailAddressInput from '../inputs/EmailAddressInput' -import RichTextEditor from '../inputs/RichTextEditor' -import TextInput from '../inputs/TextInput' +import EmailAddressInput from 'components/inputs/EmailAddressInput' +import RichTextEditor from 'components/inputs/RichTextEditor' +import TextInput from 'components/inputs/TextInput' + +import { DraftEmail } from 'contexts/DraftEmailContext' interface EmailDraftProps { email: DraftEmail diff --git a/web/src/components/emails/EmailMenuBar.tsx b/web/src/components/emails/EmailMenuBar.tsx index 1927fb351a..453cf94cd6 100644 --- a/web/src/components/emails/EmailMenuBar.tsx +++ b/web/src/components/emails/EmailMenuBar.tsx @@ -7,10 +7,11 @@ import { } from '@heroicons/react/24/outline' import { useContext, useEffect, useState } from 'react' -import { ConfigContext, Plugin } from '../../contexts/ConfigContext' -import { DraftEmailsContext } from '../../contexts/DraftEmailContext' -import { createEmail, generateLocalDraftID } from '../../services/emails' -import * as plugins from '../../services/plugins' +import { ConfigContext, Plugin } from 'contexts/ConfigContext' +import { DraftEmailsContext } from 'contexts/DraftEmailContext' + +import { createEmail, generateLocalDraftID } from 'services/emails' +import * as plugins from 'services/plugins' interface EmailMenuBarProps { emailIDs: string[] diff --git a/web/src/components/emails/EmailTableRow.tsx b/web/src/components/emails/EmailTableRow.tsx index ebf167971a..18e6c81ec1 100644 --- a/web/src/components/emails/EmailTableRow.tsx +++ b/web/src/components/emails/EmailTableRow.tsx @@ -1,10 +1,12 @@ import { useContext } from 'react' import { useNavigate } from 'react-router-dom' -import { DraftEmailsContext } from '../../contexts/DraftEmailContext' -import { EmailInfo, getEmail } from '../../services/emails' -import { getNameFromEmails } from '../../utils/emails' -import { formatDate } from '../../utils/time' +import { DraftEmailsContext } from 'contexts/DraftEmailContext' + +import { EmailInfo, getEmail } from 'services/emails' + +import { getNameFromEmails } from 'utils/emails' +import { formatDate } from 'utils/time' interface EmailTableRowProps { email: EmailInfo diff --git a/web/src/components/emails/EmailTableView.tsx b/web/src/components/emails/EmailTableView.tsx index c87608a430..01642bdfb3 100644 --- a/web/src/components/emails/EmailTableView.tsx +++ b/web/src/components/emails/EmailTableView.tsx @@ -1,7 +1,9 @@ import { useEffect, useRef } from 'react' -import useIsInViewport from '../../hooks/useIsInViewport' -import { EmailInfo } from '../../services/emails' +import useIsInViewport from 'hooks/useIsInViewport' + +import { EmailInfo } from 'services/emails' + import EmailTableRow from './EmailTableRow' interface EmailTableViewProps { diff --git a/web/src/components/emails/FullScreenContent.tsx b/web/src/components/emails/FullScreenContent.tsx index 549871c9f0..6b6f4f4384 100644 --- a/web/src/components/emails/FullScreenContent.tsx +++ b/web/src/components/emails/FullScreenContent.tsx @@ -1,11 +1,11 @@ import { useContext, useEffect, useState } from 'react' -import { - DraftEmail, - DraftEmailsContext -} from '../../contexts/DraftEmailContext' -import useThrottled from '../../hooks/useThrottled' -import { deleteEmail, saveEmail } from '../../services/emails' +import { DraftEmail, DraftEmailsContext } from 'contexts/DraftEmailContext' + +import useThrottled from 'hooks/useThrottled' + +import { deleteEmail, saveEmail } from 'services/emails' + import { EmailDraft } from './EmailDraft' interface FullScreenContentProps { diff --git a/web/src/components/inputs/EmailQuoteNode.tsx b/web/src/components/inputs/EmailQuoteNode.tsx index 055019ffa3..f42b43aeb3 100644 --- a/web/src/components/inputs/EmailQuoteNode.tsx +++ b/web/src/components/inputs/EmailQuoteNode.tsx @@ -11,7 +11,7 @@ import { } from 'lexical' import { ReactNode } from 'react' -import { parseEmailHTML } from '../../utils/emails' +import { parseEmailHTML } from 'utils/emails' export class EmailQuoteNode extends DecoratorNode { __html: string diff --git a/web/src/components/inputs/plugins/ToolbarPlugin.tsx b/web/src/components/inputs/plugins/ToolbarPlugin.tsx index 67a8322a88..e5874a6937 100644 --- a/web/src/components/inputs/plugins/ToolbarPlugin.tsx +++ b/web/src/components/inputs/plugins/ToolbarPlugin.tsx @@ -65,12 +65,12 @@ import { } from 'react' import { createPortal } from 'react-dom' -import Bars3BottomCenterIcon from '../icons/Bars3BottomCenterIcon' -import BoldIcon from '../icons/BoldIcon' -import ItalicIcon from '../icons/ItalicIcon' -import ListNumberIcon from '../icons/ListNumberIcon' -import StrikeThroughIcon from '../icons/StrikeThrough' -import UnderlineIcon from '../icons/Underline' +import Bars3BottomCenterIcon from 'components/inputs/icons/Bars3BottomCenterIcon' +import BoldIcon from 'components/inputs/icons/BoldIcon' +import ItalicIcon from 'components/inputs/icons/ItalicIcon' +import ListNumberIcon from 'components/inputs/icons/ListNumberIcon' +import StrikeThroughIcon from 'components/inputs/icons/StrikeThrough' +import UnderlineIcon from 'components/inputs/icons/Underline' const LowPriority = 1 diff --git a/web/src/components/ui/toast.tsx b/web/src/components/ui/toast.tsx index 7010b1cf97..3311501a07 100644 --- a/web/src/components/ui/toast.tsx +++ b/web/src/components/ui/toast.tsx @@ -1,9 +1,10 @@ import * as ToastPrimitives from '@radix-ui/react-toast' import { type VariantProps, cva } from 'class-variance-authority' -import { cn } from 'lib/utils' import { X } from 'lucide-react' import * as React from 'react' +import { cn } from 'lib/utils' + const ToastProvider = ToastPrimitives.Provider const ToastViewport = React.forwardRef< diff --git a/web/src/components/ui/use-toast.ts b/web/src/components/ui/use-toast.ts index 0f248a8b83..4b1bea809e 100644 --- a/web/src/components/ui/use-toast.ts +++ b/web/src/components/ui/use-toast.ts @@ -1,7 +1,8 @@ // Inspired by react-hot-toast library -import type { ToastActionElement, ToastProps } from 'components/ui/toast' import * as React from 'react' +import type { ToastActionElement, ToastProps } from 'components/ui/toast' + const TOAST_LIMIT = 1 const TOAST_REMOVE_DELAY = 1000000 diff --git a/web/src/contexts/ConfigContext.ts b/web/src/contexts/ConfigContext.ts index ef2cf3c04a..002c7aed84 100644 --- a/web/src/contexts/ConfigContext.ts +++ b/web/src/contexts/ConfigContext.ts @@ -1,4 +1,5 @@ import { Dispatch, createContext } from 'react' + import { Config } from 'services/config' export interface Plugin { diff --git a/web/src/contexts/DraftEmailContext.test.tsx b/web/src/contexts/DraftEmailContext.test.tsx index a5ed535971..76d1260df1 100644 --- a/web/src/contexts/DraftEmailContext.test.tsx +++ b/web/src/contexts/DraftEmailContext.test.tsx @@ -2,7 +2,8 @@ import { renderHook } from '@testing-library/react' import { useContext, useReducer } from 'react' import { act } from 'react-dom/test-utils' -import { Email } from '../services/emails' +import { Email } from 'services/emails' + import { DraftEmail, DraftEmailsContext, diff --git a/web/src/contexts/DraftEmailContext.ts b/web/src/contexts/DraftEmailContext.ts index cd30626ea7..7949989e4c 100644 --- a/web/src/contexts/DraftEmailContext.ts +++ b/web/src/contexts/DraftEmailContext.ts @@ -1,7 +1,8 @@ import { Dispatch, createContext } from 'react' -import { Email } from '../services/emails' -import { formatDateFull } from '../utils/time' +import { Email } from 'services/emails' + +import { formatDateFull } from 'utils/time' export interface DraftEmail { messageID: string diff --git a/web/src/pages/EmailList.tsx b/web/src/pages/EmailList.tsx index ec8d44ded2..80b4bfaa39 100644 --- a/web/src/pages/EmailList.tsx +++ b/web/src/pages/EmailList.tsx @@ -1,16 +1,20 @@ -import { toast } from 'components/ui/use-toast' import { useEffect, useRef, useState } from 'react' -import EmailMenuBar from '../components/emails/EmailMenuBar' -import EmailTableView from '../components/emails/EmailTableView' -import { useOutsideClick } from '../hooks/useOutsideClick' +import EmailMenuBar from 'components/emails/EmailMenuBar' +import EmailTableView from 'components/emails/EmailTableView' +import { toast } from 'components/ui/use-toast' + +import { useOutsideClick } from 'hooks/useOutsideClick' + import { deleteEmail, readEmail, trashEmail, unreadEmail -} from '../services/emails' -import { getCurrentYearMonth } from '../utils/time' +} from 'services/emails' + +import { getCurrentYearMonth } from 'utils/time' + import { useInboxContext } from './EmailRoot' export default function EmailList() { diff --git a/web/src/pages/EmailRoot.tsx b/web/src/pages/EmailRoot.tsx index 45342fa16d..7f020d6b83 100644 --- a/web/src/pages/EmailRoot.tsx +++ b/web/src/pages/EmailRoot.tsx @@ -5,13 +5,16 @@ import { useContext, useEffect, useState } from 'react' import { Outlet, useOutletContext } from 'react-router-dom' -import DraftEmailsTabs from '../components/emails/DraftEmailsTabs' -import FullScreenContent from '../components/emails/FullScreenContent' -import { ConfigContext } from '../contexts/ConfigContext' -import { DraftEmailsContext } from '../contexts/DraftEmailContext' -import { getConfig } from '../services/config' -import { EmailInfo, ListEmailsResponse, listEmails } from '../services/emails' -import { getCurrentYearMonth } from '../utils/time' +import DraftEmailsTabs from 'components/emails/DraftEmailsTabs' +import FullScreenContent from 'components/emails/FullScreenContent' + +import { ConfigContext } from 'contexts/ConfigContext' +import { DraftEmailsContext } from 'contexts/DraftEmailContext' + +import { getConfig } from 'services/config' +import { EmailInfo, ListEmailsResponse, listEmails } from 'services/emails' + +import { getCurrentYearMonth } from 'utils/time' type InboxContext = { count: number diff --git a/web/src/pages/EmailView.tsx b/web/src/pages/EmailView.tsx index 24545e4753..77d6d57a64 100644 --- a/web/src/pages/EmailView.tsx +++ b/web/src/pages/EmailView.tsx @@ -7,11 +7,16 @@ import { import React, { useContext, useEffect, useRef, useState } from 'react' import { Await, useLoaderData, useNavigate } from 'react-router-dom' -import { EmailDraft } from '../components/emails/EmailDraft' -import EmailMenuBar from '../components/emails/EmailMenuBar' -import { ConfigContext } from '../contexts/ConfigContext' -import { DraftEmail, DraftEmailsContext } from '../contexts/DraftEmailContext' -import { useOutsideClick } from '../hooks/useOutsideClick' +import { EmailDraft } from 'components/emails/EmailDraft' +import EmailMenuBar from 'components/emails/EmailMenuBar' + +import { ConfigContext } from 'contexts/ConfigContext' +import { DraftEmail, DraftEmailsContext } from 'contexts/DraftEmailContext' + +import { useOutsideClick } from 'hooks/useOutsideClick' + +import { useInboxContext } from 'pages/EmailRoot' + import { CreateEmailProps, Email, @@ -21,12 +26,12 @@ import { saveEmail, trashEmail, unreadEmail -} from '../services/emails' -import { Thread } from '../services/threads' -import { getNameFromEmails } from '../utils/emails' -import { parseEmailContent } from '../utils/emails' -import { formatDate } from '../utils/time' -import { useInboxContext } from './EmailRoot' +} from 'services/emails' +import { Thread } from 'services/threads' + +import { getNameFromEmails } from 'utils/emails' +import { parseEmailContent } from 'utils/emails' +import { formatDate } from 'utils/time' export default function EmailView() { const data = useLoaderData() as diff --git a/web/src/pages/Root.tsx b/web/src/pages/Root.tsx index 60d4ee8ee3..c2bc82a5b1 100644 --- a/web/src/pages/Root.tsx +++ b/web/src/pages/Root.tsx @@ -2,17 +2,18 @@ import { Toaster } from '@ui/toaster' import { useReducer } from 'react' import { Outlet } from 'react-router-dom' -import Sidebar from '../components/Sidebar' +import Sidebar from 'components/Sidebar' + import { ConfigContext, configReducer, initialConfigState -} from '../contexts/ConfigContext' +} from 'contexts/ConfigContext' import { DraftEmailsContext, draftEmailReducer, initialState -} from '../contexts/DraftEmailContext' +} from 'contexts/DraftEmailContext' export default function Root() { const [configState, configDispatch] = useReducer( diff --git a/web/src/utils/emails.tsx b/web/src/utils/emails.tsx index 2218bb27bd..a511edbf9d 100644 --- a/web/src/utils/emails.tsx +++ b/web/src/utils/emails.tsx @@ -7,7 +7,7 @@ import parse, { domToReact } from 'html-react-parser' -import { Email } from '../services/emails' +import { Email } from 'services/emails' export function getNameFromEmails(emails: string[] | null): string { if (!emails || emails.length === 0) {