mirror of
				https://github.com/lingble/twenty.git
				synced 2025-10-30 20:27:55 +00:00 
			
		
		
		
	7339 implement contextual actions inside the commandmenu (#8000)
Closes #7339 https://github.com/user-attachments/assets/b623caa4-c1b3-448e-8880-4a8301802ba8
This commit is contained in:
		| @@ -1,5 +1,5 @@ | |||||||
|  | import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; | ||||||
| import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries'; | import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries'; | ||||||
| import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; |  | ||||||
| import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | ||||||
| import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; | import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; | ||||||
| import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; | import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; | ||||||
| @@ -12,17 +12,15 @@ import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTabl | |||||||
| import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; | import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; | ||||||
| import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; | import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; | ||||||
| import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
| import { useCallback, useEffect, useState } from 'react'; | import { useCallback, useContext, useEffect, useState } from 'react'; | ||||||
| import { IconTrash, isDefined } from 'twenty-ui'; | import { IconTrash, isDefined } from 'twenty-ui'; | ||||||
|  |  | ||||||
| export const DeleteRecordsActionEffect = ({ | export const DeleteRecordsActionEffect = ({ | ||||||
|   position, |   position, | ||||||
|   objectMetadataItem, |   objectMetadataItem, | ||||||
|   actionMenuType, |  | ||||||
| }: { | }: { | ||||||
|   position: number; |   position: number; | ||||||
|   objectMetadataItem: ObjectMetadataItem; |   objectMetadataItem: ObjectMetadataItem; | ||||||
|   actionMenuType: ActionMenuType; |  | ||||||
| }) => { | }) => { | ||||||
|   const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries(); |   const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries(); | ||||||
|  |  | ||||||
| @@ -93,6 +91,9 @@ export const DeleteRecordsActionEffect = ({ | |||||||
|     contextStoreNumberOfSelectedRecords < DELETE_MAX_COUNT && |     contextStoreNumberOfSelectedRecords < DELETE_MAX_COUNT && | ||||||
|     contextStoreNumberOfSelectedRecords > 0; |     contextStoreNumberOfSelectedRecords > 0; | ||||||
|  |  | ||||||
|  |   const { isInRightDrawer, onActionExecutedCallback } = | ||||||
|  |     useContext(ActionMenuContext); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (canDelete) { |     if (canDelete) { | ||||||
|       addActionMenuEntry({ |       addActionMenuEntry({ | ||||||
| @@ -120,17 +121,14 @@ export const DeleteRecordsActionEffect = ({ | |||||||
|             } can be recovered from the Options menu.`} |             } can be recovered from the Options menu.`} | ||||||
|             onConfirmClick={() => { |             onConfirmClick={() => { | ||||||
|               handleDeleteClick(); |               handleDeleteClick(); | ||||||
|  |               onActionExecutedCallback?.(); | ||||||
|               if (actionMenuType === 'recordShow') { |               if (isInRightDrawer) { | ||||||
|                 closeRightDrawer(); |                 closeRightDrawer(); | ||||||
|               } |               } | ||||||
|             }} |             }} | ||||||
|             deleteButtonText={`Delete ${ |             deleteButtonText={`Delete ${ | ||||||
|               contextStoreNumberOfSelectedRecords > 1 ? 'Records' : 'Record' |               contextStoreNumberOfSelectedRecords > 1 ? 'Records' : 'Record' | ||||||
|             }`} |             }`} | ||||||
|             modalVariant={ |  | ||||||
|               actionMenuType === 'recordShow' ? 'tertiary' : 'primary' |  | ||||||
|             } |  | ||||||
|           /> |           /> | ||||||
|         ), |         ), | ||||||
|       }); |       }); | ||||||
| @@ -142,13 +140,14 @@ export const DeleteRecordsActionEffect = ({ | |||||||
|       removeActionMenuEntry('delete'); |       removeActionMenuEntry('delete'); | ||||||
|     }; |     }; | ||||||
|   }, [ |   }, [ | ||||||
|     actionMenuType, |  | ||||||
|     addActionMenuEntry, |     addActionMenuEntry, | ||||||
|     canDelete, |     canDelete, | ||||||
|     closeRightDrawer, |     closeRightDrawer, | ||||||
|     contextStoreNumberOfSelectedRecords, |     contextStoreNumberOfSelectedRecords, | ||||||
|     handleDeleteClick, |     handleDeleteClick, | ||||||
|     isDeleteRecordsModalOpen, |     isDeleteRecordsModalOpen, | ||||||
|  |     isInRightDrawer, | ||||||
|  |     onActionExecutedCallback, | ||||||
|     position, |     position, | ||||||
|     removeActionMenuEntry, |     removeActionMenuEntry, | ||||||
|   ]); |   ]); | ||||||
|   | |||||||
| @@ -1,27 +0,0 @@ | |||||||
| import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect'; |  | ||||||
| import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect'; |  | ||||||
| import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; |  | ||||||
| import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; |  | ||||||
|  |  | ||||||
| const actionEffects = [ExportRecordsActionEffect, DeleteRecordsActionEffect]; |  | ||||||
|  |  | ||||||
| export const MultipleRecordsActionMenuEntriesSetter = ({ |  | ||||||
|   objectMetadataItem, |  | ||||||
|   actionMenuType, |  | ||||||
| }: { |  | ||||||
|   objectMetadataItem: ObjectMetadataItem; |  | ||||||
|   actionMenuType: ActionMenuType; |  | ||||||
| }) => { |  | ||||||
|   return ( |  | ||||||
|     <> |  | ||||||
|       {actionEffects.map((ActionEffect, index) => ( |  | ||||||
|         <ActionEffect |  | ||||||
|           key={index} |  | ||||||
|           position={index} |  | ||||||
|           objectMetadataItem={objectMetadataItem} |  | ||||||
|           actionMenuType={actionMenuType} |  | ||||||
|         /> |  | ||||||
|       ))} |  | ||||||
|     </> |  | ||||||
|   ); |  | ||||||
| }; |  | ||||||
| @@ -1,16 +1,23 @@ | |||||||
| import { MultipleRecordsActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter'; | import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect'; | ||||||
| import { SingleRecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter'; | import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect'; | ||||||
| import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; | import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect'; | ||||||
| import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | ||||||
| import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | ||||||
| import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; | import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; | ||||||
| import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
|  |  | ||||||
| export const RecordActionMenuEntriesSetter = ({ | const singleRecordActionEffects = [ | ||||||
|   actionMenuType, |   ManageFavoritesActionEffect, | ||||||
| }: { |   ExportRecordsActionEffect, | ||||||
|   actionMenuType: ActionMenuType; |   DeleteRecordsActionEffect, | ||||||
| }) => { | ]; | ||||||
|  |  | ||||||
|  | const multipleRecordActionEffects = [ | ||||||
|  |   ExportRecordsActionEffect, | ||||||
|  |   DeleteRecordsActionEffect, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const RecordActionMenuEntriesSetter = () => { | ||||||
|   const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( |   const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( | ||||||
|     contextStoreNumberOfSelectedRecordsComponentState, |     contextStoreNumberOfSelectedRecordsComponentState, | ||||||
|   ); |   ); | ||||||
| @@ -33,19 +40,20 @@ export const RecordActionMenuEntriesSetter = ({ | |||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (contextStoreNumberOfSelectedRecords === 1) { |   const actions = | ||||||
|     return ( |     contextStoreNumberOfSelectedRecords === 1 | ||||||
|       <SingleRecordActionMenuEntriesSetter |       ? singleRecordActionEffects | ||||||
|         objectMetadataItem={objectMetadataItem} |       : multipleRecordActionEffects; | ||||||
|         actionMenuType={actionMenuType} |  | ||||||
|       /> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <MultipleRecordsActionMenuEntriesSetter |     <> | ||||||
|  |       {actions.map((ActionEffect, index) => ( | ||||||
|  |         <ActionEffect | ||||||
|  |           key={index} | ||||||
|  |           position={index} | ||||||
|           objectMetadataItem={objectMetadataItem} |           objectMetadataItem={objectMetadataItem} | ||||||
|       actionMenuType={actionMenuType} |  | ||||||
|         /> |         /> | ||||||
|  |       ))} | ||||||
|  |     </> | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,31 +0,0 @@ | |||||||
| import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect'; |  | ||||||
| import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect'; |  | ||||||
| import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect'; |  | ||||||
| import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; |  | ||||||
| import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; |  | ||||||
|  |  | ||||||
| export const SingleRecordActionMenuEntriesSetter = ({ |  | ||||||
|   objectMetadataItem, |  | ||||||
|   actionMenuType, |  | ||||||
| }: { |  | ||||||
|   objectMetadataItem: ObjectMetadataItem; |  | ||||||
|   actionMenuType: ActionMenuType; |  | ||||||
| }) => { |  | ||||||
|   const actionEffects = [ |  | ||||||
|     ManageFavoritesActionEffect, |  | ||||||
|     ExportRecordsActionEffect, |  | ||||||
|     DeleteRecordsActionEffect, |  | ||||||
|   ]; |  | ||||||
|   return ( |  | ||||||
|     <> |  | ||||||
|       {actionEffects.map((ActionEffect, index) => ( |  | ||||||
|         <ActionEffect |  | ||||||
|           key={index} |  | ||||||
|           position={index} |  | ||||||
|           objectMetadataItem={objectMetadataItem} |  | ||||||
|           actionMenuType={actionMenuType} |  | ||||||
|         /> |  | ||||||
|       ))} |  | ||||||
|     </> |  | ||||||
|   ); |  | ||||||
| }; |  | ||||||
| @@ -3,16 +3,12 @@ import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMen | |||||||
| import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar'; | import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar'; | ||||||
| import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown'; | import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown'; | ||||||
| import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect'; | import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect'; | ||||||
|  | import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; | ||||||
|  |  | ||||||
| import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; |  | ||||||
| import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | ||||||
| import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
|  |  | ||||||
| export const RecordIndexActionMenu = ({ | export const RecordIndexActionMenu = () => { | ||||||
|   actionMenuId, |  | ||||||
| }: { |  | ||||||
|   actionMenuId: string; |  | ||||||
| }) => { |  | ||||||
|   const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( |   const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( | ||||||
|     contextStoreCurrentObjectMetadataIdComponentState, |     contextStoreCurrentObjectMetadataIdComponentState, | ||||||
|   ); |   ); | ||||||
| @@ -20,15 +16,18 @@ export const RecordIndexActionMenu = ({ | |||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       {contextStoreCurrentObjectMetadataId && ( |       {contextStoreCurrentObjectMetadataId && ( | ||||||
|         <ActionMenuComponentInstanceContext.Provider |         <ActionMenuContext.Provider | ||||||
|           value={{ instanceId: actionMenuId }} |           value={{ | ||||||
|  |             isInRightDrawer: false, | ||||||
|  |             onActionExecutedCallback: () => {}, | ||||||
|  |           }} | ||||||
|         > |         > | ||||||
|           <RecordIndexActionMenuBar /> |           <RecordIndexActionMenuBar /> | ||||||
|           <RecordIndexActionMenuDropdown /> |           <RecordIndexActionMenuDropdown /> | ||||||
|           <ActionMenuConfirmationModals /> |           <ActionMenuConfirmationModals /> | ||||||
|           <RecordIndexActionMenuEffect /> |           <RecordIndexActionMenuEffect /> | ||||||
|           <RecordActionMenuEntriesSetter actionMenuType="recordIndex" /> |           <RecordActionMenuEntriesSetter /> | ||||||
|         </ActionMenuComponentInstanceContext.Provider> |         </ActionMenuContext.Provider> | ||||||
|       )} |       )} | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -1,7 +1,9 @@ | |||||||
| import { useActionMenu } from '@/action-menu/hooks/useActionMenu'; | import { useActionMenu } from '@/action-menu/hooks/useActionMenu'; | ||||||
| import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
|  | import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState'; | ||||||
| import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | ||||||
| import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; | import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; | ||||||
|  | import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; | ||||||
| import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; | import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; | ||||||
| import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
| import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; | import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; | ||||||
| @@ -25,6 +27,9 @@ export const RecordIndexActionMenuEffect = () => { | |||||||
|       `action-menu-dropdown-${actionMenuId}`, |       `action-menu-dropdown-${actionMenuId}`, | ||||||
|     ), |     ), | ||||||
|   ); |   ); | ||||||
|  |   const { isRightDrawerOpen } = useRightDrawer(); | ||||||
|  |  | ||||||
|  |   const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (contextStoreNumberOfSelectedRecords > 0 && !isDropdownOpen) { |     if (contextStoreNumberOfSelectedRecords > 0 && !isDropdownOpen) { | ||||||
| @@ -43,5 +48,11 @@ export const RecordIndexActionMenuEffect = () => { | |||||||
|     isDropdownOpen, |     isDropdownOpen, | ||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (isRightDrawerOpen || isCommandMenuOpened) { | ||||||
|  |       closeActionBar(); | ||||||
|  |     } | ||||||
|  |   }, [closeActionBar, isRightDrawerOpen, isCommandMenuOpened]); | ||||||
|  |  | ||||||
|   return null; |   return null; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,30 +1,53 @@ | |||||||
| import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter'; | import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter'; | ||||||
| import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals'; | import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals'; | ||||||
| import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar'; | import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; | ||||||
|  |  | ||||||
| import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; |  | ||||||
| import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | ||||||
|  | import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; | ||||||
|  | import { ObjectRecord } from '@/object-record/types/ObjectRecord'; | ||||||
| import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
|  | import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader'; | ||||||
|  |  | ||||||
| export const RecordShowActionMenu = ({ | export const RecordShowActionMenu = ({ | ||||||
|   actionMenuId, |   isFavorite, | ||||||
|  |   handleFavoriteButtonClick, | ||||||
|  |   record, | ||||||
|  |   objectMetadataItem, | ||||||
|  |   objectNameSingular, | ||||||
| }: { | }: { | ||||||
|   actionMenuId: string; |   isFavorite: boolean; | ||||||
|  |   handleFavoriteButtonClick: () => void; | ||||||
|  |   record: ObjectRecord | undefined; | ||||||
|  |   objectMetadataItem: ObjectMetadataItem; | ||||||
|  |   objectNameSingular: string; | ||||||
| }) => { | }) => { | ||||||
|   const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( |   const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( | ||||||
|     contextStoreCurrentObjectMetadataIdComponentState, |     contextStoreCurrentObjectMetadataIdComponentState, | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|  |   // TODO: refactor RecordShowPageBaseHeader to use the context store | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       {contextStoreCurrentObjectMetadataId && ( |       {contextStoreCurrentObjectMetadataId && ( | ||||||
|         <ActionMenuComponentInstanceContext.Provider |         <ActionMenuContext.Provider | ||||||
|           value={{ instanceId: actionMenuId }} |           value={{ | ||||||
|  |             isInRightDrawer: false, | ||||||
|  |             onActionExecutedCallback: () => {}, | ||||||
|  |           }} | ||||||
|         > |         > | ||||||
|           <RecordShowActionMenuBar /> |           <RecordShowPageBaseHeader | ||||||
|  |             {...{ | ||||||
|  |               isFavorite, | ||||||
|  |               handleFavoriteButtonClick, | ||||||
|  |               record, | ||||||
|  |               objectMetadataItem, | ||||||
|  |               objectNameSingular, | ||||||
|  |             }} | ||||||
|  |           /> | ||||||
|           <ActionMenuConfirmationModals /> |           <ActionMenuConfirmationModals /> | ||||||
|           <RecordActionMenuEntriesSetter actionMenuType="recordShow" /> |           <RecordActionMenuEntriesSetter /> | ||||||
|         </ActionMenuComponentInstanceContext.Provider> |         </ActionMenuContext.Provider> | ||||||
|       )} |       )} | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter'; | ||||||
|  | import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals'; | ||||||
|  | import { RecordShowRightDrawerActionMenuBar } from '@/action-menu/components/RecordShowRightDrawerActionMenuBar'; | ||||||
|  | import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; | ||||||
|  |  | ||||||
|  | import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | ||||||
|  | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
|  |  | ||||||
|  | export const RecordShowRightDrawerActionMenu = () => { | ||||||
|  |   const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( | ||||||
|  |     contextStoreCurrentObjectMetadataIdComponentState, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <> | ||||||
|  |       {contextStoreCurrentObjectMetadataId && ( | ||||||
|  |         <ActionMenuContext.Provider | ||||||
|  |           value={{ | ||||||
|  |             isInRightDrawer: true, | ||||||
|  |             onActionExecutedCallback: () => {}, | ||||||
|  |           }} | ||||||
|  |         > | ||||||
|  |           <RecordShowRightDrawerActionMenuBar /> | ||||||
|  |           <ActionMenuConfirmationModals /> | ||||||
|  |           <RecordActionMenuEntriesSetter /> | ||||||
|  |         </ActionMenuContext.Provider> | ||||||
|  |       )} | ||||||
|  |     </> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
| @@ -2,7 +2,7 @@ import { RecordShowActionMenuBarEntry } from '@/action-menu/components/RecordSho | |||||||
| import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector'; | import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector'; | ||||||
| import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; | ||||||
| 
 | 
 | ||||||
| export const RecordShowActionMenuBar = () => { | export const RecordShowRightDrawerActionMenuBar = () => { | ||||||
|   const actionMenuEntries = useRecoilComponentValueV2( |   const actionMenuEntries = useRecoilComponentValueV2( | ||||||
|     actionMenuEntriesComponentSelector, |     actionMenuEntriesComponentSelector, | ||||||
|   ); |   ); | ||||||
| @@ -2,7 +2,7 @@ import { expect, jest } from '@storybook/jest'; | |||||||
| import { Meta, StoryObj } from '@storybook/react'; | import { Meta, StoryObj } from '@storybook/react'; | ||||||
| import { RecoilRoot } from 'recoil'; | import { RecoilRoot } from 'recoil'; | ||||||
|  |  | ||||||
| import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar'; | import { RecordShowRightDrawerActionMenuBar } from '@/action-menu/components/RecordShowRightDrawerActionMenuBar'; | ||||||
| import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState'; | import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState'; | ||||||
| import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
| import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | ||||||
| @@ -20,9 +20,9 @@ const deleteMock = jest.fn(); | |||||||
| const addToFavoritesMock = jest.fn(); | const addToFavoritesMock = jest.fn(); | ||||||
| const exportMock = jest.fn(); | const exportMock = jest.fn(); | ||||||
|  |  | ||||||
| const meta: Meta<typeof RecordShowActionMenuBar> = { | const meta: Meta<typeof RecordShowRightDrawerActionMenuBar> = { | ||||||
|   title: 'Modules/ActionMenu/RecordShowActionMenuBar', |   title: 'Modules/ActionMenu/RecordShowRightDrawerActionMenuBar', | ||||||
|   component: RecordShowActionMenuBar, |   component: RecordShowRightDrawerActionMenuBar, | ||||||
|   decorators: [ |   decorators: [ | ||||||
|     (Story) => ( |     (Story) => ( | ||||||
|       <RecoilRoot |       <RecoilRoot | ||||||
| @@ -98,7 +98,7 @@ const meta: Meta<typeof RecordShowActionMenuBar> = { | |||||||
|  |  | ||||||
| export default meta; | export default meta; | ||||||
|  |  | ||||||
| type Story = StoryObj<typeof RecordShowActionMenuBar>; | type Story = StoryObj<typeof RecordShowRightDrawerActionMenuBar>; | ||||||
|  |  | ||||||
| export const Default: Story = { | export const Default: Story = { | ||||||
|   args: { |   args: { | ||||||
|   | |||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | import { createContext } from 'react'; | ||||||
|  |  | ||||||
|  | type ActionMenuContextType = { | ||||||
|  |   isInRightDrawer: boolean; | ||||||
|  |   onActionExecutedCallback: () => void; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const ActionMenuContext = createContext<ActionMenuContextType>({ | ||||||
|  |   isInRightDrawer: false, | ||||||
|  |   onActionExecutedCallback: () => {}, | ||||||
|  | }); | ||||||
| @@ -1 +0,0 @@ | |||||||
| export type ActionMenuType = 'recordIndex' | 'recordShow'; |  | ||||||
| @@ -10,6 +10,7 @@ import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchS | |||||||
| import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState'; | import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState'; | ||||||
| import { Command, CommandType } from '@/command-menu/types/Command'; | import { Command, CommandType } from '@/command-menu/types/Command'; | ||||||
| import { Company } from '@/companies/types/Company'; | import { Company } from '@/companies/types/Company'; | ||||||
|  | import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; | ||||||
| import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu'; | import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu'; | ||||||
| import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | ||||||
| import { getCompanyDomainName } from '@/object-metadata/utils/getCompanyDomainName'; | import { getCompanyDomainName } from '@/object-metadata/utils/getCompanyDomainName'; | ||||||
| @@ -287,6 +288,14 @@ export const CommandMenu = () => { | |||||||
|         : true) && cmd.type === CommandType.Create, |         : true) && cmd.type === CommandType.Create, | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|  |   const matchingActionCommands = commandMenuCommands.filter( | ||||||
|  |     (cmd) => | ||||||
|  |       (deferredCommandMenuSearch.length > 0 | ||||||
|  |         ? checkInShortcuts(cmd, deferredCommandMenuSearch) || | ||||||
|  |           checkInLabels(cmd, deferredCommandMenuSearch) | ||||||
|  |         : true) && cmd.type === CommandType.Action, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   useListenClickOutside({ |   useListenClickOutside({ | ||||||
|     refs: [commandMenuRef], |     refs: [commandMenuRef], | ||||||
|     callback: closeCommandMenu, |     callback: closeCommandMenu, | ||||||
| @@ -312,6 +321,7 @@ export const CommandMenu = () => { | |||||||
|  |  | ||||||
|   const selectableItemIds = copilotCommands |   const selectableItemIds = copilotCommands | ||||||
|     .map((cmd) => cmd.id) |     .map((cmd) => cmd.id) | ||||||
|  |     .concat(matchingActionCommands.map((cmd) => cmd.id)) | ||||||
|     .concat(matchingCreateCommand.map((cmd) => cmd.id)) |     .concat(matchingCreateCommand.map((cmd) => cmd.id)) | ||||||
|     .concat(matchingNavigateCommand.map((cmd) => cmd.id)) |     .concat(matchingNavigateCommand.map((cmd) => cmd.id)) | ||||||
|     .concat(people?.map((person) => person.id)) |     .concat(people?.map((person) => person.id)) | ||||||
| @@ -320,22 +330,28 @@ export const CommandMenu = () => { | |||||||
|     .concat(notes?.map((note) => note.id)); |     .concat(notes?.map((note) => note.id)); | ||||||
|  |  | ||||||
|   const isNoResults = |   const isNoResults = | ||||||
|  |     !matchingActionCommands.length && | ||||||
|     !matchingCreateCommand.length && |     !matchingCreateCommand.length && | ||||||
|     !matchingNavigateCommand.length && |     !matchingNavigateCommand.length && | ||||||
|     !people?.length && |     !people?.length && | ||||||
|     !companies?.length && |     !companies?.length && | ||||||
|     !notes?.length && |     !notes?.length && | ||||||
|     !opportunities?.length; |     !opportunities?.length; | ||||||
|  |  | ||||||
|   const isLoading = |   const isLoading = | ||||||
|     isPeopleLoading || |     isPeopleLoading || | ||||||
|     isNotesLoading || |     isNotesLoading || | ||||||
|     isOpportunitiesLoading || |     isOpportunitiesLoading || | ||||||
|     isCompaniesLoading; |     isCompaniesLoading; | ||||||
|  |  | ||||||
|  |   const mainContextStoreComponentInstanceId = useRecoilValue( | ||||||
|  |     mainContextStoreComponentInstanceIdState, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       {isCommandMenuOpened && ( |       {isCommandMenuOpened && ( | ||||||
|         <StyledCommandMenu ref={commandMenuRef}> |         <StyledCommandMenu ref={commandMenuRef} className="command-menu"> | ||||||
|           <StyledInputContainer> |           <StyledInputContainer> | ||||||
|             <StyledInput |             <StyledInput | ||||||
|               autoFocus |               autoFocus | ||||||
| @@ -393,6 +409,23 @@ export const CommandMenu = () => { | |||||||
|                       </SelectableItem> |                       </SelectableItem> | ||||||
|                     </CommandGroup> |                     </CommandGroup> | ||||||
|                   )} |                   )} | ||||||
|  |                   {mainContextStoreComponentInstanceId && ( | ||||||
|  |                     <CommandGroup heading="Actions"> | ||||||
|  |                       {matchingActionCommands?.map((actionCommand) => ( | ||||||
|  |                         <SelectableItem | ||||||
|  |                           itemId={actionCommand.id} | ||||||
|  |                           key={actionCommand.id} | ||||||
|  |                         > | ||||||
|  |                           <CommandMenuItem | ||||||
|  |                             id={actionCommand.id} | ||||||
|  |                             label={actionCommand.label} | ||||||
|  |                             Icon={actionCommand.Icon} | ||||||
|  |                             onClick={actionCommand.onCommandClick} | ||||||
|  |                           /> | ||||||
|  |                         </SelectableItem> | ||||||
|  |                       ))} | ||||||
|  |                     </CommandGroup> | ||||||
|  |                   )} | ||||||
|                   <CommandGroup heading="Create"> |                   <CommandGroup heading="Create"> | ||||||
|                     {matchingCreateCommand.map((cmd) => ( |                     {matchingCreateCommand.map((cmd) => ( | ||||||
|                       <SelectableItem itemId={cmd.id} key={cmd.id}> |                       <SelectableItem itemId={cmd.id} key={cmd.id}> | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { isNonEmptyString } from '@sniptt/guards'; | import { isNonEmptyString } from '@sniptt/guards'; | ||||||
| import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| import { useRecoilCallback, useSetRecoilState } from 'recoil'; | import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil'; | ||||||
|  |  | ||||||
| import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState'; | import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState'; | ||||||
| import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; | import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; | ||||||
| @@ -9,7 +9,9 @@ import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousH | |||||||
| import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope'; | import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope'; | ||||||
| import { isDefined } from '~/utils/isDefined'; | import { isDefined } from '~/utils/isDefined'; | ||||||
|  |  | ||||||
|  | import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector'; | ||||||
| import { COMMAND_MENU_COMMANDS } from '@/command-menu/constants/CommandMenuCommands'; | import { COMMAND_MENU_COMMANDS } from '@/command-menu/constants/CommandMenuCommands'; | ||||||
|  | import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; | ||||||
| import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; | import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; | ||||||
| import { ALL_ICONS } from '@ui/display/icon/providers/internal/AllIcons'; | import { ALL_ICONS } from '@ui/display/icon/providers/internal/AllIcons'; | ||||||
| import { sortByProperty } from '~/utils/array/sortByProperty'; | import { sortByProperty } from '~/utils/array/sortByProperty'; | ||||||
| @@ -27,10 +29,43 @@ export const useCommandMenu = () => { | |||||||
|     goBackToPreviousHotkeyScope, |     goBackToPreviousHotkeyScope, | ||||||
|   } = usePreviousHotkeyScope(); |   } = usePreviousHotkeyScope(); | ||||||
|  |  | ||||||
|   const openCommandMenu = useCallback(() => { |   const mainContextStoreComponentInstanceId = useRecoilValue( | ||||||
|  |     mainContextStoreComponentInstanceIdState, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   const openCommandMenu = useRecoilCallback( | ||||||
|  |     ({ snapshot }) => | ||||||
|  |       () => { | ||||||
|  |         if (isDefined(mainContextStoreComponentInstanceId)) { | ||||||
|  |           const actionMenuEntries = snapshot.getLoadable( | ||||||
|  |             actionMenuEntriesComponentSelector.selectorFamily({ | ||||||
|  |               instanceId: mainContextStoreComponentInstanceId, | ||||||
|  |             }), | ||||||
|  |           ); | ||||||
|  |  | ||||||
|  |           const actionCommands = actionMenuEntries | ||||||
|  |             .getValue() | ||||||
|  |             ?.map((actionMenuEntry) => ({ | ||||||
|  |               id: actionMenuEntry.key, | ||||||
|  |               label: actionMenuEntry.label, | ||||||
|  |               Icon: actionMenuEntry.Icon, | ||||||
|  |               onCommandClick: actionMenuEntry.onClick, | ||||||
|  |               type: CommandType.Action, | ||||||
|  |             })); | ||||||
|  |  | ||||||
|  |           setCommands(actionCommands); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         setIsCommandMenuOpened(true); |         setIsCommandMenuOpened(true); | ||||||
|         setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenuOpen); |         setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenuOpen); | ||||||
|   }, [setHotkeyScopeAndMemorizePreviousScope, setIsCommandMenuOpened]); |       }, | ||||||
|  |     [ | ||||||
|  |       mainContextStoreComponentInstanceId, | ||||||
|  |       setCommands, | ||||||
|  |       setHotkeyScopeAndMemorizePreviousScope, | ||||||
|  |       setIsCommandMenuOpened, | ||||||
|  |     ], | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   const closeCommandMenu = useRecoilCallback( |   const closeCommandMenu = useRecoilCallback( | ||||||
|     ({ snapshot }) => |     ({ snapshot }) => | ||||||
|   | |||||||
| @@ -3,13 +3,14 @@ import { IconComponent } from 'twenty-ui'; | |||||||
| export enum CommandType { | export enum CommandType { | ||||||
|   Navigate = 'Navigate', |   Navigate = 'Navigate', | ||||||
|   Create = 'Create', |   Create = 'Create', | ||||||
|  |   Action = 'Action', | ||||||
| } | } | ||||||
|  |  | ||||||
| export type Command = { | export type Command = { | ||||||
|   id: string; |   id: string; | ||||||
|   to: string; |   to?: string; | ||||||
|   label: string; |   label: string; | ||||||
|   type: CommandType.Navigate | CommandType.Create; |   type: CommandType.Navigate | CommandType.Create | CommandType.Action; | ||||||
|   Icon?: IconComponent; |   Icon?: IconComponent; | ||||||
|   firstHotKey?: string; |   firstHotKey?: string; | ||||||
|   secondHotKey?: string; |   secondHotKey?: string; | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { mainContextStoreComponentInstanceIdState } from '@/context-store/states | |||||||
| import { useContext, useEffect } from 'react'; | import { useContext, useEffect } from 'react'; | ||||||
| import { useSetRecoilState } from 'recoil'; | import { useSetRecoilState } from 'recoil'; | ||||||
| 
 | 
 | ||||||
| export const SetMainContextStoreComponentInstanceIdEffect = () => { | export const MainContextStoreComponentInstanceIdSetterEffect = () => { | ||||||
|   const setMainContextStoreComponentInstanceId = useSetRecoilState( |   const setMainContextStoreComponentInstanceId = useSetRecoilState( | ||||||
|     mainContextStoreComponentInstanceIdState, |     mainContextStoreComponentInstanceIdState, | ||||||
|   ); |   ); | ||||||
| @@ -71,7 +71,7 @@ export const RecordBoard = () => { | |||||||
|  |  | ||||||
|   useListenClickOutsideByClassName({ |   useListenClickOutsideByClassName({ | ||||||
|     classNames: ['record-board-card'], |     classNames: ['record-board-card'], | ||||||
|     excludeClassNames: ['bottom-bar', 'action-menu-dropdown'], |     excludeClassNames: ['bottom-bar', 'action-menu-dropdown', 'command-menu'], | ||||||
|     callback: resetRecordSelection, |     callback: resetRecordSelection, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -206,6 +206,7 @@ export const RecordIndexContainer = () => { | |||||||
|             viewBarId={recordIndexId} |             viewBarId={recordIndexId} | ||||||
|           /> |           /> | ||||||
|         </SpreadsheetImportProvider> |         </SpreadsheetImportProvider> | ||||||
|  |  | ||||||
|         {recordIndexViewType === ViewType.Table && ( |         {recordIndexViewType === ViewType.Table && ( | ||||||
|           <> |           <> | ||||||
|             <RecordIndexTableContainer |             <RecordIndexTableContainer | ||||||
| @@ -232,7 +233,7 @@ export const RecordIndexContainer = () => { | |||||||
|             /> |             /> | ||||||
|           </StyledContainerWithPadding> |           </StyledContainerWithPadding> | ||||||
|         )} |         )} | ||||||
|         <RecordIndexActionMenu actionMenuId={recordIndexId} /> |         <RecordIndexActionMenu /> | ||||||
|       </RecordFieldValueSelectorContextProvider> |       </RecordFieldValueSelectorContextProvider> | ||||||
|     </StyledContainer> |     </StyledContainer> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| import { useRecoilValue } from 'recoil'; | import { useRecoilValue } from 'recoil'; | ||||||
|  |  | ||||||
|  | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
|  | import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; | ||||||
| import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading'; | import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading'; | ||||||
| import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; | import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; | ||||||
| import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; | import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; | ||||||
| @@ -38,6 +40,14 @@ export const RightDrawerRecord = () => { | |||||||
|   ); |   ); | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|  |     <ContextStoreComponentInstanceContext.Provider | ||||||
|  |       value={{ | ||||||
|  |         instanceId: `record-show-${objectRecordId}`, | ||||||
|  |       }} | ||||||
|  |     > | ||||||
|  |       <ActionMenuComponentInstanceContext.Provider | ||||||
|  |         value={{ instanceId: `record-show-${objectRecordId}` }} | ||||||
|  |       > | ||||||
|         <StyledRightDrawerRecord> |         <StyledRightDrawerRecord> | ||||||
|           <RecordFieldValueSelectorContextProvider> |           <RecordFieldValueSelectorContextProvider> | ||||||
|             {!isNewViewableRecordLoading && ( |             {!isNewViewableRecordLoading && ( | ||||||
| @@ -52,5 +62,7 @@ export const RightDrawerRecord = () => { | |||||||
|             /> |             /> | ||||||
|           </RecordFieldValueSelectorContextProvider> |           </RecordFieldValueSelectorContextProvider> | ||||||
|         </StyledRightDrawerRecord> |         </StyledRightDrawerRecord> | ||||||
|  |       </ActionMenuComponentInstanceContext.Provider> | ||||||
|  |     </ContextStoreComponentInstanceContext.Provider> | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,10 +1,11 @@ | |||||||
| import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | ||||||
| import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer'; | import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer'; | ||||||
|  |  | ||||||
| import { SetMainContextStoreComponentInstanceIdEffect } from '@/context-store/components/SetMainContextStoreComponentInstanceIdEffect'; | import { MainContextStoreComponentInstanceIdSetterEffect } from '@/context-store/components/MainContextStoreComponentInstanceIdSetterEffect'; | ||||||
| import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; |  | ||||||
| import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord'; | import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord'; | ||||||
| import { RecordShowContainerContextStoreEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreEffect'; |  | ||||||
|  | import { RecordShowContainerContextStoreObjectMetadataIdEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect'; | ||||||
|  | import { RecordShowContainerContextStoreTargetedRecordsEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreTargetedRecordsEffect'; | ||||||
| import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData'; | import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData'; | ||||||
| import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs'; | import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs'; | ||||||
| import { ShowPageSubContainer } from '@/ui/layout/show-page/components/ShowPageSubContainer'; | import { ShowPageSubContainer } from '@/ui/layout/show-page/components/ShowPageSubContainer'; | ||||||
| @@ -41,16 +42,15 @@ export const RecordShowContainer = ({ | |||||||
|   ); |   ); | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <ContextStoreComponentInstanceContext.Provider |     <> | ||||||
|       value={{ |       <RecordShowContainerContextStoreObjectMetadataIdEffect | ||||||
|         instanceId: 'record-show', |  | ||||||
|       }} |  | ||||||
|     > |  | ||||||
|       <RecordShowContainerContextStoreEffect |  | ||||||
|         recordId={objectRecordId} |         recordId={objectRecordId} | ||||||
|         objectNameSingular={objectNameSingular} |         objectNameSingular={objectNameSingular} | ||||||
|       /> |       /> | ||||||
|       {!isInRightDrawer && <SetMainContextStoreComponentInstanceIdEffect />} |       <RecordShowContainerContextStoreTargetedRecordsEffect | ||||||
|  |         recordId={objectRecordId} | ||||||
|  |       /> | ||||||
|  |       {!isInRightDrawer && <MainContextStoreComponentInstanceIdSetterEffect />} | ||||||
|       {recordFromStore && recordFromStore.deletedAt && ( |       {recordFromStore && recordFromStore.deletedAt && ( | ||||||
|         <InformationBannerDeletedRecord |         <InformationBannerDeletedRecord | ||||||
|           recordId={objectRecordId} |           recordId={objectRecordId} | ||||||
| @@ -69,6 +69,6 @@ export const RecordShowContainer = ({ | |||||||
|           isNewRightDrawerItemLoading={isNewRightDrawerItemLoading} |           isNewRightDrawerItemLoading={isNewRightDrawerItemLoading} | ||||||
|         /> |         /> | ||||||
|       </ShowPageContainer> |       </ShowPageContainer> | ||||||
|     </ContextStoreComponentInstanceContext.Provider> |     </> | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; | ||||||
|  | import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; | ||||||
|  | import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; | ||||||
|  | import { useEffect } from 'react'; | ||||||
|  |  | ||||||
|  | export const RecordShowContainerContextStoreObjectMetadataIdEffect = ({ | ||||||
|  |   recordId, | ||||||
|  |   objectNameSingular, | ||||||
|  | }: { | ||||||
|  |   recordId: string; | ||||||
|  |   objectNameSingular: string; | ||||||
|  | }) => { | ||||||
|  |   const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2( | ||||||
|  |     contextStoreCurrentObjectMetadataIdComponentState, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   const { objectMetadataItem } = useObjectMetadataItem({ | ||||||
|  |     objectNameSingular: objectNameSingular, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   useEffect(() => { | ||||||
|  |     setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id); | ||||||
|  |  | ||||||
|  |     return () => { | ||||||
|  |       setContextStoreCurrentObjectMetadataId(null); | ||||||
|  |     }; | ||||||
|  |   }, [recordId, setContextStoreCurrentObjectMetadataId, objectMetadataItem.id]); | ||||||
|  |  | ||||||
|  |   return null; | ||||||
|  | }; | ||||||
| @@ -1,29 +1,17 @@ | |||||||
| import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; |  | ||||||
| import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; | ||||||
| import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; | import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; | ||||||
| import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; |  | ||||||
| import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; | import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; | ||||||
| import { useEffect } from 'react'; | import { useEffect } from 'react'; | ||||||
| 
 | 
 | ||||||
| export const RecordShowContainerContextStoreEffect = ({ | export const RecordShowContainerContextStoreTargetedRecordsEffect = ({ | ||||||
|   recordId, |   recordId, | ||||||
|   objectNameSingular, |  | ||||||
| }: { | }: { | ||||||
|   recordId: string; |   recordId: string; | ||||||
|   objectNameSingular: string; |  | ||||||
| }) => { | }) => { | ||||||
|   const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2( |   const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2( | ||||||
|     contextStoreTargetedRecordsRuleComponentState, |     contextStoreTargetedRecordsRuleComponentState, | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2( |  | ||||||
|     contextStoreCurrentObjectMetadataIdComponentState, |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   const { objectMetadataItem } = useObjectMetadataItem({ |  | ||||||
|     objectNameSingular: objectNameSingular, |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2( |   const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2( | ||||||
|     contextStoreNumberOfSelectedRecordsComponentState, |     contextStoreNumberOfSelectedRecordsComponentState, | ||||||
|   ); |   ); | ||||||
| @@ -33,7 +21,6 @@ export const RecordShowContainerContextStoreEffect = ({ | |||||||
|       mode: 'selection', |       mode: 'selection', | ||||||
|       selectedRecordIds: [recordId], |       selectedRecordIds: [recordId], | ||||||
|     }); |     }); | ||||||
|     setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id); |  | ||||||
|     setContextStoreNumberOfSelectedRecords(1); |     setContextStoreNumberOfSelectedRecords(1); | ||||||
| 
 | 
 | ||||||
|     return () => { |     return () => { | ||||||
| @@ -41,14 +28,11 @@ export const RecordShowContainerContextStoreEffect = ({ | |||||||
|         mode: 'selection', |         mode: 'selection', | ||||||
|         selectedRecordIds: [], |         selectedRecordIds: [], | ||||||
|       }); |       }); | ||||||
|       setContextStoreCurrentObjectMetadataId(null); |  | ||||||
|       setContextStoreNumberOfSelectedRecords(0); |       setContextStoreNumberOfSelectedRecords(0); | ||||||
|     }; |     }; | ||||||
|   }, [ |   }, [ | ||||||
|     recordId, |     recordId, | ||||||
|     setContextStoreTargetedRecordsRule, |     setContextStoreTargetedRecordsRule, | ||||||
|     setContextStoreCurrentObjectMetadataId, |  | ||||||
|     objectMetadataItem?.id, |  | ||||||
|     setContextStoreNumberOfSelectedRecords, |     setContextStoreNumberOfSelectedRecords, | ||||||
|   ]); |   ]); | ||||||
| 
 | 
 | ||||||
| @@ -27,7 +27,7 @@ export const RecordTableInternalEffect = ({ | |||||||
|  |  | ||||||
|   useListenClickOutsideByClassName({ |   useListenClickOutsideByClassName({ | ||||||
|     classNames: ['entity-table-cell'], |     classNames: ['entity-table-cell'], | ||||||
|     excludeClassNames: ['bottom-bar', 'action-menu-dropdown'], |     excludeClassNames: ['bottom-bar', 'action-menu-dropdown', 'command-menu'], | ||||||
|     callback: () => { |     callback: () => { | ||||||
|       leaveTableFocus(); |       leaveTableFocus(); | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -1,11 +1,13 @@ | |||||||
| import { useRecoilCallback } from 'recoil'; | import { useRecoilCallback } from 'recoil'; | ||||||
|  |  | ||||||
|  | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
| import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState'; | import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState'; | ||||||
| import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; | import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; | ||||||
| import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState'; | import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState'; | ||||||
| import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; | import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; | ||||||
| import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId'; | import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId'; | ||||||
| import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; | import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; | ||||||
|  | import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; | ||||||
| import { extractComponentFamilyState } from '@/ui/utilities/state/component-state/utils/extractComponentFamilyState'; | import { extractComponentFamilyState } from '@/ui/utilities/state/component-state/utils/extractComponentFamilyState'; | ||||||
| import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; | import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; | ||||||
|  |  | ||||||
| @@ -14,6 +16,10 @@ export const useTriggerActionMenuDropdown = ({ | |||||||
| }: { | }: { | ||||||
|   recordTableId: string; |   recordTableId: string; | ||||||
| }) => { | }) => { | ||||||
|  |   const actionMenuInstanceId = useAvailableComponentInstanceIdOrThrow( | ||||||
|  |     ActionMenuComponentInstanceContext, | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   const triggerActionMenuDropdown = useRecoilCallback( |   const triggerActionMenuDropdown = useRecoilCallback( | ||||||
|     ({ set, snapshot }) => |     ({ set, snapshot }) => | ||||||
|       (event: React.MouseEvent, recordId: string) => { |       (event: React.MouseEvent, recordId: string) => { | ||||||
| @@ -24,7 +30,7 @@ export const useTriggerActionMenuDropdown = ({ | |||||||
|         set( |         set( | ||||||
|           extractComponentState( |           extractComponentState( | ||||||
|             recordIndexActionMenuDropdownPositionComponentState, |             recordIndexActionMenuDropdownPositionComponentState, | ||||||
|             `action-menu-dropdown-${recordTableId}`, |             `action-menu-dropdown-${actionMenuInstanceId}`, | ||||||
|           ), |           ), | ||||||
|           { |           { | ||||||
|             x: event.clientX, |             x: event.clientX, | ||||||
| @@ -48,19 +54,19 @@ export const useTriggerActionMenuDropdown = ({ | |||||||
|  |  | ||||||
|         const isActionMenuDropdownOpenState = extractComponentState( |         const isActionMenuDropdownOpenState = extractComponentState( | ||||||
|           isDropdownOpenComponentState, |           isDropdownOpenComponentState, | ||||||
|           `action-menu-dropdown-${recordTableId}`, |           `action-menu-dropdown-${actionMenuInstanceId}`, | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         const isActionBarOpenState = isBottomBarOpenedComponentState.atomFamily( |         const isActionBarOpenState = isBottomBarOpenedComponentState.atomFamily( | ||||||
|           { |           { | ||||||
|             instanceId: `action-bar-${recordTableId}`, |             instanceId: `action-bar-${actionMenuInstanceId}`, | ||||||
|           }, |           }, | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         set(isActionBarOpenState, false); |         set(isActionBarOpenState, false); | ||||||
|         set(isActionMenuDropdownOpenState, true); |         set(isActionMenuDropdownOpenState, true); | ||||||
|       }, |       }, | ||||||
|     [recordTableId], |     [actionMenuInstanceId, recordTableId], | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|   return { triggerActionMenuDropdown }; |   return { triggerActionMenuDropdown }; | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| import styled from '@emotion/styled'; | import styled from '@emotion/styled'; | ||||||
|  |  | ||||||
|  | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
|  | import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; | ||||||
| import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; | import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers'; | ||||||
| import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect'; | import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect'; | ||||||
| import { ViewBar } from '@/views/components/ViewBar'; | import { ViewBar } from '@/views/components/ViewBar'; | ||||||
| @@ -21,6 +23,14 @@ export const SignInBackgroundMockContainer = () => { | |||||||
|   return ( |   return ( | ||||||
|     <StyledContainer> |     <StyledContainer> | ||||||
|       <ViewComponentInstanceContext.Provider value={{ instanceId: viewBarId }}> |       <ViewComponentInstanceContext.Provider value={{ instanceId: viewBarId }}> | ||||||
|  |         <ContextStoreComponentInstanceContext.Provider | ||||||
|  |           value={{ | ||||||
|  |             instanceId: recordIndexId, | ||||||
|  |           }} | ||||||
|  |         > | ||||||
|  |           <ActionMenuComponentInstanceContext.Provider | ||||||
|  |             value={{ instanceId: recordIndexId }} | ||||||
|  |           > | ||||||
|             <ViewBar |             <ViewBar | ||||||
|               viewBarId={viewBarId} |               viewBarId={viewBarId} | ||||||
|               onCurrentViewChange={async () => {}} |               onCurrentViewChange={async () => {}} | ||||||
| @@ -37,6 +47,8 @@ export const SignInBackgroundMockContainer = () => { | |||||||
|               viewBarId={viewBarId} |               viewBarId={viewBarId} | ||||||
|               updateRecordMutation={() => {}} |               updateRecordMutation={() => {}} | ||||||
|             /> |             /> | ||||||
|  |           </ActionMenuComponentInstanceContext.Provider> | ||||||
|  |         </ContextStoreComponentInstanceContext.Provider> | ||||||
|       </ViewComponentInstanceContext.Provider> |       </ViewComponentInstanceContext.Provider> | ||||||
|     </StyledContainer> |     </StyledContainer> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -219,6 +219,7 @@ export const Modal = ({ | |||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <StyledBackDrop |     <StyledBackDrop | ||||||
|  |       className="modal-backdrop" | ||||||
|       onMouseDown={stopEventPropagation} |       onMouseDown={stopEventPropagation} | ||||||
|       modalVariant={modalVariant} |       modalVariant={modalVariant} | ||||||
|     > |     > | ||||||
|   | |||||||
| @@ -47,6 +47,10 @@ const StyledContainer = styled(motion.div)<{ isRightDrawerMinimized: boolean }>` | |||||||
|   right: 0; |   right: 0; | ||||||
|   top: 0; |   top: 0; | ||||||
|   z-index: 100; |   z-index: 100; | ||||||
|  |  | ||||||
|  |   .modal-backdrop { | ||||||
|  |     background: ${({ theme }) => theme.background.overlayTertiary}; | ||||||
|  |   } | ||||||
| `; | `; | ||||||
|  |  | ||||||
| const StyledRightDrawer = styled.div` | const StyledRightDrawer = styled.div` | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { RecordShowActionMenu } from '@/action-menu/components/RecordShowActionMenu'; | import { RecordShowRightDrawerActionMenu } from '@/action-menu/components/RecordShowRightDrawerActionMenu'; | ||||||
| import { Calendar } from '@/activities/calendar/components/Calendar'; | import { Calendar } from '@/activities/calendar/components/Calendar'; | ||||||
| import { EmailThreads } from '@/activities/emails/components/EmailThreads'; | import { EmailThreads } from '@/activities/emails/components/EmailThreads'; | ||||||
| import { Attachments } from '@/activities/files/components/Attachments'; | import { Attachments } from '@/activities/files/components/Attachments'; | ||||||
| @@ -221,7 +221,7 @@ export const ShowPageSubContainer = ({ | |||||||
|         </StyledContentContainer> |         </StyledContentContainer> | ||||||
|         {isInRightDrawer && recordFromStore && !recordFromStore.deletedAt && ( |         {isInRightDrawer && recordFromStore && !recordFromStore.deletedAt && ( | ||||||
|           <StyledButtonContainer> |           <StyledButtonContainer> | ||||||
|             <RecordShowActionMenu actionMenuId={'right-drawer-action-menu'} /> |             <RecordShowRightDrawerActionMenu /> | ||||||
|           </StyledButtonContainer> |           </StyledButtonContainer> | ||||||
|         )} |         )} | ||||||
|       </StyledShowPageRightContainer> |       </StyledShowPageRightContainer> | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| import styled from '@emotion/styled'; | import styled from '@emotion/styled'; | ||||||
| import { useParams } from 'react-router-dom'; | import { useParams } from 'react-router-dom'; | ||||||
|  |  | ||||||
| import { SetMainContextStoreComponentInstanceIdEffect } from '@/context-store/components/SetMainContextStoreComponentInstanceIdEffect'; | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
|  | import { MainContextStoreComponentInstanceIdSetterEffect } from '@/context-store/components/MainContextStoreComponentInstanceIdSetterEffect'; | ||||||
| import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; | import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; | ||||||
| import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; | import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; | ||||||
| import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; | import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; | ||||||
| @@ -81,13 +82,19 @@ export const RecordIndexPage = () => { | |||||||
|             <StyledIndexContainer> |             <StyledIndexContainer> | ||||||
|               <ContextStoreComponentInstanceContext.Provider |               <ContextStoreComponentInstanceContext.Provider | ||||||
|                 value={{ |                 value={{ | ||||||
|                   instanceId: 'record-index', |                   instanceId: `record-index-${objectMetadataItem.id}`, | ||||||
|  |                 }} | ||||||
|  |               > | ||||||
|  |                 <ActionMenuComponentInstanceContext.Provider | ||||||
|  |                   value={{ | ||||||
|  |                     instanceId: `record-index-${objectMetadataItem.id}`, | ||||||
|                   }} |                   }} | ||||||
|                 > |                 > | ||||||
|                   <RecordIndexContainerContextStoreObjectMetadataEffect /> |                   <RecordIndexContainerContextStoreObjectMetadataEffect /> | ||||||
|                   <RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect /> |                   <RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect /> | ||||||
|                 <SetMainContextStoreComponentInstanceIdEffect /> |                   <MainContextStoreComponentInstanceIdSetterEffect /> | ||||||
|                   <RecordIndexContainer /> |                   <RecordIndexContainer /> | ||||||
|  |                 </ActionMenuComponentInstanceContext.Provider> | ||||||
|               </ContextStoreComponentInstanceContext.Provider> |               </ContextStoreComponentInstanceContext.Provider> | ||||||
|             </StyledIndexContainer> |             </StyledIndexContainer> | ||||||
|           </PageBody> |           </PageBody> | ||||||
|   | |||||||
| @@ -1,6 +1,9 @@ | |||||||
| import { useParams } from 'react-router-dom'; | import { useParams } from 'react-router-dom'; | ||||||
|  |  | ||||||
|  | import { RecordShowActionMenu } from '@/action-menu/components/RecordShowActionMenu'; | ||||||
|  | import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; | ||||||
| import { TimelineActivityContext } from '@/activities/timeline-activities/contexts/TimelineActivityContext'; | import { TimelineActivityContext } from '@/activities/timeline-activities/contexts/TimelineActivityContext'; | ||||||
|  | import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; | ||||||
| import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | ||||||
| import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; | import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; | ||||||
| import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage'; | import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage'; | ||||||
| @@ -11,7 +14,6 @@ import { PageContainer } from '@/ui/layout/page/components/PageContainer'; | |||||||
| import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle'; | import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle'; | ||||||
| import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader'; | import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader'; | ||||||
| import { RecordShowPageWorkflowVersionHeader } from '@/workflow/components/RecordShowPageWorkflowVersionHeader'; | import { RecordShowPageWorkflowVersionHeader } from '@/workflow/components/RecordShowPageWorkflowVersionHeader'; | ||||||
| import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader'; |  | ||||||
| import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader'; | import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader'; | ||||||
|  |  | ||||||
| export const RecordShowPage = () => { | export const RecordShowPage = () => { | ||||||
| @@ -38,6 +40,14 @@ export const RecordShowPage = () => { | |||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <RecordFieldValueSelectorContextProvider> |     <RecordFieldValueSelectorContextProvider> | ||||||
|  |       <ContextStoreComponentInstanceContext.Provider | ||||||
|  |         value={{ | ||||||
|  |           instanceId: `record-show-${objectRecordId}`, | ||||||
|  |         }} | ||||||
|  |       > | ||||||
|  |         <ActionMenuComponentInstanceContext.Provider | ||||||
|  |           value={{ instanceId: `record-show-${objectRecordId}` }} | ||||||
|  |         > | ||||||
|           <RecordValueSetterEffect recordId={objectRecordId} /> |           <RecordValueSetterEffect recordId={objectRecordId} /> | ||||||
|           <PageContainer> |           <PageContainer> | ||||||
|             <PageTitle title={pageTitle} /> |             <PageTitle title={pageTitle} /> | ||||||
| @@ -55,7 +65,8 @@ export const RecordShowPage = () => { | |||||||
|                     workflowVersionId={objectRecordId} |                     workflowVersionId={objectRecordId} | ||||||
|                   /> |                   /> | ||||||
|                 ) : ( |                 ) : ( | ||||||
|               <RecordShowPageBaseHeader |                   <> | ||||||
|  |                     <RecordShowActionMenu | ||||||
|                       {...{ |                       {...{ | ||||||
|                         isFavorite, |                         isFavorite, | ||||||
|                         handleFavoriteButtonClick, |                         handleFavoriteButtonClick, | ||||||
| @@ -64,6 +75,7 @@ export const RecordShowPage = () => { | |||||||
|                         objectNameSingular, |                         objectNameSingular, | ||||||
|                       }} |                       }} | ||||||
|                     /> |                     /> | ||||||
|  |                   </> | ||||||
|                 )} |                 )} | ||||||
|               </> |               </> | ||||||
|             </RecordShowPageHeader> |             </RecordShowPageHeader> | ||||||
| @@ -81,6 +93,8 @@ export const RecordShowPage = () => { | |||||||
|               </TimelineActivityContext.Provider> |               </TimelineActivityContext.Provider> | ||||||
|             </PageBody> |             </PageBody> | ||||||
|           </PageContainer> |           </PageContainer> | ||||||
|  |         </ActionMenuComponentInstanceContext.Provider> | ||||||
|  |       </ContextStoreComponentInstanceContext.Provider> | ||||||
|     </RecordFieldValueSelectorContextProvider> |     </RecordFieldValueSelectorContextProvider> | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Raphaël Bosi
					Raphaël Bosi