Display and update aggregate queries in kanban views (#8833)
Closes #8752, #8753, #8754 Implements usage of aggregate queries in kanban views. https://github.com/user-attachments/assets/732590ca-2785-4c57-82d5-d999a2279e92 TO DO 1. write tests + storybook 2. Fix values displayed should have the same format as defined in number fields + Fix display for amountMicros --------- Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -1,13 +1,15 @@
|
||||
import { DROPDOWN_OFFSET_Y } from '@/dropdown/constants/DropdownOffsetY';
|
||||
import { DROPDOWN_WIDTH } from '@/dropdown/constants/DropdownWidth';
|
||||
import { useCurrentContentId } from '@/dropdown/hooks/useCurrentContentId';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { ObjectOptionsDropdownButton } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownButton';
|
||||
import { ObjectOptionsDropdownContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownContent';
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
|
||||
import { ObjectOptionsContentId } from '@/object-record/object-options-dropdown/types/ObjectOptionsContentId';
|
||||
import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
type ObjectOptionsDropdownProps = {
|
||||
viewType: ViewType;
|
||||
@ -20,24 +22,18 @@ export const ObjectOptionsDropdown = ({
|
||||
objectMetadataItem,
|
||||
viewType,
|
||||
}: ObjectOptionsDropdownProps) => {
|
||||
const [currentContentId, setCurrentContentId] =
|
||||
useState<ObjectOptionsContentId | null>(null);
|
||||
|
||||
const handleContentChange = useCallback((key: ObjectOptionsContentId) => {
|
||||
setCurrentContentId(key);
|
||||
}, []);
|
||||
|
||||
const handleResetContent = useCallback(() => {
|
||||
setCurrentContentId(null);
|
||||
}, []);
|
||||
const { currentContentId, handleContentChange, handleResetContent } =
|
||||
useCurrentContentId<ObjectOptionsContentId>();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
dropdownId={OBJECT_OPTIONS_DROPDOWN_ID}
|
||||
clickableComponent={<ObjectOptionsDropdownButton />}
|
||||
dropdownMenuWidth={'200px'}
|
||||
dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
dropdownMenuWidth={DROPDOWN_WIDTH}
|
||||
dropdownOffset={{ y: DROPDOWN_OFFSET_Y }}
|
||||
clickableComponent={
|
||||
<StyledHeaderDropdownButton>Options</StyledHeaderDropdownButton>
|
||||
}
|
||||
dropdownComponents={
|
||||
<ObjectOptionsDropdownContext.Provider
|
||||
value={{
|
||||
@ -47,6 +43,7 @@ export const ObjectOptionsDropdown = ({
|
||||
currentContentId,
|
||||
onContentChange: handleContentChange,
|
||||
resetContent: handleResetContent,
|
||||
dropdownId: OBJECT_OPTIONS_DROPDOWN_ID,
|
||||
}}
|
||||
>
|
||||
<ObjectOptionsDropdownContent />
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
export const ObjectOptionsDropdownButton = () => {
|
||||
const { isDropdownOpen, toggleDropdown } = useDropdown(
|
||||
OBJECT_OPTIONS_DROPDOWN_ID,
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledHeaderDropdownButton
|
||||
isUnfolded={isDropdownOpen}
|
||||
onClick={toggleDropdown}
|
||||
>
|
||||
Options
|
||||
</StyledHeaderDropdownButton>
|
||||
);
|
||||
};
|
||||
@ -4,6 +4,7 @@ import { ComponentDecorator } from 'twenty-ui';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { ObjectOptionsDropdownContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownContent';
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
|
||||
import { ObjectOptionsContentId } from '@/object-record/object-options-dropdown/types/ObjectOptionsContentId';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
@ -94,6 +95,7 @@ const createStory = (contentId: ObjectOptionsContentId | null): Story => ({
|
||||
currentContentId: contentId,
|
||||
onContentChange: () => {},
|
||||
resetContent: () => {},
|
||||
dropdownId: OBJECT_OPTIONS_DROPDOWN_ID,
|
||||
}}
|
||||
>
|
||||
<DropdownMenu>
|
||||
|
||||
@ -2,6 +2,7 @@ import { renderHook } from '@testing-library/react';
|
||||
import { act } from 'react';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
@ -55,6 +56,7 @@ describe('useOptionsDropdown', () => {
|
||||
currentContentId: 'recordGroups',
|
||||
onContentChange: mockOnContentChange,
|
||||
resetContent: mockResetContent,
|
||||
dropdownId: OBJECT_OPTIONS_DROPDOWN_ID,
|
||||
...contextValue,
|
||||
}}
|
||||
>
|
||||
|
||||
@ -1,26 +1,20 @@
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useContext } from 'react';
|
||||
|
||||
export const useOptionsDropdown = () => {
|
||||
const { closeDropdown } = useDropdown(OBJECT_OPTIONS_DROPDOWN_ID);
|
||||
|
||||
const context = useContext(ObjectOptionsDropdownContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useOptionsDropdown must be used within a ObjectOptionsDropdownContext.Provider',
|
||||
);
|
||||
throw new Error('useOptionsDropdown must be used within a context');
|
||||
}
|
||||
|
||||
const handleCloseDropdown = useCallback(() => {
|
||||
context.resetContent();
|
||||
closeDropdown();
|
||||
}, [closeDropdown, context]);
|
||||
const { closeDropdown } = useDropdown({
|
||||
context: ObjectOptionsDropdownContext,
|
||||
});
|
||||
|
||||
return {
|
||||
...context,
|
||||
closeDropdown: handleCloseDropdown,
|
||||
closeDropdown,
|
||||
};
|
||||
};
|
||||
|
||||
@ -10,6 +10,7 @@ export type ObjectOptionsDropdownContextValue = {
|
||||
currentContentId: ObjectOptionsContentId | null;
|
||||
onContentChange: (key: ObjectOptionsContentId) => void;
|
||||
resetContent: () => void;
|
||||
dropdownId: string;
|
||||
};
|
||||
|
||||
export const ObjectOptionsDropdownContext =
|
||||
|
||||
Reference in New Issue
Block a user