mirror of
https://github.com/twentyhq/twenty.git
synced 2024-09-19 20:18:19 +03:00
Create board fields reorder (#2639)
* wip * fields reorder works but fields are not yet persisted * fields are persisted * modify according to comments
This commit is contained in:
parent
532e4342ec
commit
85646a8072
@ -1,6 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
||||
import { mapBoardFieldDefinitionsToViewFields } from '@/companies/utils/mapBoardFieldDefinitionsToViewFields';
|
||||
import { BoardOptionsDropdown } from '@/ui/layout/board/components/BoardOptionsDropdown';
|
||||
import { BoardOptionsDropdownId } from '@/ui/layout/board/components/constants/BoardOptionsDropdownId';
|
||||
import {
|
||||
@ -10,6 +11,7 @@ import {
|
||||
import { EntityBoardActionBar } from '@/ui/layout/board/components/EntityBoardActionBar';
|
||||
import { EntityBoardContextMenu } from '@/ui/layout/board/components/EntityBoardContextMenu';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { useViewFields } from '@/views/hooks/internal/useViewFields';
|
||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
|
||||
|
||||
@ -36,6 +38,8 @@ export const CompanyBoard = ({
|
||||
}: CompanyBoardProps) => {
|
||||
const viewScopeId = 'company-board-view';
|
||||
|
||||
const { persistViewFields } = useViewFields(viewScopeId);
|
||||
|
||||
return (
|
||||
<ViewScope
|
||||
viewScopeId={viewScopeId}
|
||||
@ -47,6 +51,9 @@ export const CompanyBoard = ({
|
||||
<BoardContext.Provider
|
||||
value={{
|
||||
BoardRecoilScopeContext: CompanyBoardRecoilScopeContext,
|
||||
onFieldsChange: (fields) => {
|
||||
persistViewFields(mapBoardFieldDefinitionsToViewFields(fields));
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ViewBar
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
|
||||
import { BoardFieldDefinition } from '@/ui/layout/board/types/BoardFieldDefinition';
|
||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||
|
||||
export const BoardContext = createContext<{
|
||||
BoardRecoilScopeContext: RecoilScopeContext;
|
||||
onFieldsChange: (fields: BoardFieldDefinition<FieldMetadata>[]) => void;
|
||||
}>({
|
||||
BoardRecoilScopeContext: createContext<string | null>(null),
|
||||
onFieldsChange: () => {},
|
||||
});
|
||||
|
@ -0,0 +1,18 @@
|
||||
import { BoardFieldDefinition } from '@/ui/layout/board/types/BoardFieldDefinition';
|
||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { ViewField } from '@/views/types/ViewField';
|
||||
|
||||
export const mapBoardFieldDefinitionsToViewFields = (
|
||||
fieldsDefinitions: BoardFieldDefinition<FieldMetadata>[],
|
||||
): ViewField[] => {
|
||||
return fieldsDefinitions.map(
|
||||
(fieldDefinition): ViewField => ({
|
||||
id: fieldDefinition.viewFieldId || '',
|
||||
fieldMetadataId: fieldDefinition.fieldMetadataId,
|
||||
size: 0,
|
||||
position: fieldDefinition.position,
|
||||
isVisible: fieldDefinition.isVisible ?? true,
|
||||
definition: fieldDefinition,
|
||||
}),
|
||||
);
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
import { useContext, useRef, useState } from 'react';
|
||||
import { useCallback, useContext, useRef, useState } from 'react';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { v4 } from 'uuid';
|
||||
@ -107,10 +108,26 @@ export const BoardOptionsDropdownContent = ({
|
||||
setCurrentMenu(menu);
|
||||
};
|
||||
|
||||
const { handleFieldVisibilityChange } = useBoardCardFields();
|
||||
const { handleFieldVisibilityChange, handleFieldsReorder } =
|
||||
useBoardCardFields();
|
||||
|
||||
const { closeDropdown } = useDropdown();
|
||||
|
||||
const handleReorderField: OnDragEndResponder = useCallback(
|
||||
(result) => {
|
||||
if (!result.destination) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reorderFields = [...visibleBoardCardFields];
|
||||
const [removed] = reorderFields.splice(result.source.index - 1, 1);
|
||||
reorderFields.splice(result.destination.index - 1, 0, removed);
|
||||
|
||||
handleFieldsReorder(reorderFields);
|
||||
},
|
||||
[handleFieldsReorder, visibleBoardCardFields],
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
Key.Escape,
|
||||
() => {
|
||||
@ -209,6 +226,7 @@ export const BoardOptionsDropdownContent = ({
|
||||
fields={visibleBoardCardFields}
|
||||
onVisibilityChange={handleFieldVisibilityChange}
|
||||
isDraggable={true}
|
||||
onDragEnd={handleReorderField}
|
||||
/>
|
||||
)}
|
||||
{hasVisibleFields && hasHiddenFields && <DropdownMenuSeparator />}
|
||||
|
@ -1,3 +1,7 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { savedBoardCardFieldsFamilyState } from '@/ui/layout/board/states/savedBoardCardFieldsFamilyState';
|
||||
import { BoardFieldDefinition } from '@/ui/layout/board/types/BoardFieldDefinition';
|
||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||
@ -7,13 +11,18 @@ import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState
|
||||
import { useBoardContext } from './useBoardContext';
|
||||
|
||||
export const useBoardCardFields = () => {
|
||||
const { BoardRecoilScopeContext } = useBoardContext();
|
||||
const { BoardRecoilScopeContext, onFieldsChange } = useBoardContext();
|
||||
|
||||
const [, setBoardCardFields] = useRecoilScopedState(
|
||||
boardCardFieldsScopedState,
|
||||
BoardRecoilScopeContext,
|
||||
);
|
||||
|
||||
const [, setSavedBoardCardFields] = useRecoilScopedState(
|
||||
savedBoardCardFieldsFamilyState,
|
||||
BoardRecoilScopeContext,
|
||||
);
|
||||
|
||||
const handleFieldVisibilityChange = (
|
||||
field: Omit<ColumnDefinition<FieldMetadata>, 'size' | 'position'>,
|
||||
) => {
|
||||
@ -26,5 +35,27 @@ export const useBoardCardFields = () => {
|
||||
);
|
||||
};
|
||||
|
||||
return { handleFieldVisibilityChange };
|
||||
const handleFieldsChange = useCallback(
|
||||
async (fields: BoardFieldDefinition<FieldMetadata>[]) => {
|
||||
setSavedBoardCardFields(fields);
|
||||
setBoardCardFields(fields);
|
||||
|
||||
await onFieldsChange?.(fields);
|
||||
},
|
||||
[setBoardCardFields, setSavedBoardCardFields, onFieldsChange],
|
||||
);
|
||||
|
||||
const handleFieldsReorder = useCallback(
|
||||
async (fields: BoardFieldDefinition<FieldMetadata>[]) => {
|
||||
const updatedFields = fields.map((column, index) => ({
|
||||
...column,
|
||||
position: index,
|
||||
}));
|
||||
|
||||
await handleFieldsChange(updatedFields);
|
||||
},
|
||||
[handleFieldsChange],
|
||||
);
|
||||
|
||||
return { handleFieldVisibilityChange, handleFieldsReorder };
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ export const visibleBoardCardFieldsScopedSelector = selectorFamily({
|
||||
get:
|
||||
(scopeId: string) =>
|
||||
({ get }) =>
|
||||
get(boardCardFieldsScopedState(scopeId)).filter(
|
||||
(field) => field.isVisible,
|
||||
),
|
||||
get(boardCardFieldsScopedState(scopeId))
|
||||
.filter((field) => field.isVisible)
|
||||
.sort((a, b) => a.position - b.position),
|
||||
});
|
||||
|
@ -5,4 +5,5 @@ export type BoardFieldDefinition<T extends FieldMetadata> =
|
||||
FieldDefinition<T> & {
|
||||
position: number;
|
||||
isVisible?: boolean;
|
||||
viewFieldId?: string;
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { BoardFieldDefinition } from '@/ui/layout/board/types/BoardFieldDefinition';
|
||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
||||
|
||||
@ -7,5 +8,7 @@ export type ViewField = {
|
||||
position: number;
|
||||
isVisible: boolean;
|
||||
size: number;
|
||||
definition: ColumnDefinition<FieldMetadata>;
|
||||
definition:
|
||||
| ColumnDefinition<FieldMetadata>
|
||||
| BoardFieldDefinition<FieldMetadata>;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user