Feat/sidecar components (#1578)

* Added a new eslint plugin in TypeScript for Effect components

* Fixed edge cases

* Fixed lint

* Fix eslint

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2023-09-15 02:04:45 +02:00
committed by GitHub
parent 09db29c91a
commit 84a27b148f
35 changed files with 4201 additions and 49 deletions

View File

@ -7,10 +7,9 @@ import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
import { CreateProfile } from '~/pages/auth/CreateProfile';
import { CreateWorkspace } from '~/pages/auth/CreateWorkspace';
import { SignInUp } from '~/pages/auth/SignInUp';
import { Verify } from '~/pages/auth/Verify';
import { VerifyEffect } from '~/pages/auth/VerifyEffect';
import { Companies } from '~/pages/companies/Companies';
import { CompanyShow } from '~/pages/companies/CompanyShow';
import { Impersonate } from '~/pages/impersonate/Impersonate';
import { Opportunities } from '~/pages/opportunities/Opportunities';
import { People } from '~/pages/people/People';
import { PersonShow } from '~/pages/people/PersonShow';
@ -19,8 +18,10 @@ import { SettingsProfile } from '~/pages/settings/SettingsProfile';
import { SettingsWorkspace } from '~/pages/settings/SettingsWorkspace';
import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMembers';
import { Tasks } from '~/pages/tasks/Tasks';
import { AppInternalHooks } from '~/sync-hooks/AppInternalHooks';
import { CommandMenuEffect } from './effect-components/CommandMenuEffect';
import { GotoHotkeysEffect } from './effect-components/GotoHotkeysEffect';
import { ImpersonateEffect } from './pages/impersonate/ImpersonateEffect';
import { NotFound } from './pages/not-found/NotFound';
import { getPageTitleFromPath } from './utils/title-utils';
@ -34,10 +35,11 @@ export function App() {
return (
<>
<PageTitle title={pageTitle} />
<AppInternalHooks />
<GotoHotkeysEffect />
<CommandMenuEffect />
<DefaultLayout>
<Routes>
<Route path={AppPath.Verify} element={<Verify />} />
<Route path={AppPath.Verify} element={<VerifyEffect />} />
<Route path={AppPath.SignIn} element={<SignInUp />} />
<Route path={AppPath.SignUp} element={<SignInUp />} />
<Route path={AppPath.Invite} element={<SignInUp />} />
@ -49,7 +51,7 @@ export function App() {
<Route path={AppPath.CompaniesPage} element={<Companies />} />
<Route path={AppPath.CompanyShowPage} element={<CompanyShow />} />
<Route path={AppPath.TasksPage} element={<Tasks />} />
<Route path={AppPath.Impersonate} element={<Impersonate />} />
<Route path={AppPath.Impersonate} element={<ImpersonateEffect />} />
<Route path={AppPath.OpportunitiesPage} element={<Opportunities />} />
<Route

View File

@ -4,7 +4,7 @@ import { useSetRecoilState } from 'recoil';
import { commandMenuCommands } from '@/command-menu/constants/commandMenuCommands';
import { commandMenuCommandsState } from '@/command-menu/states/commandMenuCommandsState';
export function CommandMenuHook() {
export function CommandMenuEffect() {
const setCommands = useSetRecoilState(commandMenuCommandsState);
const commands = commandMenuCommands;

View File

@ -1,6 +1,6 @@
import { useGoToHotkeys } from '@/ui/utilities/hotkey/hooks/useGoToHotkeys';
export function GotoHotkeysHooks() {
export function GotoHotkeysEffect() {
useGoToHotkeys('p', '/people');
useGoToHotkeys('c', '/companies');
useGoToHotkeys('o', '/opportunities');

View File

@ -6,7 +6,7 @@ import { RecoilRoot } from 'recoil';
import { ApolloProvider } from '@/apollo/components/ApolloProvider';
import { ClientConfigProvider } from '@/client-config/components/ClientConfigProvider';
import { RecoilDebugObserver } from '@/debug/components/RecoilDebugObserver';
import { RecoilDebugObserverEffect } from '@/debug/components/RecoilDebugObserver';
import { DialogProvider } from '@/ui/dialog/components/DialogProvider';
import { SnackBarProvider } from '@/ui/snack-bar/components/SnackBarProvider';
import { AppThemeProvider } from '@/ui/theme/components/AppThemeProvider';
@ -15,7 +15,7 @@ import { UserProvider } from '@/users/components/UserProvider';
import '@emotion/react';
import { PageChangeEffect } from './sync-hooks/PageChangeEffect';
import { PageChangeEffect } from './effect-components/PageChangeEffect';
import { App } from './App';
import './index.css';
@ -27,7 +27,7 @@ const root = ReactDOM.createRoot(
root.render(
<RecoilRoot>
<RecoilDebugObserver />
<RecoilDebugObserverEffect />
<BrowserRouter>
<ApolloProvider>
<HelmetProvider>

View File

@ -6,7 +6,7 @@ import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { CompanyBoard } from '../board/components/CompanyBoard';
import { HooksCompanyBoard } from '../components/HooksCompanyBoard';
import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect';
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
const meta: Meta<typeof CompanyBoard> = {
@ -15,7 +15,7 @@ const meta: Meta<typeof CompanyBoard> = {
decorators: [
(Story) => (
<RecoilScope SpecificContext={CompanyBoardRecoilScopeContext}>
<HooksCompanyBoard />
<HooksCompanyBoardEffect />
<MemoryRouter>
<Story />
</MemoryRouter>

View File

@ -14,7 +14,7 @@ import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/Componen
import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress';
import { HooksCompanyBoard } from '../components/HooksCompanyBoard';
import { HooksCompanyBoardEffect } from '../components/HooksCompanyBoardEffect';
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
const meta: Meta<typeof CompanyBoardCard> = {
@ -33,7 +33,7 @@ const meta: Meta<typeof CompanyBoardCard> = {
return (
<>
<HooksCompanyBoard />
<HooksCompanyBoardEffect />
<RecoilScope SpecificContext={BoardColumnRecoilScopeContext}>
<BoardCardIdContext.Provider
value={mockedPipelineProgressData[1].id}

View File

@ -9,7 +9,7 @@ import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { useBoardViews } from '@/views/hooks/useBoardViews';
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
import { HooksCompanyBoard } from '../../components/HooksCompanyBoard';
import { HooksCompanyBoardEffect } from '../../components/HooksCompanyBoardEffect';
import { CompanyBoardRecoilScopeContext } from '../../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
type CompanyBoardProps = Pick<
@ -31,7 +31,7 @@ export const CompanyBoard = ({
return (
<>
<HooksCompanyBoard />
<HooksCompanyBoardEffect />
<ViewBarContext.Provider
value={{
defaultViewName: 'All Opportunities',

View File

@ -24,7 +24,7 @@ import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
export function HooksCompanyBoard() {
export function HooksCompanyBoardEffect() {
const [, setAvailableFilters] = useRecoilScopedState(
availableFiltersScopedState,
CompanyBoardRecoilScopeContext,

View File

@ -9,7 +9,7 @@ import { companiesAvailableColumnDefinitions } from '../../constants/companiesAv
import { mockedCompaniesData } from './companies-mock-data';
export function CompanyTableMockData() {
export function CompanyTableMockDataEffect() {
const [, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState,
TableRecoilScopeContext,

View File

@ -2,12 +2,12 @@ import { EntityTable } from '@/ui/table/components/EntityTable';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { useUpdateOneCompanyMutation } from '~/generated/graphql';
import { CompanyTableMockData } from './CompanyTableMockData';
import { CompanyTableMockDataEffect } from './CompanyTableMockDataEffect';
export function CompanyTableMockMode() {
return (
<>
<CompanyTableMockData />
<CompanyTableMockDataEffect />
<ViewBarContext.Provider value={{ defaultViewName: 'All Companies' }}>
<EntityTable updateEntityMutation={[useUpdateOneCompanyMutation()]} />
</ViewBarContext.Provider>

View File

@ -14,7 +14,7 @@ const formatTitle = (stateName: string) => {
return [parts.join(' '), ...headerCss];
};
export function RecoilDebugObserver() {
export function RecoilDebugObserverEffect() {
const snapshot = useRecoilSnapshot();
const isDebugMode = useRecoilValue(isDebugModeState);

View File

@ -6,7 +6,7 @@ import {
import { useSetPeopleEntityTable } from '../hooks/useSetPeopleEntityTable';
export function PeopleEntityTableData({
export function PeopleEntityTableDataEffect({
orderBy = [
{
createdAt: SortOrder.Desc,

View File

@ -5,7 +5,7 @@ type OwnProps = {
onAddButtonClick?: () => void;
};
export function PageHotkeys({ onAddButtonClick }: OwnProps) {
export function PageHotkeysEffect({ onAddButtonClick }: OwnProps) {
useScopedHotkeys('c', () => onAddButtonClick?.(), TableHotkeyScope.Table, [
onAddButtonClick,
]);

View File

@ -7,7 +7,7 @@ import { useIsLogged } from '@/auth/hooks/useIsLogged';
import { AppPath } from '../../modules/types/AppPath';
import { isNonEmptyString } from '../../utils/isNonEmptyString';
export function Verify() {
export function VerifyEffect() {
const [searchParams] = useSearchParams();
const loginToken = searchParams.get('loginToken');

View File

@ -12,7 +12,7 @@ import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { PageHotkeys } from '@/ui/layout/components/PageHotkeys';
import { PageHotkeysEffect } from '@/ui/layout/components/PageHotkeysEffect';
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
import { EntityTableContextMenu } from '@/ui/table/context-menu/components/EntityTableContextMenu';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
@ -59,7 +59,7 @@ export function Companies() {
<PageContainer>
<PageHeader title="Companies" Icon={IconBuildingSkyscraper}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageHotkeys onAddButtonClick={handleAddButtonClick} />
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
</PageHeader>

View File

@ -10,7 +10,7 @@ import { useImpersonateMutation } from '~/generated/graphql';
import { AppPath } from '../../modules/types/AppPath';
import { isNonEmptyString } from '../../utils/isNonEmptyString';
export function Impersonate() {
export function ImpersonateEffect() {
const navigate = useNavigate();
const { userId } = useParams();

View File

@ -10,7 +10,7 @@ import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
import { PageHeader } from '@/ui/layout/components/PageHeader';
import { PageHotkeys } from '@/ui/layout/components/PageHotkeys';
import { PageHotkeysEffect } from '@/ui/layout/components/PageHotkeysEffect';
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
import { EntityTableContextMenu } from '@/ui/table/context-menu/components/EntityTableContextMenu';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
@ -55,7 +55,7 @@ export function People() {
<PageContainer>
<PageHeader title="People" Icon={IconUser}>
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
<PageHotkeys onAddButtonClick={handleAddButtonClick} />
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
</PageHeader>

View File

@ -1,11 +0,0 @@
import { CommandMenuHook } from './CommandMenuHook';
import { GotoHotkeysHooks } from './GotoHotkeysHooks';
export function AppInternalHooks() {
return (
<>
<GotoHotkeysHooks />
<CommandMenuHook />
</>
);
}

View File

@ -3,7 +3,7 @@ import { useEffect } from 'react';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
export function InitializeHotkeyStorybookHook() {
export function InitializeHotkeyStorybookHookEffect() {
const setHotkeyScope = useSetHotkeyScope();
useEffect(() => {

View File

@ -2,13 +2,13 @@ import { ApolloProvider } from '@apollo/client';
import { Decorator } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { InitializeHotkeyStorybookHook } from '../InitializeHotkeyStorybookHook';
import { InitializeHotkeyStorybookHookEffect } from '../InitializeHotkeyStorybookHook';
import { mockedClient } from '../mockedClient';
export const RootDecorator: Decorator = (Story) => (
<RecoilRoot>
<ApolloProvider client={mockedClient}>
<InitializeHotkeyStorybookHook />
<InitializeHotkeyStorybookHookEffect />
<Story />
</ApolloProvider>
</RecoilRoot>