mirror of
https://github.com/lingble/twenty.git
synced 2025-10-29 11:52:28 +00:00
create context chip for command menu
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { useContextStoreSelectedRecords } from '@/context-store/hooks/useContextStoreSelectedRecords';
|
||||
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
const StyledChip = styled.div`
|
||||
align-items: center;
|
||||
background: ${({ theme }) => theme.background.transparent.light};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
height: ${({ theme }) => theme.spacing(8)};
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.lg};
|
||||
`;
|
||||
|
||||
export const CommandMenuContextRecordChip = () => {
|
||||
const mainContextStoreComponentInstanceId = useRecoilValue(
|
||||
mainContextStoreComponentInstanceIdState,
|
||||
);
|
||||
|
||||
const { records, loading, totalCount } = useContextStoreSelectedRecords(
|
||||
mainContextStoreComponentInstanceId ?? undefined,
|
||||
);
|
||||
|
||||
if (loading || !totalCount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledChip>
|
||||
{totalCount === 1 ? records[0].name : `${totalCount} records`}
|
||||
</StyledChip>
|
||||
);
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import { CommandMenuContextRecordChip } from '@/command-menu/components/CommandMenuContextRecordChip';
|
||||
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
|
||||
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
@@ -19,6 +20,7 @@ const StyledInputContainer = styled.div`
|
||||
position: relative;
|
||||
|
||||
padding: 0 ${({ theme }) => theme.spacing(COMMAND_MENU_SEARCH_BAR_PADDING)};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const StyledInput = styled.input`
|
||||
@@ -31,7 +33,7 @@ const StyledInput = styled.input`
|
||||
outline: none;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
width: ${({ theme }) => `calc(100% - ${theme.spacing(8)})`};
|
||||
flex: 1;
|
||||
|
||||
&::placeholder {
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
@@ -65,10 +67,11 @@ export const CommandMenuTopBar = ({
|
||||
|
||||
return (
|
||||
<StyledInputContainer>
|
||||
<CommandMenuContextRecordChip />
|
||||
<StyledInput
|
||||
autoFocus
|
||||
value={commandMenuSearch}
|
||||
placeholder="Search"
|
||||
placeholder="Type anything"
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
{!isMobile && (
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useContextStoreCurrentObjectMetadataIdOrThrow = (
|
||||
instanceId?: string,
|
||||
) => {
|
||||
const contextStoreCurrentObjectMetadataIdComponent =
|
||||
useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
if (!contextStoreCurrentObjectMetadataIdComponent) {
|
||||
throw new Error('contextStoreCurrentObjectMetadataIdComponent is not set');
|
||||
}
|
||||
|
||||
return contextStoreCurrentObjectMetadataIdComponent;
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
import { useContextStoreCurrentObjectMetadataIdOrThrow } from '@/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow';
|
||||
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const useContextStoreSelectedRecords = (
|
||||
instanceId?: string,
|
||||
limit = 3,
|
||||
) => {
|
||||
const objectMetadataId =
|
||||
useContextStoreCurrentObjectMetadataIdOrThrow(instanceId);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
objectId: objectMetadataId,
|
||||
});
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const contextStoreFilters = useRecoilComponentValueV2(
|
||||
contextStoreFiltersComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const queryFilter = computeContextStoreFilters(
|
||||
contextStoreTargetedRecordsRule,
|
||||
contextStoreFilters,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
const { records, loading, totalCount } = useFindManyRecords({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
filter: queryFilter,
|
||||
orderBy: [
|
||||
{
|
||||
createdAt: 'DescNullsFirst',
|
||||
},
|
||||
],
|
||||
skip:
|
||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0,
|
||||
limit,
|
||||
});
|
||||
|
||||
return {
|
||||
records,
|
||||
totalCount,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user