369b1b19af
question -- should we have confirmation modal on delete -- if yes -- should it appear on save -- or on delete? figma - https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=79469-817497&t=5gFTRiI5f8nPyzc6-0 Note - Figma has a new side panel header, which is unavailable for now, so I used the existing one In a follow-up, we could even have icons for tabs -- would be cool -- and an icon picker for the icons? followups which could be addressed in separate PRs - - ~~tabs being edited state (select state?) -- this would have blue border around tab~~ done - add icons on tabs -- need to update the entity to add icon -- and set a default (dashboard) -- at least - icon picker in the sidepanel header closes - https://discord.com/channels/1130383047699738754/1430204556884836532 video QA https://github.com/user-attachments/assets/a4ad4b93-911d-46ce-9b68-347fd48fe933
85 lines
3.0 KiB
TypeScript
85 lines
3.0 KiB
TypeScript
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
|
import { getTabListInstanceIdFromPageLayoutId } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutId';
|
|
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
|
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
|
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
|
import { useRecoilCallback } from 'recoil';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
import { pageLayoutCurrentLayoutsComponentState } from '../states/pageLayoutCurrentLayoutsComponentState';
|
|
import { pageLayoutDraftComponentState } from '../states/pageLayoutDraftComponentState';
|
|
import { type PageLayoutTab } from '../types/PageLayoutTab';
|
|
import { getEmptyTabLayout } from '../utils/getEmptyTabLayout';
|
|
|
|
export const useCreatePageLayoutTab = (pageLayoutIdFromProps?: string) => {
|
|
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
|
|
PageLayoutComponentInstanceContext,
|
|
pageLayoutIdFromProps,
|
|
);
|
|
|
|
const pageLayoutDraftState = useRecoilComponentCallbackState(
|
|
pageLayoutDraftComponentState,
|
|
pageLayoutId,
|
|
);
|
|
|
|
const pageLayoutCurrentLayoutsState = useRecoilComponentCallbackState(
|
|
pageLayoutCurrentLayoutsComponentState,
|
|
pageLayoutId,
|
|
);
|
|
|
|
const tabListInstanceId = getTabListInstanceIdFromPageLayoutId(pageLayoutId);
|
|
const setActiveTabId = useSetRecoilComponentState(
|
|
activeTabIdComponentState,
|
|
tabListInstanceId,
|
|
);
|
|
|
|
const createPageLayoutTab = useRecoilCallback(
|
|
({ snapshot, set }) =>
|
|
(title?: string): string => {
|
|
const pageLayoutDraft = snapshot
|
|
.getLoadable(pageLayoutDraftState)
|
|
.getValue();
|
|
|
|
const newTabId = uuidv4();
|
|
const tabsLength = pageLayoutDraft.tabs.length;
|
|
const maxPosition =
|
|
tabsLength > 0
|
|
? Math.max(...pageLayoutDraft.tabs.map((t) => t.position))
|
|
: -1;
|
|
const newTab: PageLayoutTab = {
|
|
id: newTabId,
|
|
title: title || `Tab ${tabsLength + 1}`,
|
|
position: maxPosition + 1,
|
|
pageLayoutId: pageLayoutId,
|
|
widgets: [],
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
deletedAt: null,
|
|
};
|
|
|
|
const updatedTabs = [...(pageLayoutDraft.tabs || []), newTab];
|
|
|
|
set(pageLayoutDraftState, (prev) => ({
|
|
...prev,
|
|
tabs: updatedTabs,
|
|
}));
|
|
|
|
set(pageLayoutCurrentLayoutsState, (prev) =>
|
|
getEmptyTabLayout(prev, newTabId),
|
|
);
|
|
|
|
setActiveTabId(newTabId);
|
|
|
|
return newTabId;
|
|
},
|
|
[
|
|
pageLayoutCurrentLayoutsState,
|
|
pageLayoutDraftState,
|
|
pageLayoutId,
|
|
setActiveTabId,
|
|
],
|
|
);
|
|
|
|
return { createPageLayoutTab };
|
|
};
|