Migrate view field to new data model - Part 2 (#2270)

* Migrate view field to new data model

* Migrate view fields to new model
This commit is contained in:
Charles Bochet
2023-10-28 19:13:48 +02:00
committed by GitHub
parent b591023eb3
commit 685d342170
168 changed files with 960 additions and 4568 deletions

View File

@ -23,8 +23,8 @@ export const ActivityAssigneeEditableField = ({
entityId: activity.id,
recoilScopeId: 'assignee',
fieldDefinition: {
key: 'assignee',
name: 'Assignee',
fieldId: 'assignee',
label: 'Assignee',
Icon: IconUserCircle,
type: 'relation',
metadata: {

View File

@ -21,8 +21,8 @@ export const ActivityEditorDateField = ({
entityId: activityId,
recoilScopeId: 'activityDueAt',
fieldDefinition: {
key: 'activityDueAt',
name: 'Due date',
fieldId: 'activityDueAt',
label: 'Due date',
Icon: IconCalendar,
type: 'date',
metadata: {

View File

@ -3,11 +3,8 @@ import { useRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { turnFilterIntoWhereClause } from '@/ui/data/filter/utils/turnFilterIntoWhereClause';
import {
ActivityType,
useGetActivitiesQuery,
ViewFilterOperand,
} from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { ActivityType, useGetActivitiesQuery } from '~/generated/graphql';
import { parseDate } from '~/utils/date-utils';
export const useCurrentUserTaskCount = () => {

View File

@ -7,31 +7,31 @@ export const pipeline = {
{
id: 'pipeline-stage-1',
name: 'New',
index: 0,
position: 0,
color: 'red',
},
{
id: 'pipeline-stage-2',
name: 'Screening',
index: 1,
position: 1,
color: 'purple',
},
{
id: 'pipeline-stage-3',
name: 'Meeting',
index: 2,
position: 2,
color: 'sky',
},
{
id: 'pipeline-stage-4',
name: 'Proposal',
index: 3,
position: 3,
color: 'turquoise',
},
{
id: 'pipeline-stage-5',
name: 'Customer',
index: 4,
position: 4,
color: 'yellow',
},
],

View File

@ -222,14 +222,14 @@ export const CompanyBoardCard = () => {
<StyledBoardCardBody>
<AnimatedEaseInOut isOpen={!showCompactView}>
{visibleBoardCardFields.map((viewField) => (
<PreventSelectOnClickContainer key={viewField.key}>
<PreventSelectOnClickContainer key={viewField.fieldId}>
<FieldContext.Provider
value={{
entityId: boardCardId,
recoilScopeId: boardCardId + viewField.key,
recoilScopeId: boardCardId + viewField.fieldId,
fieldDefinition: {
key: viewField.key,
name: viewField.name,
fieldId: viewField.fieldId,
label: viewField.label,
Icon: viewField.Icon,
type: viewField.type,
metadata: viewField.metadata,

View File

@ -28,11 +28,11 @@ import { User } from '~/generated/graphql';
export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[] =
[
{
key: 'name',
name: 'Name',
fieldId: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
size: 180,
index: 0,
position: 0,
type: 'chip',
metadata: {
urlFieldName: 'domainName',
@ -45,11 +45,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
basePathToShowPage: '/companies/',
} satisfies ColumnDefinition<FieldChipMetadata>,
{
key: 'domainName',
name: 'URL',
fieldId: 'domainName',
label: 'URL',
Icon: IconLink,
size: 100,
index: 1,
position: 1,
type: 'url',
metadata: {
fieldName: 'domainName',
@ -60,11 +60,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
'The company website URL. We use this url to fetch the company icon.',
} satisfies ColumnDefinition<FieldURLMetadata>,
{
key: 'accountOwner',
name: 'Account Owner',
fieldId: 'accountOwner',
label: 'Account Owner',
Icon: IconUserCircle,
size: 150,
index: 2,
position: 2,
type: 'relation',
metadata: {
fieldName: 'accountOwner',
@ -82,11 +82,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
},
} satisfies ColumnDefinition<FieldRelationMetadata>,
{
key: 'createdAt',
name: 'Creation',
fieldId: 'createdAt',
label: 'Creation',
Icon: IconCalendarEvent,
size: 150,
index: 3,
position: 3,
type: 'date',
metadata: {
fieldName: 'createdAt',
@ -95,11 +95,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
infoTooltipContent: "Date when the company's record was created.",
} satisfies ColumnDefinition<FieldDateMetadata>,
{
key: 'employees',
name: 'Employees',
fieldId: 'employees',
label: 'Employees',
Icon: IconUsers,
size: 150,
index: 4,
position: 4,
type: 'number',
metadata: {
fieldName: 'employees',
@ -110,11 +110,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
infoTooltipContent: 'Number of employees in the company.',
} satisfies ColumnDefinition<FieldNumberMetadata>,
{
key: 'linkedin',
name: 'LinkedIn',
fieldId: 'linkedin',
label: 'LinkedIn',
Icon: IconBrandLinkedin,
size: 170,
index: 5,
position: 5,
type: 'url',
metadata: {
fieldName: 'linkedinUrl',
@ -124,11 +124,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
infoTooltipContent: 'The company Linkedin account.',
} satisfies ColumnDefinition<FieldURLMetadata>,
{
key: 'address',
name: 'Address',
fieldId: 'address',
label: 'Address',
Icon: IconMap,
size: 170,
index: 6,
position: 6,
type: 'text',
metadata: {
fieldName: 'address',
@ -138,11 +138,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
infoTooltipContent: 'The company address.',
} satisfies ColumnDefinition<FieldTextMetadata>,
{
key: 'idealCustomerProfile',
name: 'ICP',
fieldId: 'idealCustomerProfile',
label: 'ICP',
Icon: IconTarget,
size: 150,
index: 7,
position: 7,
type: 'boolean',
metadata: {
fieldName: 'idealCustomerProfile',
@ -152,11 +152,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you.',
} satisfies ColumnDefinition<FieldBooleanMetadata>,
{
key: 'annualRecurringRevenue',
name: 'ARR',
fieldId: 'annualRecurringRevenue',
label: 'ARR',
Icon: IconMoneybag,
size: 150,
index: 8,
position: 8,
type: 'moneyAmount',
metadata: {
fieldName: 'annualRecurringRevenue',
@ -166,11 +166,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
'Annual Recurring Revenue: The actual or estimated annual revenue of the company.',
} satisfies ColumnDefinition<FieldMoneyMetadata>,
{
key: 'xUrl',
name: 'Twitter',
fieldId: 'xUrl',
label: 'Twitter',
Icon: IconBrandX,
size: 150,
index: 9,
position: 9,
type: 'url',
metadata: {
fieldName: 'xUrl',
@ -184,11 +184,11 @@ export const companiesAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>
export const suppliersAvailableColumnDefinitions: ColumnDefinition<FieldMetadata>[] =
[
{
key: 'name',
name: 'Name',
fieldId: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
size: 180,
index: 0,
position: 0,
type: 'text',
metadata: {
fieldName: 'name',
@ -199,11 +199,11 @@ export const suppliersAvailableColumnDefinitions: ColumnDefinition<FieldMetadata
basePathToShowPage: '/companies/',
} satisfies ColumnDefinition<FieldTextMetadata>,
{
key: 'city',
name: 'City',
fieldId: 'city',
label: 'City',
Icon: IconBuildingSkyscraper,
size: 180,
index: 0,
position: 0,
type: 'text',
metadata: {
fieldName: 'city',

View File

@ -92,8 +92,8 @@ export const useUpdateCompanyBoard = () =>
const pipelineStages = pipeline?.pipelineStages ?? [];
const orderedPipelineStages = [...pipelineStages].sort((a, b) => {
if (!a.index || !b.index) return 0;
return a.index - b.index;
if (!a.position || !b.position) return 0;
return a.position - b.position;
});
const newBoardColumns: BoardColumnDefinition[] =
@ -110,7 +110,7 @@ export const useUpdateCompanyBoard = () =>
colorCode: isThemeColor(pipelineStage.color)
? pipelineStage.color
: undefined,
index: pipelineStage.index ?? 0,
position: pipelineStage.position ?? 0,
};
});
if (currentBoardColumns.length === 0) {

View File

@ -1,5 +1,7 @@
import styled from '@emotion/styled';
import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions';
import { getCompaniesOptimisticEffectDefinition } from '@/companies/graphql/optimistic-effect-definitions/getCompaniesOptimisticEffectDefinition';
import { useCompanyTableActionBarEntries } from '@/companies/hooks/useCompanyTableActionBarEntries';
import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries';
@ -9,10 +11,13 @@ import { DataTableEffect } from '@/ui/data/data-table/components/DataTableEffect
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
import { useUpsertDataTableItem } from '@/ui/data/data-table/hooks/useUpsertDataTableItem';
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
import { ViewBar } from '@/views/components/ViewBar';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { useView } from '@/views/hooks/useView';
import { ViewScope } from '@/views/scopes/ViewScope';
import { columnDefinitionsToViewFields } from '@/views/utils/columnDefinitionToViewField';
import { viewFieldsToColumnDefinitions } from '@/views/utils/viewFieldsToColumnDefinitions';
import {
UpdateOneCompanyMutationVariables,
useGetCompaniesQuery,
@ -26,13 +31,18 @@ import CompanyTableEffect from './CompanyTableEffect';
export const CompanyTable = () => {
const tableViewScopeId = 'company-table';
const setTableColumns = useSetRecoilState(
tableColumnsScopedState('companies'),
);
const [updateEntityMutation] = useUpdateOneCompanyMutation();
const upsertDataTableItem = useUpsertDataTableItem();
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
const { persistViewFields } = useViewFields(tableViewScopeId);
const { setCurrentViewFields } = useView({ viewScopeId: tableViewScopeId });
const { setCurrentViewFields, currentViewId } = useView({
viewScopeId: tableViewScopeId,
});
const { setContextMenuEntries } = useCompanyTableContextMenuEntries();
const { setActionBarEntries } = useCompanyTableActionBarEntries();
@ -77,14 +87,25 @@ export const CompanyTable = () => {
`;
return (
<ViewScope viewScopeId={tableViewScopeId}>
<ViewScope
viewScopeId={tableViewScopeId}
onViewFieldsChange={(viewFields) => {
setTableColumns(
viewFieldsToColumnDefinitions(
viewFields,
companiesAvailableFieldDefinitions,
),
);
}}
onViewFiltersChange={() => {}}
>
<StyledContainer>
<TableContext.Provider
value={{
onColumnsChange: (columns) => {
setCurrentViewFields?.(columns);
persistViewFields(columns);
},
onColumnsChange: useRecoilCallback(() => (columns) => {
setCurrentViewFields?.(columnDefinitionsToViewFields(columns));
persistViewFields(columnDefinitionsToViewFields(columns));
}),
}}
>
<ViewBar

View File

@ -3,13 +3,9 @@ import { useEffect } from 'react';
import { companiesAvailableFieldDefinitions } from '@/companies/constants/companiesAvailableFieldDefinitions';
import { availableTableColumnsScopedState } from '@/ui/data/data-table/states/availableTableColumnsScopedState';
import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
import { tableFiltersScopedState } from '@/ui/data/data-table/states/tableFiltersScopedState';
import { tableSortsScopedState } from '@/ui/data/data-table/states/tableSortsScopedState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useView } from '@/views/hooks/useView';
import { useViewInternalStates } from '@/views/hooks/useViewInternalStates';
import { ViewType } from '~/generated/graphql';
import { ViewType } from '@/views/types/ViewType';
import { companyAvailableFilters } from '~/pages/companies/companies-filters';
import { companyAvailableSorts } from '~/pages/companies/companies-sorts';
@ -21,23 +17,6 @@ const CompanyTableEffect = () => {
setViewType,
setViewObjectId,
} = useView();
const { currentViewFields, currentViewSorts, currentViewFilters } =
useViewInternalStates();
const [, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState,
TableRecoilScopeContext,
);
const [, setTableSorts] = useRecoilScopedState(
tableSortsScopedState,
TableRecoilScopeContext,
);
const [, setTableFilters] = useRecoilScopedState(
tableFiltersScopedState,
TableRecoilScopeContext,
);
const [, setAvailableTableColumns] = useRecoilScopedState(
availableTableColumnsScopedState,
@ -57,33 +36,32 @@ const CompanyTableEffect = () => {
setAvailableFilters,
setAvailableSorts,
setAvailableTableColumns,
setTableColumns,
setViewObjectId,
setViewType,
]);
useEffect(() => {
if (currentViewFields) {
setTableColumns([...currentViewFields].sort((a, b) => a.index - b.index));
}
}, [currentViewFields, setTableColumns]);
// useEffect(() => {
// if (currentViewFields) {
// setTableColumns([...currentViewFields].sort((a, b) => a.index - b.index));
// }
// }, [currentViewFields, setTableColumns]);
useEffect(() => {
if (currentViewSorts) {
setTableSorts(currentViewSorts);
}
}, [currentViewFields, currentViewSorts, setTableColumns, setTableSorts]);
// useEffect(() => {
// if (currentViewSorts) {
// setTableSorts(currentViewSorts);
// }
// }, [currentViewFields, currentViewSorts, setTableColumns, setTableSorts]);
useEffect(() => {
if (currentViewFilters) {
setTableFilters(currentViewFilters);
}
}, [
currentViewFields,
currentViewFilters,
setTableColumns,
setTableFilters,
setTableSorts,
]);
// useEffect(() => {
// if (currentViewFilters) {
// setTableFilters(currentViewFilters);
// }
// }, [
// currentViewFields,
// currentViewFilters,
// setTableColumns,
// setTableFilters,
// setTableSorts,
// ]);
return <></>;
};

View File

@ -1,52 +1,30 @@
import { useNavigate } from 'react-router-dom';
import { IconArchive } from '@/ui/display/icon';
import { IconBuildingSkyscraper } from '@/ui/display/icon';
import { Button } from '@/ui/input/button/components/Button';
import { IconButton } from '@/ui/input/button/components/IconButton';
import NavItem from '@/ui/navigation/navbar/components/NavItem';
import { capitalize } from '~/utils/string/capitalize';
import { useCreateNewTempsCustomObject } from '../hooks/useCreateNewTempCustomObject';
import { useDeleteOneMetadataObject } from '../hooks/useDeleteOneMetadataObject';
import { useFindManyMetadataObjects } from '../hooks/useFindManyMetadataObjects';
export const MetadataObjectNavItems = () => {
const { metadataObjects } = useFindManyMetadataObjects();
const createNewTempCustomObject = useCreateNewTempsCustomObject();
const { deleteOneMetadataObject } = useDeleteOneMetadataObject();
const navigate = useNavigate();
return (
<>
<Button
title="+ Create new object"
variant="secondary"
onClick={createNewTempCustomObject}
/>
{metadataObjects
.filter((metadataObject) => !!metadataObject.isActive)
.map((metadataObject) => (
<div style={{ display: 'flex', flexDirection: 'row', width: '60%' }}>
<IconButton
Icon={IconArchive}
onClick={() => {
deleteOneMetadataObject(metadataObject.id);
}}
/>
<NavItem
key={metadataObject.id}
label={capitalize(metadataObject.namePlural)}
to={`/objects/${metadataObject.namePlural}`}
Icon={IconBuildingSkyscraper}
onClick={() => {
navigate(`/objects/${metadataObject.namePlural}`);
}}
/>
</div>
<NavItem
key={metadataObject.id}
label={capitalize(metadataObject.namePlural)}
to={`/objects/${metadataObject.namePlural}`}
Icon={IconBuildingSkyscraper}
onClick={() => {
navigate(`/objects/${metadataObject.namePlural}`);
}}
/>
))}
</>
);

View File

@ -128,7 +128,7 @@ export const ObjectShowPage = () => {
fieldDefinition:
formatMetadataFieldAsColumnDefinition({
field: metadataField,
index: index,
position: index,
metadataObject: foundMetadataObject,
}),
useUpdateEntityMutation: useUpdateOneObjectMutation,

View File

@ -1,15 +1,9 @@
import styled from '@emotion/styled';
import { useRecoilCallback } from 'recoil';
import { DataTable } from '@/ui/data/data-table/components/DataTable';
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
import { ViewBar } from '@/views/components/ViewBar';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { useView } from '@/views/hooks/useView';
import { ViewScope } from '@/views/scopes/ViewScope';
import { useUpdateOneObject } from '../hooks/useUpdateOneObject';
@ -37,9 +31,6 @@ export const ObjectTable = ({ objectNamePlural }: ObjectTableProps) => {
const viewScopeId = objectNamePlural ?? '';
const { persistViewFields } = useViewFields(viewScopeId);
const { setCurrentViewFields } = useView({ viewScopeId: viewScopeId });
const updateEntity = ({
variables,
}: {
@ -56,27 +47,12 @@ export const ObjectTable = ({ objectNamePlural }: ObjectTableProps) => {
});
};
const updateTableColumns = useRecoilCallback(
({ set, snapshot }) =>
(viewFields: ColumnDefinition<FieldMetadata>[]) => {
set(tableColumnsScopedState(viewScopeId), viewFields);
},
);
return (
<ViewScope
viewScopeId={viewScopeId}
onViewFieldsChange={(viewFields) => {
// updateTableColumns(viewFields);
}}
>
<ViewScope viewScopeId={viewScopeId} onViewFieldsChange={() => {}}>
<StyledContainer>
<TableContext.Provider
value={{
onColumnsChange: (columns) => {
// setCurrentViewFields?.(columns);
// persistViewFields(columns);
},
onColumnsChange: () => {},
}}
>
<ViewBar

View File

@ -3,13 +3,11 @@ import { useSetRecoilState } from 'recoil';
import { availableTableColumnsScopedState } from '@/ui/data/data-table/states/availableTableColumnsScopedState';
import { useView } from '@/views/hooks/useView';
import { ViewType } from '~/generated/graphql';
import { ViewType } from '@/views/types/ViewType';
import { useMetadataObjectInContext } from '../hooks/useMetadataObjectInContext';
export const ObjectTableEffect = () => {
console.log('ObjectTableEffect');
const {
setAvailableSorts,
setAvailableFilters,

View File

@ -1,208 +0,0 @@
import { getOperationName } from '@apollo/client/utilities';
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
import { FieldType } from '@/ui/data/field/types/FieldType';
import { IconBrandLinkedin } from '@/ui/display/icon';
import { GET_VIEW_FIELDS } from '@/views/graphql/queries/getViewFields';
import { GET_VIEWS } from '@/views/graphql/queries/getViews';
import { toViewFieldInput } from '@/views/hooks/internal/useViewFields';
import {
useCreateViewFieldsMutation,
useCreateViewMutation,
ViewType,
} from '~/generated/graphql';
import { useCreateOneMetadataField } from './useCreateOneMetadataField';
import { useCreateOneMetadataObject } from './useCreateOneMetadataObject';
import { useUpdateOneMetadataField } from './useUpdateOneMetadataField';
import { useUpdateOneMetadataObject } from './useUpdateOneMetadataObject';
const useCreateActiveMetadataField = () => {
const { createOneMetadataField } = useCreateOneMetadataField();
const { updateOneMetadataField } = useUpdateOneMetadataField();
return async ({
objectId,
label,
name,
type,
}: {
objectId: string;
label: string;
name: string;
type: FieldType;
}) => {
const { data: createdField } = await createOneMetadataField({
objectId: objectId,
label: label,
name: name,
type: type,
description: label,
icon: 'IconMap',
});
if (!createdField || !createdField.createOneField.name) {
throw new Error('Could not create metadata field');
}
await updateOneMetadataField({
fieldIdToUpdate: createdField?.createOneField?.id ?? '',
updatePayload: {
isActive: true,
},
});
return createdField.createOneField;
};
};
export const useCreateNewTempsCustomObject = () => {
const { createOneMetadataObject } = useCreateOneMetadataObject();
const { updateOneMetadataObject } = useUpdateOneMetadataObject();
const [createViewMutation] = useCreateViewMutation();
const [createViewFieldsMutation] = useCreateViewFieldsMutation();
const createActiveMetadataField = useCreateActiveMetadataField();
return async () => {
const date = new Date().toISOString().replace(/[\/:\.\-\_]/g, '');
const { data: createdMetadataObject } = await createOneMetadataObject({
labelPlural: 'Suppliers' + date,
labelSingular: 'Supplier' + date,
nameSingular: 'supplier' + date,
namePlural: 'suppliers' + date,
description: 'Suppliers' + date,
icon: 'IconBuilding',
});
const supplierObjectId = createdMetadataObject?.createOneObject?.id ?? '';
if (!createdMetadataObject) {
throw new Error('Could not create metadata object');
}
await updateOneMetadataObject({
idToUpdate: supplierObjectId,
updatePayload: {
isActive: true,
},
});
const nameFieldData = await createActiveMetadataField({
label: 'Name',
name: 'name',
objectId: supplierObjectId,
type: 'text',
});
const cityFieldData = await createActiveMetadataField({
label: 'City',
name: 'city',
objectId: supplierObjectId,
type: 'text',
});
const emailFieldData = await createActiveMetadataField({
label: 'Email',
name: 'email',
objectId: supplierObjectId,
type: 'email',
});
const phoneFieldData = await createActiveMetadataField({
label: 'Phone',
name: 'phone',
objectId: supplierObjectId,
type: 'phone',
});
const twitterFieldData = await createActiveMetadataField({
label: 'Twitter',
name: 'twitter',
objectId: supplierObjectId,
type: 'url',
});
const booleanFieldData = await createActiveMetadataField({
label: 'Boolean example',
name: 'boolexample',
objectId: supplierObjectId,
type: 'boolean',
});
const employeesFieldData = await createActiveMetadataField({
label: 'Employees',
name: 'employees',
objectId: supplierObjectId,
type: 'number',
});
const ARRFieldData = await createActiveMetadataField({
label: 'ARR',
name: 'arr',
objectId: supplierObjectId,
type: 'money',
});
const createdAt = await createActiveMetadataField({
label: 'Created at',
name: 'createdAt',
objectId: supplierObjectId,
type: 'date',
});
const objectId = 'suppliers' + date;
const { data: newView } = await createViewMutation({
variables: {
data: {
name: 'Default',
objectId: objectId,
type: ViewType.Table,
},
},
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
});
const createdFields = [
nameFieldData,
emailFieldData,
cityFieldData,
phoneFieldData,
twitterFieldData,
booleanFieldData,
employeesFieldData,
ARRFieldData,
createdAt,
];
const tempColumnDefinitions: ColumnDefinition<FieldMetadata>[] =
createdFields.map((field, index) => ({
index,
key: field.name,
name: field.label,
size: 100,
type: field.type as FieldType,
metadata: {
fieldName: field.name,
placeHolder: field.label,
},
Icon: IconBrandLinkedin,
isVisible: true,
})) ?? [];
await createViewFieldsMutation({
variables: {
data: tempColumnDefinitions.map((column) => ({
...toViewFieldInput(objectId, column),
viewId: newView?.view.id ?? '',
})),
},
refetchQueries: [getOperationName(GET_VIEW_FIELDS) ?? ''],
});
};
};

View File

@ -6,6 +6,7 @@ import {
MetadataObjectsQuery,
MetadataObjectsQueryVariables,
} from '~/generated-metadata/graphql';
import { logError } from '~/utils/logError';
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
import { formatPagedMetadataObjectsToMetadataObjects } from '../utils/formatPagedMetadataObjectsToMetadataObjects';
@ -29,8 +30,7 @@ export const useFindManyMetadataObjects = () => {
client: apolloMetadataClient ?? undefined,
skip: !apolloMetadataClient,
onError: (error) => {
// eslint-disable-next-line no-console
console.error('useFindManyMetadataObjects error : ', error);
logError('useFindManyMetadataObjects error : ' + error);
enqueueSnackBar(
`Error during useFindManyMetadataObjects, ${error.message}`,
{
@ -38,10 +38,7 @@ export const useFindManyMetadataObjects = () => {
},
);
},
onCompleted: (data) => {
// eslint-disable-next-line no-console
//console.log('useFindManyMetadataObjects data : ', data);
},
onCompleted: () => {},
},
);

View File

@ -2,6 +2,7 @@ import { useMemo } from 'react';
import { useQuery } from '@apollo/client';
import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
import { logError } from '~/utils/logError';
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
import { PaginatedObjectType } from '../types/PaginatedObjectType';
@ -41,10 +42,8 @@ export const useFindManyObjects = <
onCompleted: (data) =>
objectNamePlural && onCompleted?.(data[objectNamePlural]),
onError: (error) => {
// eslint-disable-next-line no-console
console.error(
`useFindManyObjects for "${objectNamePlural}" error : `,
error,
logError(
`useFindManyObjects for "${objectNamePlural}" error : ` + error,
);
enqueueSnackBar(
`Error during useFindManyObjects for "${objectNamePlural}", ${error.message}`,

View File

@ -8,6 +8,7 @@ import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFi
import { generateCreateOneObjectMutation } from '../utils/generateCreateOneObjectMutation';
import { generateFindManyCustomObjectsQuery } from '../utils/generateFindManyCustomObjectsQuery';
import { generateFindOneCustomObjectQuery } from '../utils/generateFindOneCustomObjectQuery';
import { generateUpdateOneObjectMutation } from '../utils/generateUpdateOneObjectMutation';
import { useFindManyMetadataObjects } from './useFindManyMetadataObjects';
@ -30,7 +31,7 @@ export const useFindOneMetadataObject = ({
const columnDefinitions: ColumnDefinition<FieldMetadata>[] =
foundMetadataObject?.fields.map((field, index) =>
formatMetadataFieldAsColumnDefinition({
index,
position: index,
field,
metadataObject: foundMetadataObject,
}),
@ -66,6 +67,16 @@ export const useFindOneMetadataObject = ({
}
`;
const updateOneMutation = foundMetadataObject
? generateUpdateOneObjectMutation({
metadataObject: foundMetadataObject,
})
: gql`
mutation EmptyMutation {
empty
}
`;
// TODO: implement backend delete
const deleteOneMutation = foundMetadataObject
? generateCreateOneObjectMutation({
@ -84,6 +95,7 @@ export const useFindOneMetadataObject = ({
findManyQuery,
findOneQuery,
createOneMutation,
updateOneMutation,
deleteOneMutation,
loading,
};

View File

@ -1,8 +1,7 @@
import { gql, useMutation } from '@apollo/client';
import { useMutation } from '@apollo/client';
import { getOperationName } from '@apollo/client/utilities';
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
import { generateUpdateOneObjectMutation } from '../utils/generateUpdateOneObjectMutation';
import { useFindOneMetadataObject } from './useFindOneMetadataObject';
@ -10,24 +9,18 @@ export const useUpdateOneObject = ({
objectNamePlural,
objectNameSingular,
}: MetadataObjectIdentifier) => {
const { foundMetadataObject, objectNotFoundInMetadata, findManyQuery } =
useFindOneMetadataObject({
objectNamePlural,
objectNameSingular,
});
const generatedMutation = foundMetadataObject
? generateUpdateOneObjectMutation({
metadataObject: foundMetadataObject,
})
: gql`
mutation EmptyMutation {
empty
}
`;
const {
foundMetadataObject,
objectNotFoundInMetadata,
findManyQuery,
updateOneMutation,
} = useFindOneMetadataObject({
objectNamePlural,
objectNameSingular,
});
// TODO: type this with a minimal type at least with Record<string, any>
const [mutate] = useMutation(generatedMutation, {
const [mutate] = useMutation(updateOneMutation, {
refetchQueries: [getOperationName(findManyQuery) ?? ''],
});

View File

@ -18,17 +18,17 @@ const parseFieldType = (fieldType: string): FieldType => {
};
export const formatMetadataFieldAsColumnDefinition = ({
index,
position,
field,
metadataObject,
}: {
index: number;
position: number;
field: MetadataObject['fields'][0];
metadataObject: Omit<MetadataObject, 'fields'>;
}): ColumnDefinition<FieldMetadata> => ({
index,
key: field.name,
name: field.label,
position,
fieldId: field.id,
label: field.label,
size: 100,
type: parseFieldType(field.type),
metadata: {

View File

@ -27,11 +27,11 @@ import { getLogoUrlFromDomainName } from '~/utils';
export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[] =
[
{
key: 'displayName',
name: 'People',
fieldId: 'displayName',
label: 'People',
Icon: IconUser,
size: 210,
index: 0,
position: 0,
type: 'double-text-chip',
metadata: {
firstValueFieldName: 'firstName',
@ -45,12 +45,12 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
basePathToShowPage: '/person/',
} satisfies ColumnDefinition<FieldDoubleTextChipMetadata>,
{
key: 'email',
name: 'Email',
fieldId: 'email',
label: 'Email',
Icon: IconMail,
size: 150,
type: 'email',
index: 1,
position: 1,
metadata: {
fieldName: 'email',
placeHolder: 'Email', // Hack: Fake character to prevent password-manager from filling the field
@ -58,11 +58,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
infoTooltipContent: 'Contacts Email.',
} satisfies ColumnDefinition<FieldEmailMetadata>,
{
key: 'company',
name: 'Company',
fieldId: 'company',
label: 'Company',
Icon: IconBuildingSkyscraper,
size: 150,
index: 2,
position: 2,
type: 'relation',
metadata: {
fieldName: 'company',
@ -78,11 +78,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
},
} satisfies ColumnDefinition<FieldRelationMetadata>,
{
key: 'phone',
name: 'Phone',
fieldId: 'phone',
label: 'Phone',
Icon: IconPhone,
size: 150,
index: 3,
position: 3,
type: 'phone',
metadata: {
fieldName: 'phone',
@ -91,11 +91,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
infoTooltipContent: 'Contacts phone number.',
} satisfies ColumnDefinition<FieldPhoneMetadata>,
{
key: 'createdAt',
name: 'Creation',
fieldId: 'createdAt',
label: 'Creation',
Icon: IconCalendarEvent,
size: 150,
index: 4,
position: 4,
type: 'date',
metadata: {
fieldName: 'createdAt',
@ -103,11 +103,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
infoTooltipContent: 'Date when the contact was added.',
} satisfies ColumnDefinition<FieldDateMetadata>,
{
key: 'city',
name: 'City',
fieldId: 'city',
label: 'City',
Icon: IconMap,
size: 150,
index: 5,
position: 5,
type: 'text',
metadata: {
fieldName: 'city',
@ -116,11 +116,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
infoTooltipContent: 'Contacts city.',
} satisfies ColumnDefinition<FieldTextMetadata>,
{
key: 'jobTitle',
name: 'Job title',
fieldId: 'jobTitle',
label: 'Job title',
Icon: IconBriefcase,
size: 150,
index: 6,
position: 6,
type: 'text',
metadata: {
fieldName: 'jobTitle',
@ -129,11 +129,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
infoTooltipContent: 'Contacts job title.',
} satisfies ColumnDefinition<FieldTextMetadata>,
{
key: 'linkedin',
name: 'LinkedIn',
fieldId: 'linkedin',
label: 'LinkedIn',
Icon: IconBrandLinkedin,
size: 150,
index: 7,
position: 7,
type: 'url',
metadata: {
fieldName: 'linkedinUrl',
@ -142,11 +142,11 @@ export const peopleAvailableFieldDefinitions: ColumnDefinition<FieldMetadata>[]
infoTooltipContent: 'Contacts Linkedin account.',
} satisfies ColumnDefinition<FieldURLMetadata>,
{
key: 'x',
name: 'Twitter',
fieldId: 'x',
label: 'Twitter',
Icon: IconBrandX,
size: 150,
index: 8,
position: 8,
type: 'url',
metadata: {
fieldName: 'xUrl',

View File

@ -11,8 +11,6 @@ import { useUpsertDataTableItem } from '@/ui/data/data-table/hooks/useUpsertData
import { TableOptionsDropdown } from '@/ui/data/data-table/options/components/TableOptionsDropdown';
import { ViewBar } from '@/views/components/ViewBar';
import { ViewBarEffect } from '@/views/components/ViewBarEffect';
import { useViewFields } from '@/views/hooks/internal/useViewFields';
import { useView } from '@/views/hooks/useView';
import { ViewScope } from '@/views/scopes/ViewScope';
import {
UpdateOnePersonMutationVariables,
@ -30,9 +28,6 @@ export const PeopleTable = () => {
const [updateEntityMutation] = useUpdateOnePersonMutation();
const upsertDataTableItem = useUpsertDataTableItem();
const { persistViewFields } = useViewFields(tableViewScopeId);
const { setCurrentViewFields } = useView({ viewScopeId: tableViewScopeId });
const { setContextMenuEntries } = usePersonTableContextMenuEntries();
const { setActionBarEntries } = usePersonTableActionBarEntries();
@ -56,10 +51,7 @@ export const PeopleTable = () => {
<StyledContainer>
<TableContext.Provider
value={{
onColumnsChange: (columns) => {
setCurrentViewFields?.(columns);
persistViewFields(columns);
},
onColumnsChange: () => {},
}}
>
<ViewBarEffect />

View File

@ -4,12 +4,9 @@ import { peopleAvailableFieldDefinitions } from '@/people/constants/peopleAvaila
import { availableTableColumnsScopedState } from '@/ui/data/data-table/states/availableTableColumnsScopedState';
import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
import { tableFiltersScopedState } from '@/ui/data/data-table/states/tableFiltersScopedState';
import { tableSortsScopedState } from '@/ui/data/data-table/states/tableSortsScopedState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useView } from '@/views/hooks/useView';
import { useViewInternalStates } from '@/views/hooks/useViewInternalStates';
import { ViewType } from '~/generated/graphql';
import { ViewType } from '@/views/types/ViewType';
import { peopleAvailableFilters } from '~/pages/people/people-filters';
import { peopleAvailableSorts } from '~/pages/people/people-sorts';
@ -21,24 +18,12 @@ const PeopleTableEffect = () => {
setViewType,
setViewObjectId,
} = useView();
const { currentViewFields, currentViewSorts, currentViewFilters } =
useViewInternalStates();
const [, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState,
TableRecoilScopeContext,
);
const [, setTableSorts] = useRecoilScopedState(
tableSortsScopedState,
TableRecoilScopeContext,
);
const [, setTableFilters] = useRecoilScopedState(
tableFiltersScopedState,
TableRecoilScopeContext,
);
const [, setAvailableTableColumns] = useRecoilScopedState(
availableTableColumnsScopedState,
TableRecoilScopeContext,
@ -61,29 +46,29 @@ const PeopleTableEffect = () => {
setViewObjectId,
setViewType,
]);
useEffect(() => {
if (currentViewFields) {
setTableColumns([...currentViewFields].sort((a, b) => a.index - b.index));
}
}, [currentViewFields, setTableColumns]);
// useEffect(() => {
// if (currentViewFields) {
// setTableColumns([...currentViewFields].sort((a, b) => a.index - b.index));
// }
// }, [currentViewFields, setTableColumns]);
useEffect(() => {
if (currentViewSorts) {
setTableSorts(currentViewSorts);
}
}, [currentViewFields, currentViewSorts, setTableColumns, setTableSorts]);
// useEffect(() => {
// if (currentViewSorts) {
// setTableSorts(currentViewSorts);
// }
// }, [currentViewFields, currentViewSorts, setTableColumns, setTableSorts]);
useEffect(() => {
if (currentViewFilters) {
setTableFilters(currentViewFilters);
}
}, [
currentViewFields,
currentViewFilters,
setTableColumns,
setTableFilters,
setTableSorts,
]);
// useEffect(() => {
// if (currentViewFilters) {
// setTableFilters(currentViewFilters);
// }
// }, [
// currentViewFields,
// currentViewFilters,
// setTableColumns,
// setTableFilters,
// setTableSorts,
// ]);
return <></>;
};

View File

@ -18,10 +18,10 @@ import { Person } from '~/generated/graphql';
export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetadata>[] =
[
{
key: 'closeDate',
name: 'Close Date',
fieldId: 'closeDate',
label: 'Close Date',
Icon: IconCalendarEvent,
index: 0,
position: 0,
type: 'date',
metadata: {
fieldName: 'closeDate',
@ -31,10 +31,10 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
'Specified date by which an opportunity must be completed.',
} satisfies BoardFieldDefinition<FieldDateMetadata>,
{
key: 'amount',
name: 'Amount',
fieldId: 'amount',
label: 'Amount',
Icon: IconCurrencyDollar,
index: 1,
position: 1,
type: 'number',
metadata: {
fieldName: 'amount',
@ -44,10 +44,10 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
infoTooltipContent: 'Potential monetary value of a business opportunity.',
} satisfies BoardFieldDefinition<FieldNumberMetadata>,
{
key: 'probability',
name: 'Probability',
fieldId: 'probability',
label: 'Probability',
Icon: IconProgressCheck,
index: 2,
position: 2,
type: 'probability',
metadata: {
fieldName: 'probability',
@ -57,10 +57,10 @@ export const pipelineAvailableFieldDefinitions: BoardFieldDefinition<FieldMetada
"Level of certainty in the lead's potential to convert into a success.",
} satisfies BoardFieldDefinition<FieldProbabilityMetadata>,
{
key: 'pointOfContact',
name: 'Point of Contact',
fieldId: 'pointOfContact',
label: 'Point of Contact',
Icon: IconUser,
index: 3,
position: 3,
type: 'relation',
metadata: {
fieldName: 'pointOfContact',

View File

@ -10,7 +10,7 @@ export const GET_PIPELINES = gql`
id
name
color
index
position
}
}
}

View File

@ -24,7 +24,7 @@ export const usePipelineStages = () => {
data: {
color: boardColumn.colorCode ?? 'gray',
id: boardColumn.id,
index: boardColumn.index,
position: boardColumn.position,
name: boardColumn.title,
pipeline: { connect: { id: currentPipeline.id } },
type: 'ongoing',

View File

@ -44,7 +44,7 @@ export const ColumnHead = ({ column }: ColumnHeadProps) => {
<StyledIcon>
{column.Icon && <column.Icon size={theme.icon.size.md} />}
</StyledIcon>
<StyledText>{column.name}</StyledText>
<StyledText>{column.label}</StyledText>
</StyledTitle>
</>
);

View File

@ -21,7 +21,7 @@ export const ColumnHeadWithDropdown = ({
primaryColumnKey,
}: ColumnHeadWithDropdownProps) => {
return (
<DropdownScope dropdownScopeId={column.key + '-header'}>
<DropdownScope dropdownScopeId={column.fieldId + '-header'}>
<Dropdown
clickableComponent={<ColumnHead column={column} />}
dropdownComponents={
@ -34,7 +34,7 @@ export const ColumnHeadWithDropdown = ({
}
dropdownOffset={{ x: -1 }}
dropdownPlacement="bottom-start"
dropdownHotkeyScope={{ scope: column.key + '-header' }}
dropdownHotkeyScope={{ scope: column.fieldId + '-header' }}
/>
</DropdownScope>
);

View File

@ -51,7 +51,7 @@ export const DataTableCell = ({ cellIndex }: { cellIndex: number }) => {
<td onContextMenu={(event) => handleContextMenu(event)}>
<FieldContext.Provider
value={{
recoilScopeId: currentRowId + columnDefinition.name,
recoilScopeId: currentRowId + columnDefinition.label,
entityId: currentRowId,
fieldDefinition: columnDefinition,
useUpdateEntityMutation: () => [updateEntityMutation, {}],

View File

@ -46,7 +46,7 @@ export const DataTableColumnDropdownMenu = ({
handleColumnVisibilityChange(column);
};
return column.key === primaryColumnKey ? (
return column.fieldId === primaryColumnKey ? (
<></>
) : (
<DropdownMenuItemsContainer>

View File

@ -6,7 +6,6 @@ import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimis
import { OptimisticEffectDefinition } from '@/apollo/optimistic-effect/types/OptimisticEffectDefinition';
import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useView } from '@/views/hooks/useView';
import {
SortOrder,
useGetCompaniesQuery,
@ -40,7 +39,6 @@ export const DataTableEffect = ({
}) => {
const setDataTableData = useSetDataTableData();
const { registerOptimisticEffect } = useOptimisticEffect();
const { setCurrentViewId } = useView();
const tableSortsOrderBy = useRecoilScopedValue(
tableSortsOrderByScopedSelector,

View File

@ -134,7 +134,7 @@ export const DataTableHeader = () => {
if (nextWidth !== tableColumnsByKey[resizedFieldKey].size) {
const nextColumns = tableColumns.map((column) =>
column.key === resizedFieldKey
column.fieldId === resizedFieldKey
? { ...column, size: nextWidth }
: column,
);
@ -152,7 +152,9 @@ export const DataTableHeader = () => {
onMouseUp: handleResizeHandlerEnd,
});
const primaryColumn = visibleTableColumns[0];
const primaryColumn = visibleTableColumns.find(
(column) => column.position === 0,
);
return (
<StyledTableHead data-select-disable>
@ -167,30 +169,32 @@ export const DataTableHeader = () => {
<SelectAllCheckbox />
</th>
{[...visibleTableColumns]
.sort((columnA, columnB) => columnA.index - columnB.index)
.map((column, index) => (
.sort((columnA, columnB) => columnA.position - columnB.position)
.map((column) => (
<StyledColumnHeaderCell
key={column.key}
isResizing={resizedFieldKey === column.key}
key={column.fieldId}
isResizing={resizedFieldKey === column.fieldId}
columnWidth={Math.max(
tableColumnsByKey[column.key].size +
(resizedFieldKey === column.key ? resizeFieldOffset : 0),
tableColumnsByKey[column.fieldId].size +
(resizedFieldKey === column.fieldId ? resizeFieldOffset : 0),
COLUMN_MIN_WIDTH,
)}
>
<StyledColumnHeadContainer>
<ColumnHeadWithDropdown
column={column}
isFirstColumn={index === 1}
isLastColumn={index === visibleTableColumns.length - 1}
primaryColumnKey={primaryColumn.key}
isFirstColumn={column.position === 1}
isLastColumn={
column.position === visibleTableColumns.length - 1
}
primaryColumnKey={primaryColumn?.fieldId || ''}
/>
</StyledColumnHeadContainer>
<StyledResizeHandler
className="cursor-col-resize"
role="separator"
onPointerDown={() => {
setResizedFieldKey(column.key);
setResizedFieldKey(column.fieldId);
}}
/>
</StyledColumnHeaderCell>

View File

@ -34,7 +34,7 @@ export const DataTableHeaderPlusButtonContent = () => {
<DropdownMenuItemsContainer>
{hiddenTableColumns.map((column) => (
<MenuItem
key={column.key}
key={column.fieldId}
iconButtons={[
{
Icon: IconPlus,
@ -42,7 +42,7 @@ export const DataTableHeaderPlusButtonContent = () => {
},
]}
LeftIcon={column.Icon}
text={column.name}
text={column.label}
/>
))}
</DropdownMenuItemsContainer>

View File

@ -39,10 +39,10 @@ export const DataTableRow = forwardRef<HTMLTableRowElement, DataTableRowProps>(
<CheckboxCell />
</td>
{[...visibleTableColumns]
.sort((columnA, columnB) => columnA.index - columnB.index)
.sort((columnA, columnB) => columnA.position - columnB.position)
.map((column, columnIndex) => {
return (
<ColumnContext.Provider value={column} key={column.key}>
<ColumnContext.Provider value={column} key={column.fieldId}>
<DataTableCell cellIndex={columnIndex} />
</ColumnContext.Provider>
);

View File

@ -1,5 +1,5 @@
export const useMoveViewColumns = () => {
const handleColumnMove = <T extends { index: number }>(
const handleColumnMove = <T extends { position: number }>(
direction: 'left' | 'right',
currentArrayindex: number,
targetArray: T[],
@ -19,13 +19,17 @@ export const useMoveViewColumns = () => {
newArray[currentArrayindex] = {
...targetEntity,
index: currentEntity.index,
index: currentEntity.position,
};
newArray[targetArrayIndex] = {
...currentEntity,
index: targetEntity.index,
index: targetEntity.position,
};
return newArray;
return newArray.map((column, index) => ({
...column,
position: index,
}));
}
return targetArray;

View File

@ -4,13 +4,14 @@ import { useSetRecoilState } from 'recoil';
import { useMoveViewColumns } from '@/ui/data/data-table/hooks/useMoveViewColumns';
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useView } from '@/views/hooks/useView';
import { ViewFieldForVisibility } from '@/views/types/ViewFieldForVisibility';
import { TableContext } from '../contexts/TableContext';
import { availableTableColumnsScopedState } from '../states/availableTableColumnsScopedState';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsFamilyState } from '../states/savedTableColumnsFamilyState';
import { visibleTableColumnsScopedSelector } from '../states/selectors/visibleTableColumnsScopedSelector';
import { tableColumnsScopedState } from '../states/tableColumnsScopedState';
import { ColumnDefinition } from '../types/ColumnDefinition';
@ -32,6 +33,10 @@ export const useTableColumns = () => {
TableRecoilScopeContext,
);
const visibleTableColumns = useRecoilScopedValue(
visibleTableColumnsScopedSelector,
TableRecoilScopeContext,
);
const { handleColumnMove } = useMoveViewColumns();
const handleColumnsChange = useCallback(
@ -44,27 +49,18 @@ export const useTableColumns = () => {
[onColumnsChange, setSavedTableColumns, setTableColumns],
);
const handleColumnReorder = useCallback(
async (columns: ColumnDefinition<FieldMetadata>[]) => {
const updatedColumns = columns.map((column, index) => ({
...column,
index,
}));
await handleColumnsChange(updatedColumns);
},
[handleColumnsChange],
);
const handleColumnVisibilityChange = useCallback(
async (viewField: ViewFieldForVisibility) => {
async (
viewField: Omit<ColumnDefinition<FieldMetadata>, 'size' | 'position'>,
) => {
const isNewColumn = !tableColumns.some(
(tableColumns) => tableColumns.key === viewField.key,
(tableColumns) => tableColumns.fieldId === viewField.fieldId,
);
if (isNewColumn) {
const newColumn = availableTableColumns.find(
(availableTableColumn) => availableTableColumn.key === viewField.key,
(availableTableColumn) =>
availableTableColumn.fieldId === viewField.fieldId,
);
if (!newColumn) return;
@ -76,7 +72,7 @@ export const useTableColumns = () => {
await handleColumnsChange(nextColumns);
} else {
const nextColumns = tableColumns.map((previousColumn) =>
previousColumn.key === viewField.key
previousColumn.fieldId === viewField.fieldId
? { ...previousColumn, isVisible: !viewField.isVisible }
: previousColumn,
);
@ -92,18 +88,31 @@ export const useTableColumns = () => {
direction: 'left' | 'right',
column: ColumnDefinition<FieldMetadata>,
) => {
const currentColumnArrayIndex = tableColumns.findIndex(
(tableColumn) => tableColumn.key === column.key,
const currentColumnArrayIndex = visibleTableColumns.findIndex(
(visibleColumn) => visibleColumn.fieldId === column.fieldId,
);
const columns = handleColumnMove(
direction,
currentColumnArrayIndex,
tableColumns,
visibleTableColumns,
);
await handleColumnsChange(columns);
},
[tableColumns, handleColumnMove, handleColumnsChange],
[visibleTableColumns, handleColumnMove, handleColumnsChange],
);
const handleColumnReorder = useCallback(
async (columns: ColumnDefinition<FieldMetadata>[]) => {
const updatedColumns = columns.map((column, index) => ({
...column,
position: index,
}));
await handleColumnsChange(updatedColumns);
},
[handleColumnsChange],
);
return {

View File

@ -59,13 +59,17 @@ export const TableOptionsDropdownContent = ({
const handleReorderField: OnDragEndResponder = useCallback(
(result) => {
if (!result.destination || result.destination.index === 0) {
if (
!result.destination ||
result.destination.index === 1 ||
result.source.index === 1
) {
return;
}
const reorderFields = Array.from(visibleTableColumns);
const [removed] = reorderFields.splice(result.source.index, 1);
reorderFields.splice(result.destination.index, 0, removed);
const reorderFields = [...visibleTableColumns];
const [removed] = reorderFields.splice(result.source.index - 1, 1);
reorderFields.splice(result.destination.index - 1, 0, removed);
handleColumnReorder(reorderFields);
},

View File

@ -9,10 +9,10 @@ export const hiddenTableColumnsScopedSelector = selectorFamily({
(scopeId: string) =>
({ get }) => {
const columns = get(tableColumnsScopedState(scopeId));
const columnKeys = columns.map(({ key }) => key);
const columnKeys = columns.map(({ fieldId }) => fieldId);
const otherAvailableColumns = get(
availableTableColumnsScopedState(scopeId),
).filter(({ key }) => !columnKeys.includes(key));
).filter(({ fieldId }) => !columnKeys.includes(fieldId));
return [
...columns.filter((column) => !column.isVisible),

View File

@ -12,5 +12,5 @@ export const savedTableColumnsByKeyFamilySelector = selectorFamily({
({ get }) =>
get(savedTableColumnsFamilyState(viewId)).reduce<
Record<string, ColumnDefinition<FieldMetadata>>
>((result, column) => ({ ...result, [column.key]: column }), {}),
>((result, column) => ({ ...result, [column.fieldId]: column }), {}),
});

View File

@ -12,5 +12,5 @@ export const tableColumnsByKeyScopedSelector = selectorFamily({
({ get }) =>
get(tableColumnsScopedState(scopeId)).reduce<
Record<string, ColumnDefinition<FieldMetadata>>
>((result, column) => ({ ...result, [column.key]: column }), {}),
>((result, column) => ({ ...result, [column.fieldId]: column }), {}),
});

View File

@ -7,7 +7,9 @@ export const visibleTableColumnsScopedSelector = selectorFamily({
get:
(scopeId: string) =>
({ get }) =>
get(tableColumnsScopedState(scopeId)).filter(
(column) => column.isVisible,
),
[
...get(tableColumnsScopedState(scopeId)).filter(
(column) => column.isVisible,
),
].sort((a, b) => a.position - b.position),
});

View File

@ -3,6 +3,7 @@ import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
export type ColumnDefinition<T extends FieldMetadata> = FieldDefinition<T> & {
size: number;
index: number;
position: number;
isVisible?: boolean;
viewFieldId?: string;
};

View File

@ -10,8 +10,8 @@ export const useIsFieldEmpty = () => {
const isFieldEmpty = useRecoilValue(
isEntityFieldEmptyFamilySelector({
fieldDefinition: {
key: fieldDefinition.key,
name: fieldDefinition.name,
fieldId: fieldDefinition.fieldId,
label: fieldDefinition.label,
type: fieldDefinition.type,
metadata: fieldDefinition.metadata,
},

View File

@ -31,8 +31,8 @@ const DateFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'date',
name: 'Date',
fieldId: 'date',
label: 'Date',
type: 'date',
metadata: {
fieldName: 'Date',

View File

@ -38,8 +38,8 @@ const DoubleTextFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'double-text',
name: 'Double-Text',
fieldId: 'double-text',
label: 'Double-Text',
type: 'double-text',
metadata: {
firstValueFieldName: 'First-text',

View File

@ -30,8 +30,8 @@ const EmailFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'email',
name: 'Email',
fieldId: 'email',
label: 'Email',
type: 'email',
metadata: {
fieldName: 'Email',

View File

@ -32,8 +32,8 @@ const MoneyFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'money',
name: 'Money',
fieldId: 'money',
label: 'Money',
type: 'moneyAmount',
metadata: {
fieldName: 'Amount',

View File

@ -32,8 +32,8 @@ const NumberFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'number',
name: 'Number',
fieldId: 'number',
label: 'Number',
type: 'number',
metadata: {
fieldName: 'Number',

View File

@ -30,8 +30,8 @@ const PhoneFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'phone',
name: 'Phone',
fieldId: 'phone',
label: 'Phone',
type: 'phone',
metadata: {
fieldName: 'Phone',

View File

@ -32,8 +32,8 @@ const TextFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'text',
name: 'Text',
fieldId: 'text',
label: 'Text',
type: 'text',
metadata: {
fieldName: 'Text',

View File

@ -30,8 +30,8 @@ const URLFieldDisplayWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'URL',
name: 'URL',
fieldId: 'URL',
label: 'URL',
type: 'url',
metadata: {
fieldName: 'URL',

View File

@ -34,8 +34,8 @@ const BooleanFieldInputWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'boolean',
name: 'Boolean',
fieldId: 'boolean',
label: 'Boolean',
type: 'boolean',
metadata: {
fieldName: 'Boolean',

View File

@ -44,8 +44,8 @@ const ChipFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'chip',
name: 'Chip',
fieldId: 'chip',
label: 'Chip',
type: 'chip',
metadata: {
contentFieldName: 'name',

View File

@ -44,8 +44,8 @@ const DateFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'date',
name: 'Date',
fieldId: 'date',
label: 'Date',
type: 'date',
metadata: {
fieldName: 'Date',

View File

@ -57,8 +57,8 @@ const DoubleTextChipFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'double-text-chip',
name: 'Double-Text-Chip',
fieldId: 'double-text-chip',
label: 'Double-Text-Chip',
type: 'double-text-chip',
metadata: {
firstValueFieldName: 'First-text',

View File

@ -55,8 +55,8 @@ const DoubleTextFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'double-text',
name: 'Double-Text',
fieldId: 'double-text',
label: 'Double-Text',
type: 'double-text',
metadata: {
firstValueFieldName: 'First-text',

View File

@ -43,8 +43,8 @@ const EmailFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'email',
name: 'Email',
fieldId: 'email',
label: 'Email',
type: 'email',
metadata: {
fieldName: 'email',

View File

@ -43,8 +43,8 @@ const MoneyFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'moneyAmount',
name: 'MoneyAmout',
fieldId: 'moneyAmount',
label: 'MoneyAmout',
type: 'moneyAmount',
metadata: {
fieldName: 'moneyAmount',

View File

@ -43,8 +43,8 @@ const NumberFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'number',
name: 'Number',
fieldId: 'number',
label: 'Number',
type: 'number',
metadata: {
fieldName: 'number',

View File

@ -43,8 +43,8 @@ const PhoneFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'phone',
name: 'Phone',
fieldId: 'phone',
label: 'Phone',
type: 'phone',
metadata: {
fieldName: 'Phone',

View File

@ -41,8 +41,8 @@ const ProbabilityFieldInputWithContext = ({
return (
<FieldContextProvider
fieldDefinition={{
key: 'probability',
name: 'Probability',
fieldId: 'probability',
label: 'Probability',
type: 'probability',
metadata: {
fieldName: 'Probability',

View File

@ -46,8 +46,8 @@ const RelationFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'relation',
name: 'Relation',
fieldId: 'relation',
label: 'Relation',
type: 'relation',
metadata: {
fieldName: 'Relation',

View File

@ -43,8 +43,8 @@ const TextFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'text',
name: 'Text',
fieldId: 'text',
label: 'Text',
type: 'text',
metadata: {
fieldName: 'Text',

View File

@ -43,8 +43,8 @@ const URLFieldInputWithContext = ({
<div>
<FieldContextProvider
fieldDefinition={{
key: 'url',
name: 'URL',
fieldId: 'url',
label: 'URL',
type: 'url',
metadata: {
fieldName: 'URL',

View File

@ -23,7 +23,7 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({
}: {
fieldDefinition: Pick<
FieldDefinition<FieldMetadata>,
'type' | 'metadata' | 'key' | 'name'
'type' | 'metadata' | 'fieldId' | 'label'
>;
entityId: string;
}) => {

View File

@ -5,8 +5,8 @@ import { FieldMetadata } from './FieldMetadata';
import { FieldType } from './FieldType';
export type FieldDefinition<T extends FieldMetadata> = {
key: string;
name: string;
fieldId: string;
label: string;
Icon?: IconComponent;
type: FieldType;
metadata: T;

View File

@ -6,7 +6,7 @@ import { SingleEntitySelectBase } from '@/ui/input/relation-picker/components/Si
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
import { useRemoveFilter } from '@/views/hooks/useRemoveFilter';
import { useUpsertFilter } from '@/views/hooks/useUpsertFilter';
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useFilter } from '../hooks/useFilter';

View File

@ -1,6 +1,6 @@
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useUpsertFilter } from '../../../../views/hooks/useUpsertFilter';
import { useFilter } from '../hooks/useFilter';

View File

@ -6,7 +6,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useFilter } from '../hooks/useFilter';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';

View File

@ -1,5 +1,5 @@
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
export const selectedOperandInDropdownScopedState =
createScopedState<ViewFilterOperand | null>({

View File

@ -1,4 +1,4 @@
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { FilterType } from './FilterType';

View File

@ -1 +1 @@
export { ViewFilterOperand as FilterOperand } from '~/generated/graphql';
export { ViewFilterOperand as FilterOperand } from '@/views/types/ViewFilterOperand';

View File

@ -1,4 +1,4 @@
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
export const getOperandLabel = (
operand: ViewFilterOperand | null | undefined,

View File

@ -1,4 +1,4 @@
import { ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { FilterType } from '../types/FilterType';

View File

@ -1,4 +1,5 @@
import { QueryMode, ViewFilterOperand } from '~/generated/graphql';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { QueryMode } from '~/generated/graphql';
import { Filter } from '../types/Filter';

View File

@ -49,7 +49,7 @@ type BoardOptionsMenu = 'fields' | 'stage-creation' | 'stages';
type ColumnForCreate = {
id: string;
colorCode: ThemeColor;
index: number;
position: number;
title: string;
};
@ -93,7 +93,7 @@ export const BoardOptionsDropdownContent = ({
const columnToCreate: ColumnForCreate = {
id: v4(),
colorCode: 'gray',
index: boardColumns.length,
position: boardColumns.length,
title: stageInputRef.current.value,
};

View File

@ -132,7 +132,7 @@ export const EntityBoard = ({
);
const sortedBoardColumns = [...boardColumns].sort((a, b) => {
return a.index - b.index;
return a.position - b.position;
});
const boardRef = useRef<HTMLDivElement>(null);
@ -155,8 +155,9 @@ export const EntityBoard = ({
value={{
id: column.id,
columnDefinition: column,
isFirstColumn: column.index === 0,
isLastColumn: column.index === sortedBoardColumns.length - 1,
isFirstColumn: column.position === 0,
isLastColumn:
column.position === sortedBoardColumns.length - 1,
}}
>
<RecoilScope

View File

@ -1,5 +1,6 @@
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { ViewFieldForVisibility } from '@/views/types/ViewFieldForVisibility';
import { boardCardFieldsScopedState } from '../states/boardCardFieldsScopedState';
@ -13,10 +14,12 @@ export const useBoardCardFields = () => {
BoardRecoilScopeContext,
);
const handleFieldVisibilityChange = (field: ViewFieldForVisibility) => {
const handleFieldVisibilityChange = (
field: Omit<ColumnDefinition<FieldMetadata>, 'size' | 'position'>,
) => {
setBoardCardFields((previousFields) =>
previousFields.map((previousField) =>
previousField.key === field.key
previousField.fieldId === field.fieldId
? { ...previousField, isVisible: !field.isVisible }
: previousField,
),

View File

@ -21,7 +21,7 @@ export const useBoardColumns = () => {
updatePipelineStageMutation({
variables: {
data: {
index: stage.index,
position: stage.position,
},
id: stage.id,
},

View File

@ -12,5 +12,5 @@ export const boardCardFieldsByKeyScopedSelector = selectorFamily({
({ get }) =>
get(boardCardFieldsScopedState(scopeId)).reduce<
Record<string, BoardFieldDefinition<FieldMetadata>>
>((result, field) => ({ ...result, [field.key]: field }), {}),
>((result, field) => ({ ...result, [field.fieldId]: field }), {}),
});

View File

@ -9,10 +9,10 @@ export const hiddenBoardCardFieldsScopedSelector = selectorFamily({
(scopeId: string) =>
({ get }) => {
const fields = get(boardCardFieldsScopedState(scopeId));
const fieldKeys = fields.map(({ key }) => key);
const fieldKeys = fields.map(({ fieldId }) => fieldId);
const otherAvailableKeys = get(
availableBoardCardFieldsScopedState(scopeId),
).filter(({ key }) => !fieldKeys.includes(key));
).filter(({ fieldId }) => !fieldKeys.includes(fieldId));
return [
...fields.filter((field) => !field.isVisible),

View File

@ -12,5 +12,5 @@ export const savedBoardCardFieldsByKeyFamilySelector = selectorFamily({
({ get }) =>
get(savedBoardCardFieldsFamilyState(viewId)).reduce<
Record<string, BoardFieldDefinition<FieldMetadata>>
>((result, field) => ({ ...result, [field.key]: field }), {}),
>((result, field) => ({ ...result, [field.fieldId]: field }), {}),
});

View File

@ -3,6 +3,6 @@ import { ThemeColor } from '@/ui/theme/constants/colors';
export type BoardColumnDefinition = {
id: string;
title: string;
index: number;
position: number;
colorCode?: ThemeColor;
};

View File

@ -3,6 +3,6 @@ import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
export type BoardFieldDefinition<T extends FieldMetadata> =
FieldDefinition<T> & {
index: number;
position: number;
isVisible?: boolean;
};

View File

@ -4,25 +4,14 @@ import { useRecoilCallback } from 'recoil';
import { useFindManyObjects } from '@/metadata/hooks/useFindManyObjects';
import { PaginatedObjectTypeResults } from '@/metadata/types/PaginatedObjectTypeResults';
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
import { Filter } from '@/ui/data/filter/types/Filter';
import { Sort } from '@/ui/data/sort/types/Sort';
import {
useGetViewFiltersQuery,
useGetViewSortsQuery,
} from '~/generated/graphql';
import { assertNotNull } from '~/utils/assert';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { useView } from '../hooks/useView';
import { useViewInternalStates } from '../hooks/useViewInternalStates';
import { availableFieldsScopedState } from '../states/availableFieldsScopedState';
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
import { availableSortsScopedState } from '../states/availableSortsScopedState';
import { onViewFieldsChangeScopedState } from '../states/onViewFieldsChangeScopedState';
import { savedViewFieldsScopedFamilyState } from '../states/savedViewFieldsScopedFamilyState';
import { savedViewFiltersScopedFamilyState } from '../states/savedViewFiltersScopedFamilyState';
import { savedViewSortsScopedFamilyState } from '../states/savedViewSortsScopedFamilyState';
import { viewsScopedState } from '../states/viewsScopedState';
import { View } from '../types/View';
import { ViewField } from '../types/ViewField';
@ -32,10 +21,6 @@ export const ViewBarEffect = () => {
scopeId: viewScopeId,
setCurrentViewFields,
setSavedViewFields,
setCurrentViewSorts,
setSavedViewSorts,
setCurrentViewFilters,
setSavedViewFilters,
currentViewId,
setViews,
changeView,
@ -56,6 +41,12 @@ export const ViewBarEffect = () => {
.getLoadable(availableFieldsScopedState({ scopeId: viewScopeId }))
.getValue();
const onViewFieldsChange = snapshot
.getLoadable(
onViewFieldsChangeScopedState({ scopeId: viewScopeId }),
)
.getValue();
if (!availableFields || !currentViewId) {
return;
}
@ -70,27 +61,13 @@ export const ViewBarEffect = () => {
.getValue();
const queriedViewFields = data.edges
.map<ColumnDefinition<FieldMetadata> | null>((viewField) => {
const columnDefinition = availableFields.find(
({ key }) => viewField.node.fieldId === key,
);
return columnDefinition
? {
...columnDefinition,
key: viewField.node.fieldId,
name: viewField.node.fieldId,
index: viewField.node.position,
size: viewField.node.size ?? columnDefinition.size,
isVisible: viewField.node.isVisible,
}
: null;
})
.filter<ColumnDefinition<FieldMetadata>>(assertNotNull);
.map((viewField) => viewField.node)
.filter(assertNotNull);
if (!isDeeplyEqual(savedViewFields, queriedViewFields)) {
setCurrentViewFields?.(queriedViewFields);
setSavedViewFields?.(queriedViewFields);
onViewFieldsChange?.(queriedViewFields);
}
},
),
@ -115,108 +92,108 @@ export const ViewBarEffect = () => {
if (!nextViews.length) return;
if (!currentViewId) return setCurrentViewId(nextViews[0].id);
if (!currentViewId) return changeView(nextViews[0].id);
},
),
});
useGetViewSortsQuery({
skip: !currentViewId,
variables: {
where: {
viewId: { equals: currentViewId },
},
},
onCompleted: useRecoilCallback(({ snapshot }) => async (data) => {
const availableSorts = snapshot
.getLoadable(availableSortsScopedState({ scopeId: viewScopeId }))
.getValue();
// useGetViewSortsQuery({
// skip: !currentViewId,
// variables: {
// where: {
// viewId: { equals: currentViewId },
// },
// },
// onCompleted: useRecoilCallback(({ snapshot }) => async (data) => {
// const availableSorts = snapshot
// .getLoadable(availableSortsScopedState({ scopeId: viewScopeId }))
// .getValue();
if (!availableSorts || !currentViewId) {
return;
}
// if (!availableSorts || !currentViewId) {
// return;
// }
const savedViewSorts = snapshot
.getLoadable(
savedViewSortsScopedFamilyState({
scopeId: viewScopeId,
familyKey: currentViewId,
}),
)
.getValue();
// const savedViewSorts = snapshot
// .getLoadable(
// savedViewSortsScopedFamilyState({
// scopeId: viewScopeId,
// familyKey: currentViewId,
// }),
// )
// .getValue();
const queriedViewSorts = data.viewSorts
.map((viewSort) => {
const foundCorrespondingSortDefinition = availableSorts.find(
(sort) => sort.key === viewSort.key,
);
// const queriedViewSorts = data.viewSorts
// .map((viewSort) => {
// const foundCorrespondingSortDefinition = availableSorts.find(
// (sort) => sort.key === viewSort.key,
// );
if (foundCorrespondingSortDefinition) {
return {
key: viewSort.key,
definition: foundCorrespondingSortDefinition,
direction: viewSort.direction.toLowerCase(),
} as Sort;
} else {
return undefined;
}
})
.filter((sort): sort is Sort => !!sort);
// if (foundCorrespondingSortDefinition) {
// return {
// key: viewSort.key,
// definition: foundCorrespondingSortDefinition,
// direction: viewSort.direction.toLowerCase(),
// } as Sort;
// } else {
// return undefined;
// }
// })
// .filter((sort): sort is Sort => !!sort);
if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
setSavedViewSorts?.(queriedViewSorts);
setCurrentViewSorts?.(queriedViewSorts);
}
}),
});
// if (!isDeeplyEqual(savedViewSorts, queriedViewSorts)) {
// setSavedViewSorts?.(queriedViewSorts);
// setCurrentViewSorts?.(queriedViewSorts);
// }
// }),
// });
useGetViewFiltersQuery({
skip: !currentViewId,
variables: {
where: {
viewId: { equals: currentViewId },
},
},
onCompleted: useRecoilCallback(({ snapshot }) => (data) => {
const availableFilters = snapshot
.getLoadable(availableFiltersScopedState({ scopeId: viewScopeId }))
.getValue();
// useGetViewFiltersQuery({
// skip: !currentViewId,
// variables: {
// where: {
// viewId: { equals: currentViewId },
// },
// },
// onCompleted: useRecoilCallback(({ snapshot }) => (data) => {
// const availableFilters = snapshot
// .getLoadable(availableFiltersScopedState({ scopeId: viewScopeId }))
// .getValue();
if (!availableFilters || !currentViewId) {
return;
}
// if (!availableFilters || !currentViewId) {
// return;
// }
const savedViewFilters = snapshot
.getLoadable(
savedViewFiltersScopedFamilyState({
scopeId: viewScopeId,
familyKey: currentViewId,
}),
)
.getValue();
// const savedViewFilters = snapshot
// .getLoadable(
// savedViewFiltersScopedFamilyState({
// scopeId: viewScopeId,
// familyKey: currentViewId,
// }),
// )
// .getValue();
const queriedViewFilters = data.viewFilters
.map(({ __typename, name: _name, ...viewFilter }) => {
const availableFilter = availableFilters.find(
(filter) => filter.key === viewFilter.key,
);
// const queriedViewFilters = data.viewFilters
// .map(({ __typename, name: _name, ...viewFilter }) => {
// const availableFilter = availableFilters.find(
// (filter) => filter.key === viewFilter.key,
// );
return availableFilter
? {
...viewFilter,
displayValue: viewFilter.displayValue ?? viewFilter.value,
type: availableFilter.type,
}
: undefined;
})
.filter((filter): filter is Filter => !!filter);
// return availableFilter
// ? {
// ...viewFilter,
// displayValue: viewFilter.displayValue ?? viewFilter.value,
// type: availableFilter.type,
// }
// : undefined;
// })
// .filter((filter): filter is Filter => !!filter);
if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
setSavedViewFilters?.(queriedViewFilters);
setCurrentViewFilters?.(queriedViewFilters);
}
}),
});
// if (!isDeeplyEqual(savedViewFilters, queriedViewFilters)) {
// setSavedViewFilters?.(queriedViewFilters);
// setCurrentViewFilters?.(queriedViewFilters);
// }
// }),
// });
const currentViewIdFromUrl = searchParams.get('view');

View File

@ -6,6 +6,8 @@ import {
ResponderProvided,
} from '@hello-pangea/dnd';
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
import { IconMinus, IconPlus } from '@/ui/display/icon';
import { AppTooltip } from '@/ui/display/tooltip/AppTooltip';
import { IconInfoCircle } from '@/ui/input/constants/icons';
@ -18,11 +20,11 @@ import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItem
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isDefined } from '~/utils/isDefined';
import { ViewFieldForVisibility } from '../types/ViewFieldForVisibility';
type ViewFieldsVisibilityDropdownSectionProps = {
fields: ViewFieldForVisibility[];
onVisibilityChange: (field: ViewFieldForVisibility) => void;
fields: Omit<ColumnDefinition<FieldMetadata>, 'size'>[];
onVisibilityChange: (
field: Omit<ColumnDefinition<FieldMetadata>, 'size' | 'position'>,
) => void;
title: string;
isDraggable: boolean;
onDragEnd?: OnDragEndResponder;
@ -46,7 +48,10 @@ export const ViewFieldsVisibilityDropdownSection = ({
else setOpenToolTipIndex(index);
};
const getIconButtons = (index: number, field: ViewFieldForVisibility) => {
const getIconButtons = (
index: number,
field: Omit<ColumnDefinition<FieldMetadata>, 'size' | 'position'>,
) => {
if (field.infoTooltipContent) {
return [
{
@ -88,20 +93,20 @@ export const ViewFieldsVisibilityDropdownSection = ({
onDragEnd={handleOnDrag}
draggableItems={
<>
{fields
.filter(({ index, size }) => index !== 0 || !size)
{[...fields]
.sort((a, b) => a.position - b.position)
.map((field, index) => (
<DraggableItem
key={field.key}
draggableId={field.key}
key={field.fieldId}
draggableId={field.fieldId}
index={index + 1}
itemComponent={
<MenuItemDraggable
key={field.key}
key={field.fieldId}
LeftIcon={field.Icon}
iconButtons={getIconButtons(index + 1, field)}
isTooltipOpen={openToolTipIndex === index + 1}
text={field.name}
text={field.label}
className={`${title}-draggable-item-tooltip-anchor-${
index + 1
}`}
@ -115,11 +120,11 @@ export const ViewFieldsVisibilityDropdownSection = ({
) : (
fields.map((field, index) => (
<MenuItem
key={field.key}
key={field.fieldId}
LeftIcon={field.Icon}
iconButtons={getIconButtons(index, field)}
isTooltipOpen={openToolTipIndex === index}
text={field.name}
text={field.label}
className={`${title}-fixed-item-tooltip-anchor-${index}`}
/>
))

View File

@ -1,12 +0,0 @@
import { gql } from '@apollo/client';
export const VIEW_FIELD_FRAGMENT = gql`
fragment ViewFieldFragment on ViewField {
index
isVisible
key
name
size
viewId
}
`;

View File

@ -1,10 +0,0 @@
import { gql } from '@apollo/client';
export const CREATE_VIEW = gql`
mutation CreateView($data: ViewCreateInput!) {
view: createOneView(data: $data) {
id
name
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const CREATE_VIEW_FIELDS = gql`
mutation CreateViewFields($data: [ViewFieldCreateManyInput!]!) {
createManyViewField(data: $data) {
count
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const CREATE_VIEW_FILTERS = gql`
mutation CreateViewFilters($data: [ViewFilterCreateManyInput!]!) {
createManyViewFilter(data: $data) {
count
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const CREATE_VIEW_SORTS = gql`
mutation CreateViewSorts($data: [ViewSortCreateManyInput!]!) {
createManyViewSort(data: $data) {
count
}
}
`;

View File

@ -1,10 +0,0 @@
import { gql } from '@apollo/client';
export const DELETE_VIEW = gql`
mutation DeleteView($where: ViewWhereUniqueInput!) {
view: deleteOneView(where: $where) {
id
name
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const DELETE_VIEW_FILTERS = gql`
mutation DeleteViewFilters($where: ViewFilterWhereInput!) {
deleteManyViewFilter(where: $where) {
count
}
}
`;

View File

@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const DELETE_VIEW_SORTS = gql`
mutation DeleteViewSorts($where: ViewSortWhereInput!) {
deleteManyViewSort(where: $where) {
count
}
}
`;

View File

@ -1,10 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_VIEW = gql`
mutation UpdateView($data: ViewUpdateInput!, $where: ViewWhereUniqueInput!) {
view: updateOneView(data: $data, where: $where) {
id
name
}
}
`;

View File

@ -1,12 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_VIEW_FIELD = gql`
mutation UpdateViewField(
$data: ViewFieldUpdateInput!
$where: ViewFieldWhereUniqueInput!
) {
updateOneViewField(data: $data, where: $where) {
...ViewFieldFragment
}
}
`;

View File

@ -1,16 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_VIEW_FILTER = gql`
mutation UpdateViewFilter(
$data: ViewFilterUpdateInput!
$where: ViewFilterWhereUniqueInput!
) {
viewFilter: updateOneViewFilter(data: $data, where: $where) {
displayValue
key
name
operand
value
}
}
`;

View File

@ -1,14 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_VIEW_SORT = gql`
mutation UpdateViewSort(
$data: ViewSortUpdateInput!
$where: ViewSortWhereUniqueInput!
) {
viewSort: updateOneViewSort(data: $data, where: $where) {
direction
key
name
}
}
`;

View File

@ -1,12 +0,0 @@
import { gql } from '@apollo/client';
export const GET_VIEW_FIELDS = gql`
query GetViewFields(
$where: ViewFieldWhereInput
$orderBy: [ViewFieldOrderByWithRelationInput!]
) {
viewFields: findManyViewField(where: $where, orderBy: $orderBy) {
...ViewFieldFragment
}
}
`;

View File

@ -1,13 +0,0 @@
import { gql } from '@apollo/client';
export const GET_VIEW_FILTERS = gql`
query GetViewFilters($where: ViewFilterWhereInput) {
viewFilters: findManyViewFilter(where: $where) {
displayValue
key
name
operand
value
}
}
`;

View File

@ -1,11 +0,0 @@
import { gql } from '@apollo/client';
export const GET_VIEW_SORTS = gql`
query GetViewSorts($where: ViewSortWhereInput) {
viewSorts: findManyViewSort(where: $where) {
direction
key
name
}
}
`;

Some files were not shown because too many files have changed in this diff Show More