twentyhq / twenty

Building a modern alternative to Salesforce, powered by the community.
https://twenty.com
GNU Affero General Public License v3.0
16.06k stars 1.82k forks source link

Use react router for ShowPageRightContainer tabs #5493

Open FelixMalfait opened 4 months ago

FelixMalfait commented 4 months ago

Tabs on a record's show page are currently managed through a recoilState.

It would be best to change this and have a proper url for each tab (/tasks, /emails...). No need to add /timeline in the url for the default tab, the default tab should be just /{id) Also make sure we use Link and not navigate to switch between tabs

greptile-apps[bot] commented 4 months ago

Disclaimer: This comment was automatically generated with AI. It can give some useful hints as to where to look for, but sometimes it can also give very inaccurate answers so takes this with a pinch of salt :).

To use React Router for ShowPageRightContainer tabs, follow these steps:

  1. Update ShowPageRightContainer.tsx:
    • Import necessary components from react-router-dom.
    • Replace Recoil state management with React Router logic.
    • Use Link for tab navigation.
import { Link, useLocation } from 'react-router-dom';

const ShowPageRightContainer = ({ targetableObject, timeline, tasks, notes, emails, loading }: ShowPageRightContainerProps) => {
  const location = useLocation();
  const activeTabId = location.pathname.split('/').pop();

  const shouldDisplayCalendarTab =
    targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Company ||
    targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person;

  const shouldDisplayLogTab = useIsFeatureEnabled('IS_EVENT_OBJECT_ENABLED');

  const shouldDisplayEmailsTab =
    (emails && targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Company) ||
    targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person;

  const TASK_TABS = [
    { id: 'timeline', title: 'Timeline', Icon: IconTimelineEvent, hide: !timeline },
    { id: 'tasks', title: 'Tasks', Icon: IconCheckbox, hide: !tasks },
    { id: 'notes', title: 'Notes', Icon: IconNotes, hide: !notes },
    { id: 'files', title: 'Files', Icon: IconPaperclip, hide: !notes },
    { id: 'emails', title: 'Emails', Icon: IconMail, hide: !shouldDisplayEmailsTab },
    { id: 'calendar', title: 'Calendar', Icon: IconCalendarEvent, hide: !shouldDisplayCalendarTab },
    { id: 'logs', title: 'Logs', Icon: IconTimelineEvent, hide: !shouldDisplayLogTab, hasBetaPill: true },
  ];

  return (
    <StyledShowPageRightContainer>
      <StyledTabListContainer>
        <TabList loading={loading} tabListId={TAB_LIST_COMPONENT_ID} tabs={TASK_TABS} />
      </StyledTabListContainer>
      {activeTabId === 'timeline' && (
        <>
          <TimelineQueryEffect targetableObject={targetableObject} />
          <Timeline loading={loading} targetableObject={targetableObject} />
        </>
      )}
      {activeTabId === 'tasks' && <ObjectTasks targetableObject={targetableObject} />}
      {activeTabId === 'notes' && <Notes targetableObject={targetableObject} />}
      {activeTabId === 'files' && <Attachments targetableObject={targetableObject} />}
      {activeTabId === 'emails' && <EmailThreads targetableObject={targetableObject} />}
      {activeTabId === 'calendar' && <Calendar targetableObject={targetableObject} />}
      {activeTabId === 'logs' && <TimelineActivities targetableObject={targetableObject} />}
    </StyledShowPageRightContainer>
  );
};
  1. Update TabList.tsx:
    • Use Link from react-router-dom for tab navigation.
import { Link } from 'react-router-dom';

export const TabList = ({ tabs, tabListId, loading }: TabListProps) => {
  const initialActiveTabId = tabs[0].id;

  const { activeTabIdState, setActiveTabId } = useTabList(tabListId);

  const activeTabId = useRecoilValue(activeTabIdState);

  React.useEffect(() => {
    setActiveTabId(initialActiveTabId);
  }, [initialActiveTabId, setActiveTabId]);

  return (
    <TabListScope tabListScopeId={tabListId}>
      <ScrollWrapper hideY>
        <StyledContainer>
          {tabs
            .filter((tab) => !tab.hide)
            .map((tab) => (
              <Link to={`/${tab.id}`} key={tab.id}>
                <Tab
                  id={tab.id}
                  title={tab.title}
                  Icon={tab.Icon}
                  active={tab.id === activeTabId}
                  onClick={() => {
                    setActiveTabId(tab.id);
                  }}
                  disabled={tab.disabled ?? loading}
                  hasBetaPill={tab.hasBetaPill}
                />
              </Link>
            ))}
        </StyledContainer>
      </ScrollWrapper>
    </TabListScope>
  );
};
  1. Update App.tsx:
    • Define routes for each tab.
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

const App = () => {
  return (
    <Router>
      <Routes>
        <Route path="/timeline" element={<ShowPageRightContainer />} />
        <Route path="/tasks" element={<ShowPageRightContainer />} />
        <Route path="/notes" element={<ShowPageRightContainer />} />
        <Route path="/files" element={<ShowPageRightContainer />} />
        <Route path="/emails" element={<ShowPageRightContainer />} />
        <Route path="/calendar" element={<ShowPageRightContainer />} />
        <Route path="/logs" element={<ShowPageRightContainer />} />
      </Routes>
    </Router>
  );
};

These changes will enable tab navigation using React Router with proper URLs and Link components.

References

/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx /packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx /packages/twenty-front/src/modules/ui/layout/tab/hooks/useTabList.ts /packages/twenty-front/src/App.tsx /packages/twenty-front/src/modules/object-record/record-show/components /packages/twenty-front/src/pages/object-record/RecordShowPage.tsx

Ask Greptile