Refactor board and table options (#3700)
* Refactor board and table options * Fix * Fix
This commit is contained in:
@ -14,7 +14,6 @@ const StyledColumn = styled.div<{ isFirstColumn: boolean }>`
|
||||
isFirstColumn ? 'none' : theme.border.color.light};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: fit-content;
|
||||
max-width: 200px;
|
||||
min-width: 200px;
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ import { useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
|
||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||
@ -11,13 +10,12 @@ import { RecordIndexBoardContainerEffect } from '@/object-record/record-index/co
|
||||
import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer';
|
||||
import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect';
|
||||
import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect';
|
||||
import { RecordIndexOptionsDropdown } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdown';
|
||||
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
|
||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
|
||||
import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { TableOptionsDropdown } from '@/object-record/record-table/options/components/TableOptionsDropdown';
|
||||
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
|
||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
@ -66,37 +64,23 @@ export const RecordIndexContainer = ({
|
||||
const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState);
|
||||
const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState);
|
||||
|
||||
const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport();
|
||||
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
|
||||
|
||||
const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({
|
||||
recordTableId: recordIndexId,
|
||||
});
|
||||
|
||||
const handleImport = () => {
|
||||
const openImport =
|
||||
objectNamePlural === 'companies'
|
||||
? openCompanySpreadsheetImport
|
||||
: openPersonSpreadsheetImport;
|
||||
openImport();
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<SpreadsheetImportProvider>
|
||||
<ViewBar
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<TableOptionsDropdown
|
||||
recordTableId={recordIndexId}
|
||||
onImport={
|
||||
['companies', 'people'].includes(recordIndexId)
|
||||
? handleImport
|
||||
: undefined
|
||||
}
|
||||
<RecordIndexOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
viewType={recordIndexViewType ?? ViewType.Table}
|
||||
/>
|
||||
}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
optionsDropdownScopeId={RECORD_INDEX_OPTIONS_DROPDOWN_ID}
|
||||
onViewFieldsChange={(viewFields) => {
|
||||
setTableColumns(
|
||||
mapViewFieldsToColumnDefinitions(viewFields, columnDefinitions),
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
import { RecordIndexOptionsDropdownButton } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdownButton';
|
||||
import { RecordIndexOptionsDropdownContent } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdownContent';
|
||||
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
|
||||
import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
type RecordIndexOptionsDropdownProps = {
|
||||
viewType: ViewType;
|
||||
objectNameSingular: string;
|
||||
recordIndexId: string;
|
||||
};
|
||||
|
||||
export const RecordIndexOptionsDropdown = ({
|
||||
recordIndexId,
|
||||
objectNameSingular,
|
||||
viewType,
|
||||
}: RecordIndexOptionsDropdownProps) => {
|
||||
const { setViewEditMode } = useViewBar();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
dropdownId={RECORD_INDEX_OPTIONS_DROPDOWN_ID}
|
||||
clickableComponent={<RecordIndexOptionsDropdownButton />}
|
||||
dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
dropdownComponents={
|
||||
<RecordIndexOptionsDropdownContent
|
||||
viewType={viewType}
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordIndexId={recordIndexId}
|
||||
/>
|
||||
}
|
||||
onClickOutside={() => setViewEditMode('none')}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -1,10 +1,10 @@
|
||||
import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId';
|
||||
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
|
||||
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
export const TableOptionsDropdownButton = () => {
|
||||
export const RecordIndexOptionsDropdownButton = () => {
|
||||
const { isDropdownOpen, toggleDropdown } = useDropdown(
|
||||
TableOptionsDropdownId,
|
||||
RECORD_INDEX_OPTIONS_DROPDOWN_ID,
|
||||
);
|
||||
|
||||
return (
|
||||
@ -1,10 +1,12 @@
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId';
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
|
||||
import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard';
|
||||
import { useRecordIndexOptionsForTable } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForTable';
|
||||
import { useRecordIndexOptionsImport } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsImport';
|
||||
import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope';
|
||||
import { IconChevronLeft, IconFileImport, IconTag } from '@/ui/display/icon';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
|
||||
@ -16,69 +18,42 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
||||
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
import { useTableColumns } from '../../hooks/useTableColumns';
|
||||
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
|
||||
type RecordIndexOptionsMenu = 'fields';
|
||||
|
||||
type TableOptionsMenu = 'fields';
|
||||
type RecordIndexOptionsDropdownContentProps = {
|
||||
recordIndexId: string;
|
||||
objectNameSingular: string;
|
||||
viewType: ViewType;
|
||||
};
|
||||
|
||||
export const TableOptionsDropdownContent = ({
|
||||
onImport,
|
||||
recordTableId,
|
||||
}: {
|
||||
onImport?: () => void;
|
||||
recordTableId: string;
|
||||
}) => {
|
||||
const { setViewEditMode, handleViewNameSubmit } = useViewBar();
|
||||
export const RecordIndexOptionsDropdownContent = ({
|
||||
viewType,
|
||||
recordIndexId,
|
||||
objectNameSingular,
|
||||
}: RecordIndexOptionsDropdownContentProps) => {
|
||||
const { setViewEditMode, handleViewNameSubmit } = useViewBar({
|
||||
viewBarId: recordIndexId,
|
||||
});
|
||||
const { viewEditModeState, currentViewSelector } = useViewScopedStates();
|
||||
|
||||
const viewEditMode = useRecoilValue(viewEditModeState);
|
||||
const currentView = useRecoilValue(currentViewSelector);
|
||||
const { closeDropdown } = useDropdown(TableOptionsDropdownId);
|
||||
const { closeDropdown } = useDropdown(RECORD_INDEX_OPTIONS_DROPDOWN_ID);
|
||||
|
||||
const [currentMenu, setCurrentMenu] = useState<TableOptionsMenu | undefined>(
|
||||
undefined,
|
||||
);
|
||||
const [currentMenu, setCurrentMenu] = useState<
|
||||
RecordIndexOptionsMenu | undefined
|
||||
>(undefined);
|
||||
|
||||
const resetMenu = () => setCurrentMenu(undefined);
|
||||
|
||||
const viewEditInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } =
|
||||
useRecordTableStates(recordTableId);
|
||||
|
||||
const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector());
|
||||
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
|
||||
|
||||
const { handleColumnVisibilityChange, handleColumnReorder } = useTableColumns(
|
||||
{ recordTableId },
|
||||
);
|
||||
|
||||
const handleSelectMenu = (option: TableOptionsMenu) => {
|
||||
const name = viewEditInputRef.current?.value;
|
||||
handleViewNameSubmit(name);
|
||||
const handleSelectMenu = (option: RecordIndexOptionsMenu) => {
|
||||
setCurrentMenu(option);
|
||||
};
|
||||
|
||||
const handleReorderField: OnDragEndResponder = useCallback(
|
||||
(result) => {
|
||||
if (
|
||||
!result.destination ||
|
||||
result.destination.index === 1 ||
|
||||
result.source.index === 1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reorderFields = [...visibleTableColumns];
|
||||
const [removed] = reorderFields.splice(result.source.index - 1, 1);
|
||||
reorderFields.splice(result.destination.index - 1, 0, removed);
|
||||
|
||||
handleColumnReorder(reorderFields);
|
||||
},
|
||||
[visibleTableColumns, handleColumnReorder],
|
||||
);
|
||||
|
||||
const resetMenu = () => setCurrentMenu(undefined);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
@ -99,6 +74,41 @@ export const TableOptionsDropdownContent = ({
|
||||
TableOptionsHotkeyScope.Dropdown,
|
||||
);
|
||||
|
||||
const {
|
||||
handleColumnVisibilityChange,
|
||||
handleReorderColumns,
|
||||
visibleTableColumns,
|
||||
hiddenTableColumns,
|
||||
} = useRecordIndexOptionsForTable(recordIndexId);
|
||||
|
||||
const {
|
||||
visibleBoardFields,
|
||||
hiddenBoardFields,
|
||||
handleReorderBoardFields,
|
||||
handleBoardFieldVisibilityChange,
|
||||
} = useRecordIndexOptionsForBoard({
|
||||
objectNameSingular,
|
||||
viewBarId: recordIndexId,
|
||||
});
|
||||
|
||||
const visibleRecordFields =
|
||||
viewType === ViewType.Kanban ? visibleBoardFields : visibleTableColumns;
|
||||
|
||||
const hiddenRecordFields =
|
||||
viewType === ViewType.Kanban ? hiddenBoardFields : hiddenTableColumns;
|
||||
|
||||
const handleReorderFields =
|
||||
viewType === ViewType.Kanban
|
||||
? handleReorderBoardFields
|
||||
: handleReorderColumns;
|
||||
|
||||
const handleChangeFieldVisibility =
|
||||
viewType === ViewType.Kanban
|
||||
? handleBoardFieldVisibilityChange
|
||||
: handleColumnVisibilityChange;
|
||||
|
||||
const { handleImport } = useRecordIndexOptionsImport({ objectNameSingular });
|
||||
|
||||
return (
|
||||
<>
|
||||
{!currentMenu && (
|
||||
@ -122,9 +132,9 @@ export const TableOptionsDropdownContent = ({
|
||||
LeftIcon={IconTag}
|
||||
text="Fields"
|
||||
/>
|
||||
{onImport && (
|
||||
{handleImport && (
|
||||
<MenuItem
|
||||
onClick={onImport}
|
||||
onClick={() => handleImport()}
|
||||
LeftIcon={IconFileImport}
|
||||
text="Import"
|
||||
/>
|
||||
@ -140,20 +150,20 @@ export const TableOptionsDropdownContent = ({
|
||||
<DropdownMenuSeparator />
|
||||
<ViewFieldsVisibilityDropdownSection
|
||||
title="Visible"
|
||||
fields={visibleTableColumns}
|
||||
fields={visibleRecordFields}
|
||||
isVisible={true}
|
||||
onVisibilityChange={handleColumnVisibilityChange}
|
||||
onVisibilityChange={handleChangeFieldVisibility}
|
||||
isDraggable={true}
|
||||
onDragEnd={handleReorderField}
|
||||
onDragEnd={handleReorderFields}
|
||||
/>
|
||||
{hiddenTableColumns.length > 0 && (
|
||||
{hiddenRecordFields.length > 0 && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<ViewFieldsVisibilityDropdownSection
|
||||
title="Hidden"
|
||||
fields={hiddenTableColumns}
|
||||
fields={hiddenRecordFields}
|
||||
isVisible={false}
|
||||
onVisibilityChange={handleColumnVisibilityChange}
|
||||
onVisibilityChange={handleChangeFieldVisibility}
|
||||
isDraggable={false}
|
||||
/>
|
||||
</>
|
||||
@ -0,0 +1,2 @@
|
||||
export const RECORD_INDEX_BOARD_OPTIONS_DROPDOWN_ID =
|
||||
'record-index-table-options-dropdown-id';
|
||||
@ -0,0 +1,2 @@
|
||||
export const RECORD_INDEX_OPTIONS_DROPDOWN_ID =
|
||||
'record-index-options-dropdown-id';
|
||||
@ -0,0 +1,156 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { mapBoardFieldDefinitionsToViewFields } from '@/companies/utils/mapBoardFieldDefinitionsToViewFields';
|
||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||
import { useObjectMetadataItemOnly } from '@/object-metadata/hooks/useObjectMetadataItemOnly';
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { useViewFields } from '@/views/hooks/internal/useViewFields';
|
||||
|
||||
type useRecordIndexOptionsForBoardParams = {
|
||||
objectNameSingular: string;
|
||||
viewBarId: string;
|
||||
};
|
||||
|
||||
export const useRecordIndexOptionsForBoard = ({
|
||||
objectNameSingular,
|
||||
viewBarId,
|
||||
}: useRecordIndexOptionsForBoardParams) => {
|
||||
const [recordIndexFieldDefinitions, setRecordIndexFieldDefinitions] =
|
||||
useRecoilState(recordIndexFieldDefinitionsState);
|
||||
|
||||
const { persistViewFields } = useViewFields(viewBarId);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemOnly({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { columnDefinitions } =
|
||||
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
|
||||
|
||||
const visibleBoardFields = useMemo(
|
||||
() =>
|
||||
columnDefinitions.filter((columnDefinition) => {
|
||||
return recordIndexFieldDefinitions.some(
|
||||
(existingRecordFieldDefinition) => {
|
||||
return (
|
||||
columnDefinition.fieldMetadataId ===
|
||||
existingRecordFieldDefinition.fieldMetadataId &&
|
||||
existingRecordFieldDefinition.isVisible
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
[columnDefinitions, recordIndexFieldDefinitions],
|
||||
);
|
||||
|
||||
const hiddenBoardFields = useMemo(
|
||||
() =>
|
||||
columnDefinitions.filter((columnDefinition) => {
|
||||
return !recordIndexFieldDefinitions.some(
|
||||
(existingRecordFieldDefinition) => {
|
||||
return (
|
||||
columnDefinition.fieldMetadataId ===
|
||||
existingRecordFieldDefinition.fieldMetadataId &&
|
||||
existingRecordFieldDefinition.isVisible
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
[columnDefinitions, recordIndexFieldDefinitions],
|
||||
);
|
||||
|
||||
const handleReorderBoardFields: OnDragEndResponder = useCallback(
|
||||
(result) => {
|
||||
if (
|
||||
!result.destination ||
|
||||
result.destination.index === 1 ||
|
||||
result.source.index === 1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reorderFields = [...recordIndexFieldDefinitions];
|
||||
const [removed] = reorderFields.splice(result.source.index - 1, 1);
|
||||
reorderFields.splice(result.destination.index - 1, 0, removed);
|
||||
|
||||
const updatedFields = reorderFields.map((field, index) => ({
|
||||
...field,
|
||||
position: index,
|
||||
}));
|
||||
|
||||
setRecordIndexFieldDefinitions(updatedFields);
|
||||
persistViewFields(mapBoardFieldDefinitionsToViewFields(updatedFields));
|
||||
},
|
||||
[
|
||||
persistViewFields,
|
||||
recordIndexFieldDefinitions,
|
||||
setRecordIndexFieldDefinitions,
|
||||
],
|
||||
);
|
||||
|
||||
// Todo : this seems over complex and should at least be extracted to an util with unit test.
|
||||
// Let's refactor this as we introduce the new viewBar
|
||||
const handleBoardFieldVisibilityChange = useCallback(
|
||||
async (
|
||||
updatedFieldDefinition: Omit<
|
||||
ColumnDefinition<FieldMetadata>,
|
||||
'size' | 'position'
|
||||
>,
|
||||
) => {
|
||||
const isNewViewField = !recordIndexFieldDefinitions.some(
|
||||
(fieldDefinition) =>
|
||||
fieldDefinition.fieldMetadataId ===
|
||||
updatedFieldDefinition.fieldMetadataId,
|
||||
);
|
||||
|
||||
let updatedFieldsDefinitions: ColumnDefinition<FieldMetadata>[];
|
||||
|
||||
if (isNewViewField) {
|
||||
const correspondingFieldDefinition = columnDefinitions.find(
|
||||
(availableTableColumn) =>
|
||||
availableTableColumn.fieldMetadataId ===
|
||||
updatedFieldDefinition.fieldMetadataId,
|
||||
);
|
||||
if (!correspondingFieldDefinition) return;
|
||||
|
||||
updatedFieldsDefinitions = [
|
||||
...recordIndexFieldDefinitions,
|
||||
{ ...correspondingFieldDefinition, isVisible: true },
|
||||
];
|
||||
} else {
|
||||
updatedFieldsDefinitions = recordIndexFieldDefinitions.map(
|
||||
(exitingFieldDefinition) =>
|
||||
exitingFieldDefinition.fieldMetadataId ===
|
||||
updatedFieldDefinition.fieldMetadataId
|
||||
? {
|
||||
...exitingFieldDefinition,
|
||||
isVisible: !updatedFieldDefinition.isVisible,
|
||||
}
|
||||
: exitingFieldDefinition,
|
||||
);
|
||||
}
|
||||
|
||||
setRecordIndexFieldDefinitions(updatedFieldsDefinitions);
|
||||
persistViewFields(
|
||||
mapBoardFieldDefinitionsToViewFields(updatedFieldsDefinitions),
|
||||
);
|
||||
},
|
||||
[
|
||||
recordIndexFieldDefinitions,
|
||||
setRecordIndexFieldDefinitions,
|
||||
persistViewFields,
|
||||
columnDefinitions,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
handleReorderBoardFields,
|
||||
handleBoardFieldVisibilityChange,
|
||||
visibleBoardFields,
|
||||
hiddenBoardFields,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,44 @@
|
||||
import { useCallback } from 'react';
|
||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { useTableColumns } from '@/object-record/record-table/hooks/useTableColumns';
|
||||
|
||||
export const useRecordIndexOptionsForTable = (recordTableId: string) => {
|
||||
const { getHiddenTableColumnsSelector, getVisibleTableColumnsSelector } =
|
||||
useRecordTableStates(recordTableId);
|
||||
|
||||
const hiddenTableColumns = useRecoilValue(getHiddenTableColumnsSelector());
|
||||
const visibleTableColumns = useRecoilValue(getVisibleTableColumnsSelector());
|
||||
|
||||
const { handleColumnVisibilityChange, handleColumnReorder } = useTableColumns(
|
||||
{ recordTableId: recordTableId },
|
||||
);
|
||||
|
||||
const handleReorderColumns: OnDragEndResponder = useCallback(
|
||||
(result) => {
|
||||
if (
|
||||
!result.destination ||
|
||||
result.destination.index === 1 ||
|
||||
result.source.index === 1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reorderFields = [...visibleTableColumns];
|
||||
const [removed] = reorderFields.splice(result.source.index - 1, 1);
|
||||
reorderFields.splice(result.destination.index - 1, 0, removed);
|
||||
|
||||
handleColumnReorder(reorderFields);
|
||||
},
|
||||
[visibleTableColumns, handleColumnReorder],
|
||||
);
|
||||
|
||||
return {
|
||||
handleReorderColumns,
|
||||
handleColumnVisibilityChange,
|
||||
visibleTableColumns,
|
||||
hiddenTableColumns,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,23 @@
|
||||
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
|
||||
|
||||
type useRecordIndexOptionsImportParams = {
|
||||
objectNameSingular: string;
|
||||
};
|
||||
|
||||
export const useRecordIndexOptionsImport = ({
|
||||
objectNameSingular,
|
||||
}: useRecordIndexOptionsImportParams) => {
|
||||
const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport();
|
||||
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
|
||||
|
||||
const handleImport =
|
||||
CoreObjectNameSingular.Company === objectNameSingular
|
||||
? openCompanySpreadsheetImport
|
||||
: CoreObjectNameSingular.Person === objectNameSingular
|
||||
? openPersonSpreadsheetImport
|
||||
: undefined;
|
||||
|
||||
return { handleImport };
|
||||
};
|
||||
@ -1,2 +0,0 @@
|
||||
// We should either apply the constant all caps case or maybe define a more general enum to store those ids ?
|
||||
export const TableOptionsDropdownId = 'table-options-dropdown-id';
|
||||
@ -1,34 +0,0 @@
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { useViewBar } from '@/views/hooks/useViewBar';
|
||||
|
||||
import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId';
|
||||
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
|
||||
|
||||
import { TableOptionsDropdownButton } from './TableOptionsDropdownButton';
|
||||
import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
|
||||
|
||||
export const TableOptionsDropdown = ({
|
||||
onImport,
|
||||
recordTableId,
|
||||
}: {
|
||||
onImport?: () => void;
|
||||
recordTableId: string;
|
||||
}) => {
|
||||
const { setViewEditMode } = useViewBar();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
dropdownId={TableOptionsDropdownId}
|
||||
clickableComponent={<TableOptionsDropdownButton />}
|
||||
dropdownHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
|
||||
dropdownOffset={{ y: 8 }}
|
||||
dropdownComponents={
|
||||
<TableOptionsDropdownContent
|
||||
onImport={onImport}
|
||||
recordTableId={recordTableId}
|
||||
/>
|
||||
}
|
||||
onClickOutside={() => setViewEditMode('none')}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -1,10 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RecordIndexOptionsDropdown } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdown';
|
||||
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
|
||||
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
|
||||
import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId';
|
||||
import { TableOptionsDropdown } from '@/object-record/record-table/options/components/TableOptionsDropdown';
|
||||
import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
@ -16,7 +17,7 @@ const StyledContainer = styled.div`
|
||||
export const SignInBackgroundMockContainer = () => {
|
||||
const objectNamePlural = 'companies';
|
||||
const objectNameSingular = 'company';
|
||||
const recordTableId = 'sign-up-mock-record-table-id';
|
||||
const recordIndexId = 'sign-up-mock-record-table-id';
|
||||
const viewBarId = 'companies-mock';
|
||||
|
||||
return (
|
||||
@ -24,18 +25,22 @@ export const SignInBackgroundMockContainer = () => {
|
||||
<ViewBar
|
||||
viewBarId={viewBarId}
|
||||
optionsDropdownButton={
|
||||
<TableOptionsDropdown recordTableId={recordTableId} />
|
||||
<RecordIndexOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
viewType={ViewType.Table}
|
||||
/>
|
||||
}
|
||||
optionsDropdownScopeId={TableOptionsDropdownId}
|
||||
optionsDropdownScopeId={RECORD_INDEX_OPTIONS_DROPDOWN_ID}
|
||||
/>
|
||||
<SignInBackgroundMockContainerEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
recordTableId={recordTableId}
|
||||
recordTableId={recordIndexId}
|
||||
viewId={viewBarId}
|
||||
/>
|
||||
<RecordTableWithWrappers
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordTableId={recordTableId}
|
||||
recordTableId={recordIndexId}
|
||||
viewBarId={viewBarId}
|
||||
createRecord={async () => {}}
|
||||
updateRecordMutation={() => {}}
|
||||
|
||||
Reference in New Issue
Block a user