mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-18 00:52:21 +03:00
feat: allow adding available pre-defined table columns to views (#1371)
* feat: allow adding available pre-defined table columns to views Closes #1360 * fix: allow creating views with the same name for the same table * refactor: code review - rename things - move handleColumnVisibilityChange to useTableColumns hook
This commit is contained in:
parent
9df4b475d8
commit
4aae22ab34
@ -2805,13 +2805,6 @@ export type ViewWhereInput = {
|
|||||||
|
|
||||||
export type ViewWhereUniqueInput = {
|
export type ViewWhereUniqueInput = {
|
||||||
id?: InputMaybe<Scalars['String']>;
|
id?: InputMaybe<Scalars['String']>;
|
||||||
workspaceId_type_objectId_name?: InputMaybe<ViewWorkspaceIdTypeObjectIdNameCompoundUniqueInput>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ViewWorkspaceIdTypeObjectIdNameCompoundUniqueInput = {
|
|
||||||
name: Scalars['String'];
|
|
||||||
objectId: Scalars['String'];
|
|
||||||
type: ViewType;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Workspace = {
|
export type Workspace = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { cloneElement, ComponentProps, useRef } from 'react';
|
import { cloneElement, type ComponentProps, useCallback, useRef } from 'react';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
@ -6,19 +6,22 @@ import { IconButton } from '@/ui/button/components/IconButton';
|
|||||||
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
|
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
|
||||||
import { IconPlus } from '@/ui/icon';
|
import { IconPlus } from '@/ui/icon';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
|
||||||
|
import { useTableColumns } from '../hooks/useTableColumns';
|
||||||
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
import { hiddenTableColumnsScopedSelector } from '../states/selectors/hiddenTableColumnsScopedSelector';
|
import { hiddenTableColumnsScopedSelector } from '../states/selectors/hiddenTableColumnsScopedSelector';
|
||||||
|
import type { ColumnDefinition } from '../types/ColumnDefinition';
|
||||||
|
|
||||||
const StyledColumnMenu = styled(StyledDropdownMenu)`
|
const StyledColumnMenu = styled(StyledDropdownMenu)`
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type EntityTableColumnMenuProps = {
|
type EntityTableColumnMenuProps = {
|
||||||
onAddColumn: (columnId: string) => void;
|
onAddColumn?: () => void;
|
||||||
onClickOutside?: () => void;
|
onClickOutside?: () => void;
|
||||||
} & ComponentProps<'div'>;
|
} & ComponentProps<'div'>;
|
||||||
|
|
||||||
@ -40,6 +43,16 @@ export const EntityTableColumnMenu = ({
|
|||||||
callback: onClickOutside,
|
callback: onClickOutside,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { handleColumnVisibilityChange } = useTableColumns();
|
||||||
|
|
||||||
|
const handleAddColumn = useCallback(
|
||||||
|
(column: ColumnDefinition<ViewFieldMetadata>) => {
|
||||||
|
onAddColumn?.();
|
||||||
|
handleColumnVisibilityChange(column);
|
||||||
|
},
|
||||||
|
[handleColumnVisibilityChange, onAddColumn],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledColumnMenu {...props} ref={ref}>
|
<StyledColumnMenu {...props} ref={ref}>
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuItemsContainer>
|
||||||
@ -48,8 +61,9 @@ export const EntityTableColumnMenu = ({
|
|||||||
key={column.id}
|
key={column.id}
|
||||||
actions={[
|
actions={[
|
||||||
<IconButton
|
<IconButton
|
||||||
|
key={`add-${column.id}`}
|
||||||
icon={<IconPlus size={theme.icon.size.sm} />}
|
icon={<IconPlus size={theme.icon.size.sm} />}
|
||||||
onClick={() => onAddColumn(column.id)}
|
onClick={() => handleAddColumn(column)}
|
||||||
/>,
|
/>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -148,19 +148,6 @@ export function EntityTableHeader() {
|
|||||||
setIsColumnMenuOpen((previousValue) => !previousValue);
|
setIsColumnMenuOpen((previousValue) => !previousValue);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAddColumn = useCallback(
|
|
||||||
(columnId: string) => {
|
|
||||||
setIsColumnMenuOpen(false);
|
|
||||||
|
|
||||||
const nextColumns = columns.map((column) =>
|
|
||||||
column.id === columnId ? { ...column, isVisible: true } : column,
|
|
||||||
);
|
|
||||||
|
|
||||||
setColumns(nextColumns);
|
|
||||||
},
|
|
||||||
[columns, setColumns],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<thead data-select-disable>
|
<thead data-select-disable>
|
||||||
<tr>
|
<tr>
|
||||||
@ -204,7 +191,7 @@ export function EntityTableHeader() {
|
|||||||
/>
|
/>
|
||||||
{isColumnMenuOpen && (
|
{isColumnMenuOpen && (
|
||||||
<StyledEntityTableColumnMenu
|
<StyledEntityTableColumnMenu
|
||||||
onAddColumn={handleAddColumn}
|
onAddColumn={toggleColumnMenu}
|
||||||
onClickOutside={toggleColumnMenu}
|
onClickOutside={toggleColumnMenu}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
40
front/src/modules/ui/table/hooks/useTableColumns.ts
Normal file
40
front/src/modules/ui/table/hooks/useTableColumns.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
|
||||||
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
|
||||||
|
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import { tableColumnsByIdScopedSelector } from '../states/selectors/tableColumnsByIdScopedSelector';
|
||||||
|
import { tableColumnsScopedState } from '../states/tableColumnsScopedState';
|
||||||
|
import type { ColumnDefinition } from '../types/ColumnDefinition';
|
||||||
|
|
||||||
|
export const useTableColumns = () => {
|
||||||
|
const [tableColumns, setTableColumns] = useRecoilScopedState(
|
||||||
|
tableColumnsScopedState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const tableColumnsById = useRecoilScopedValue(
|
||||||
|
tableColumnsByIdScopedSelector,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleColumnVisibilityChange = useCallback(
|
||||||
|
(column: ColumnDefinition<ViewFieldMetadata>) => {
|
||||||
|
const nextColumns = tableColumnsById[column.id]
|
||||||
|
? tableColumns.map((previousColumn) =>
|
||||||
|
previousColumn.id === column.id
|
||||||
|
? { ...previousColumn, isVisible: !column.isVisible }
|
||||||
|
: previousColumn,
|
||||||
|
)
|
||||||
|
: [...tableColumns, { ...column, isVisible: true }].sort(
|
||||||
|
(columnA, columnB) => columnA.order - columnB.order,
|
||||||
|
);
|
||||||
|
|
||||||
|
setTableColumns(nextColumns);
|
||||||
|
},
|
||||||
|
[setTableColumns, tableColumns, tableColumnsById],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { handleColumnVisibilityChange };
|
||||||
|
};
|
@ -27,9 +27,9 @@ import {
|
|||||||
import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState';
|
import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
|
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
|
||||||
|
import { useTableColumns } from '../../hooks/useTableColumns';
|
||||||
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
import { savedTableColumnsScopedState } from '../../states/savedTableColumnsScopedState';
|
import { savedTableColumnsScopedState } from '../../states/savedTableColumnsScopedState';
|
||||||
import { hiddenTableColumnsScopedSelector } from '../../states/selectors/hiddenTableColumnsScopedSelector';
|
import { hiddenTableColumnsScopedSelector } from '../../states/selectors/hiddenTableColumnsScopedSelector';
|
||||||
@ -74,10 +74,6 @@ export function TableOptionsDropdownContent({
|
|||||||
const [viewEditMode, setViewEditMode] = useRecoilState(
|
const [viewEditMode, setViewEditMode] = useRecoilState(
|
||||||
tableViewEditModeState,
|
tableViewEditModeState,
|
||||||
);
|
);
|
||||||
const [columns, setColumns] = useRecoilScopedState(
|
|
||||||
tableColumnsScopedState,
|
|
||||||
TableRecoilScopeContext,
|
|
||||||
);
|
|
||||||
const visibleColumns = useRecoilScopedValue(
|
const visibleColumns = useRecoilScopedValue(
|
||||||
visibleTableColumnsScopedSelector,
|
visibleTableColumnsScopedSelector,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
@ -91,18 +87,7 @@ export function TableOptionsDropdownContent({
|
|||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleColumnVisibilityChange = useCallback(
|
const { handleColumnVisibilityChange } = useTableColumns();
|
||||||
async (columnId: string, nextIsVisible: boolean) => {
|
|
||||||
const nextColumns = columns.map((column) =>
|
|
||||||
column.id === columnId
|
|
||||||
? { ...column, isVisible: nextIsVisible }
|
|
||||||
: column,
|
|
||||||
);
|
|
||||||
|
|
||||||
setColumns(nextColumns);
|
|
||||||
},
|
|
||||||
[columns, setColumns],
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderFieldActions = useCallback(
|
const renderFieldActions = useCallback(
|
||||||
(column: ColumnDefinition<ViewFieldMetadata>) =>
|
(column: ColumnDefinition<ViewFieldMetadata>) =>
|
||||||
@ -110,6 +95,7 @@ export function TableOptionsDropdownContent({
|
|||||||
!column.isVisible || visibleColumns.length > 1
|
!column.isVisible || visibleColumns.length > 1
|
||||||
? [
|
? [
|
||||||
<IconButton
|
<IconButton
|
||||||
|
key={`action-${column.id}`}
|
||||||
icon={
|
icon={
|
||||||
column.isVisible ? (
|
column.isVisible ? (
|
||||||
<IconMinus size={theme.icon.size.sm} />
|
<IconMinus size={theme.icon.size.sm} />
|
||||||
@ -117,9 +103,7 @@ export function TableOptionsDropdownContent({
|
|||||||
<IconPlus size={theme.icon.size.sm} />
|
<IconPlus size={theme.icon.size.sm} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onClick={() =>
|
onClick={() => handleColumnVisibilityChange(column)}
|
||||||
handleColumnVisibilityChange(column.id, !column.isVisible)
|
|
||||||
}
|
|
||||||
/>,
|
/>,
|
||||||
]
|
]
|
||||||
: undefined,
|
: undefined,
|
||||||
|
@ -112,12 +112,15 @@ export const TableUpdateViewButtonGroup = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleViewSubmit = useCallback(async () => {
|
const handleViewSubmit = useCallback(async () => {
|
||||||
await Promise.resolve(onViewSubmit?.());
|
if (canPersistColumns) setSavedColumns(currentColumns);
|
||||||
|
if (canPersistFilters) setSavedFilters(selectedFilters);
|
||||||
|
if (canPersistSorts) setSavedSorts(selectedSorts);
|
||||||
|
|
||||||
setSavedColumns(currentColumns);
|
await Promise.resolve(onViewSubmit?.());
|
||||||
setSavedFilters(selectedFilters);
|
|
||||||
setSavedSorts(selectedSorts);
|
|
||||||
}, [
|
}, [
|
||||||
|
canPersistColumns,
|
||||||
|
canPersistFilters,
|
||||||
|
canPersistSorts,
|
||||||
currentColumns,
|
currentColumns,
|
||||||
onViewSubmit,
|
onViewSubmit,
|
||||||
selectedFilters,
|
selectedFilters,
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
import { atomFamily } from 'recoil';
|
||||||
|
|
||||||
|
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
|
||||||
|
|
||||||
|
import type { ColumnDefinition } from '../types/ColumnDefinition';
|
||||||
|
|
||||||
|
export const availableTableColumnsScopedState = atomFamily<
|
||||||
|
ColumnDefinition<ViewFieldMetadata>[],
|
||||||
|
string
|
||||||
|
>({
|
||||||
|
key: 'availableTableColumnsScopedState',
|
||||||
|
default: [],
|
||||||
|
});
|
@ -1,13 +1,22 @@
|
|||||||
import { selectorFamily } from 'recoil';
|
import { selectorFamily } from 'recoil';
|
||||||
|
|
||||||
|
import { availableTableColumnsScopedState } from '../availableTableColumnsScopedState';
|
||||||
import { tableColumnsScopedState } from '../tableColumnsScopedState';
|
import { tableColumnsScopedState } from '../tableColumnsScopedState';
|
||||||
|
|
||||||
export const hiddenTableColumnsScopedSelector = selectorFamily({
|
export const hiddenTableColumnsScopedSelector = selectorFamily({
|
||||||
key: 'hiddenTableColumnsScopedSelector',
|
key: 'hiddenTableColumnsScopedSelector',
|
||||||
get:
|
get:
|
||||||
(scopeId: string) =>
|
(scopeId: string) =>
|
||||||
({ get }) =>
|
({ get }) => {
|
||||||
get(tableColumnsScopedState(scopeId)).filter(
|
const columns = get(tableColumnsScopedState(scopeId));
|
||||||
(column) => !column.isVisible,
|
const columnLabels = columns.map(({ label }) => label);
|
||||||
),
|
const otherAvailableColumns = get(
|
||||||
|
availableTableColumnsScopedState(scopeId),
|
||||||
|
).filter(({ label }) => !columnLabels.includes(label));
|
||||||
|
|
||||||
|
return [
|
||||||
|
...columns.filter((column) => !column.isVisible),
|
||||||
|
...otherAvailableColumns,
|
||||||
|
];
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,7 @@ import type {
|
|||||||
ViewFieldMetadata,
|
ViewFieldMetadata,
|
||||||
ViewFieldTextMetadata,
|
ViewFieldTextMetadata,
|
||||||
} from '@/ui/editable-field/types/ViewField';
|
} from '@/ui/editable-field/types/ViewField';
|
||||||
|
import { availableTableColumnsScopedState } from '@/ui/table/states/availableTableColumnsScopedState';
|
||||||
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
import { savedTableColumnsScopedState } from '@/ui/table/states/savedTableColumnsScopedState';
|
import { savedTableColumnsScopedState } from '@/ui/table/states/savedTableColumnsScopedState';
|
||||||
import { savedTableColumnsByIdScopedSelector } from '@/ui/table/states/selectors/savedTableColumnsByIdScopedSelector';
|
import { savedTableColumnsByIdScopedSelector } from '@/ui/table/states/selectors/savedTableColumnsByIdScopedSelector';
|
||||||
@ -45,19 +46,24 @@ export const useTableViewFields = ({
|
|||||||
objectName: 'company' | 'person';
|
objectName: 'company' | 'person';
|
||||||
columnDefinitions: ColumnDefinition<ViewFieldMetadata>[];
|
columnDefinitions: ColumnDefinition<ViewFieldMetadata>[];
|
||||||
}) => {
|
}) => {
|
||||||
const currentViewId = useRecoilScopedValue(
|
const currentTableViewId = useRecoilScopedValue(
|
||||||
currentTableViewIdState,
|
currentTableViewIdState,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
);
|
);
|
||||||
const [columns, setColumns] = useRecoilScopedState(
|
const [availableTableColumns, setAvailableTableColumns] =
|
||||||
|
useRecoilScopedState(
|
||||||
|
availableTableColumnsScopedState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const [tableColumns, setTableColumns] = useRecoilScopedState(
|
||||||
tableColumnsScopedState,
|
tableColumnsScopedState,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
);
|
);
|
||||||
const setSavedColumns = useSetRecoilState(
|
const setSavedTableColumns = useSetRecoilState(
|
||||||
savedTableColumnsScopedState(currentViewId),
|
savedTableColumnsScopedState(currentTableViewId),
|
||||||
);
|
);
|
||||||
const savedColumnsById = useRecoilValue(
|
const savedTableColumnsById = useRecoilValue(
|
||||||
savedTableColumnsByIdScopedSelector(currentViewId),
|
savedTableColumnsByIdScopedSelector(currentTableViewId),
|
||||||
);
|
);
|
||||||
|
|
||||||
const [createViewFieldsMutation] = useCreateViewFieldsMutation();
|
const [createViewFieldsMutation] = useCreateViewFieldsMutation();
|
||||||
@ -66,7 +72,7 @@ export const useTableViewFields = ({
|
|||||||
const createViewFields = useCallback(
|
const createViewFields = useCallback(
|
||||||
(
|
(
|
||||||
columns: ColumnDefinition<ViewFieldMetadata>[],
|
columns: ColumnDefinition<ViewFieldMetadata>[],
|
||||||
viewId = currentViewId,
|
viewId = currentTableViewId,
|
||||||
) => {
|
) => {
|
||||||
if (!viewId || !columns.length) return;
|
if (!viewId || !columns.length) return;
|
||||||
|
|
||||||
@ -79,12 +85,12 @@ export const useTableViewFields = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[createViewFieldsMutation, currentViewId, objectName],
|
[createViewFieldsMutation, currentTableViewId, objectName],
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateViewFields = useCallback(
|
const updateViewFields = useCallback(
|
||||||
(columns: ColumnDefinition<ViewFieldMetadata>[]) => {
|
(columns: ColumnDefinition<ViewFieldMetadata>[]) => {
|
||||||
if (!currentViewId || !columns.length) return;
|
if (!currentTableViewId || !columns.length) return;
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
columns.map((column) =>
|
columns.map((column) =>
|
||||||
@ -100,16 +106,16 @@ export const useTableViewFields = ({
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[currentViewId, updateViewFieldMutation],
|
[currentTableViewId, updateViewFieldMutation],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { refetch } = useGetViewFieldsQuery({
|
const { refetch } = useGetViewFieldsQuery({
|
||||||
skip: !currentViewId,
|
skip: !currentTableViewId,
|
||||||
variables: {
|
variables: {
|
||||||
orderBy: { index: SortOrder.Asc },
|
orderBy: { index: SortOrder.Asc },
|
||||||
where: {
|
where: {
|
||||||
objectName: { equals: objectName },
|
objectName: { equals: objectName },
|
||||||
viewId: { equals: currentViewId ?? null },
|
viewId: { equals: currentTableViewId ?? null },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onCompleted: async (data) => {
|
onCompleted: async (data) => {
|
||||||
@ -132,26 +138,42 @@ export const useTableViewFields = ({
|
|||||||
isVisible: viewField.isVisible,
|
isVisible: viewField.isVisible,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (!isDeeplyEqual(columns, nextColumns)) {
|
if (!isDeeplyEqual(tableColumns, nextColumns)) {
|
||||||
setSavedColumns(nextColumns);
|
setSavedTableColumns(nextColumns);
|
||||||
setColumns(nextColumns);
|
setTableColumns(nextColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!availableTableColumns.length) {
|
||||||
|
setAvailableTableColumns(columnDefinitions);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const persistColumns = useCallback(async () => {
|
const persistColumns = useCallback(async () => {
|
||||||
if (!currentViewId) return;
|
if (!currentTableViewId) return;
|
||||||
|
|
||||||
const viewFieldsToUpdate = columns.filter(
|
const viewFieldsToCreate = tableColumns.filter(
|
||||||
|
(column) => !savedTableColumnsById[column.id],
|
||||||
|
);
|
||||||
|
await createViewFields(viewFieldsToCreate);
|
||||||
|
|
||||||
|
const viewFieldsToUpdate = tableColumns.filter(
|
||||||
(column) =>
|
(column) =>
|
||||||
savedColumnsById[column.id] &&
|
savedTableColumnsById[column.id] &&
|
||||||
(savedColumnsById[column.id].size !== column.size ||
|
(savedTableColumnsById[column.id].size !== column.size ||
|
||||||
savedColumnsById[column.id].isVisible !== column.isVisible),
|
savedTableColumnsById[column.id].isVisible !== column.isVisible),
|
||||||
);
|
);
|
||||||
await updateViewFields(viewFieldsToUpdate);
|
await updateViewFields(viewFieldsToUpdate);
|
||||||
|
|
||||||
return refetch();
|
return refetch();
|
||||||
}, [columns, currentViewId, refetch, savedColumnsById, updateViewFields]);
|
}, [
|
||||||
|
createViewFields,
|
||||||
|
currentTableViewId,
|
||||||
|
refetch,
|
||||||
|
savedTableColumnsById,
|
||||||
|
tableColumns,
|
||||||
|
updateViewFields,
|
||||||
|
]);
|
||||||
|
|
||||||
return { createViewFields, persistColumns };
|
return { createViewFields, persistColumns };
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "views_workspaceId_type_objectId_name_key";
|
@ -216,31 +216,31 @@ model WorkspaceMember {
|
|||||||
model Company {
|
model Company {
|
||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
name String
|
name String
|
||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
domainName String
|
domainName String
|
||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
linkedinUrl String?
|
linkedinUrl String?
|
||||||
/// @Validator.IsNumber()
|
/// @Validator.IsNumber()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
annualRecurringRevenue Int?
|
annualRecurringRevenue Int?
|
||||||
/// @Validator.IsBoolean()
|
/// @Validator.IsBoolean()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
idealCustomerProfile Boolean @default(false)
|
idealCustomerProfile Boolean @default(false)
|
||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
xUrl String?
|
xUrl String?
|
||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
address String
|
address String
|
||||||
/// @Validator.IsNumber()
|
/// @Validator.IsNumber()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
employees Int?
|
employees Int?
|
||||||
|
|
||||||
people Person[]
|
people Person[]
|
||||||
accountOwner User? @relation(fields: [accountOwnerId], references: [id], onDelete: SetNull)
|
accountOwner User? @relation(fields: [accountOwnerId], references: [id], onDelete: SetNull)
|
||||||
@ -603,7 +603,6 @@ model View {
|
|||||||
/// @TypeGraphQL.omit(input: true, output: true)
|
/// @TypeGraphQL.omit(input: true, output: true)
|
||||||
workspaceId String
|
workspaceId String
|
||||||
|
|
||||||
@@unique([workspaceId, type, objectId, name])
|
|
||||||
@@map("views")
|
@@map("views")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user