Board V2 - Part 1 (#2619)
* improve useComputeDefinitionsFromFieldMetadata to prevent infinit loops * fix viewFields * improve initial seeding * fix height 100% * fix filters and sorts * allow filter on currency * remove probability from filter * fix opportunities count * fix persist filters and sorts
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
||||||
import { BoardOptionsDropdown } from '@/ui/layout/board/components/BoardOptionsDropdown';
|
import { BoardOptionsDropdown } from '@/ui/layout/board/components/BoardOptionsDropdown';
|
||||||
@ -10,6 +11,7 @@ import {
|
|||||||
import { EntityBoardActionBar } from '@/ui/layout/board/components/EntityBoardActionBar';
|
import { EntityBoardActionBar } from '@/ui/layout/board/components/EntityBoardActionBar';
|
||||||
import { EntityBoardContextMenu } from '@/ui/layout/board/components/EntityBoardContextMenu';
|
import { EntityBoardContextMenu } from '@/ui/layout/board/components/EntityBoardContextMenu';
|
||||||
import { ViewBar } from '@/views/components/ViewBar';
|
import { ViewBar } from '@/views/components/ViewBar';
|
||||||
|
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
|
||||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||||
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
|
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
|
||||||
|
|
||||||
@ -35,8 +37,32 @@ export const CompanyBoard = ({
|
|||||||
onEditColumnTitle,
|
onEditColumnTitle,
|
||||||
}: CompanyBoardProps) => {
|
}: CompanyBoardProps) => {
|
||||||
const viewScopeId = 'company-board-view';
|
const viewScopeId = 'company-board-view';
|
||||||
|
|
||||||
|
const {
|
||||||
|
currentViewFieldsState,
|
||||||
|
currentViewFiltersState,
|
||||||
|
currentViewSortsState,
|
||||||
|
} = useViewScopedStates({
|
||||||
|
customViewScopeId: viewScopeId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setCurrentViewFields = useSetRecoilState(currentViewFieldsState);
|
||||||
|
const setCurrentViewFilters = useSetRecoilState(currentViewFiltersState);
|
||||||
|
const setCurrentViewSorts = useSetRecoilState(currentViewSortsState);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewScope viewScopeId={viewScopeId}>
|
<ViewScope
|
||||||
|
viewScopeId={viewScopeId}
|
||||||
|
onViewFieldsChange={(viewFields) => {
|
||||||
|
setCurrentViewFields(viewFields);
|
||||||
|
}}
|
||||||
|
onViewFiltersChange={(viewFilters) => {
|
||||||
|
setCurrentViewFilters(viewFilters);
|
||||||
|
}}
|
||||||
|
onViewSortsChange={(viewSorts) => {
|
||||||
|
setCurrentViewSorts(viewSorts);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<BoardContext.Provider
|
<BoardContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { Company } from '@/companies/types/Company';
|
import { Company } from '@/companies/types/Company';
|
||||||
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
|
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
|
||||||
@ -16,13 +15,16 @@ import { useBoardContextMenuEntries } from '@/ui/layout/board/hooks/useBoardCont
|
|||||||
import { availableBoardCardFieldsScopedState } from '@/ui/layout/board/states/availableBoardCardFieldsScopedState';
|
import { availableBoardCardFieldsScopedState } from '@/ui/layout/board/states/availableBoardCardFieldsScopedState';
|
||||||
import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState';
|
import { boardCardFieldsScopedState } from '@/ui/layout/board/states/boardCardFieldsScopedState';
|
||||||
import { isBoardLoadedState } from '@/ui/layout/board/states/isBoardLoadedState';
|
import { isBoardLoadedState } from '@/ui/layout/board/states/isBoardLoadedState';
|
||||||
|
import { turnFiltersIntoWhereClauseV2 } from '@/ui/object/object-filter-dropdown/utils/turnFiltersIntoWhereClauseV2';
|
||||||
|
import { turnSortsIntoOrderByV2 } from '@/ui/object/object-sort-dropdown/utils/turnSortsIntoOrderByV2';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
|
import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2';
|
||||||
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
|
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
|
||||||
import { useView } from '@/views/hooks/useView';
|
import { useView } from '@/views/hooks/useView';
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
|
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
|
||||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||||
|
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||||
|
|
||||||
import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
|
import { useUpdateCompanyBoardCardIds } from '../hooks/useUpdateBoardCardIds';
|
||||||
import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
|
import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
|
||||||
@ -37,13 +39,19 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
setViewType,
|
setViewType,
|
||||||
} = useView();
|
} = useView();
|
||||||
|
|
||||||
const { currentViewFieldsState } = useViewScopedStates();
|
const {
|
||||||
|
currentViewFieldsState,
|
||||||
|
currentViewFiltersState,
|
||||||
|
currentViewSortsState,
|
||||||
|
} = useViewScopedStates();
|
||||||
|
|
||||||
const [pipelineSteps, setPipelineSteps] = useState<PipelineStep[]>([]);
|
const [pipelineSteps, setPipelineSteps] = useState<PipelineStep[]>([]);
|
||||||
const [opportunities, setOpportunities] = useState<Opportunity[]>([]);
|
const [opportunities, setOpportunities] = useState<Opportunity[]>([]);
|
||||||
const [companies, setCompanies] = useState<Company[]>([]);
|
const [companies, setCompanies] = useState<Company[]>([]);
|
||||||
|
|
||||||
const currentViewFields = useRecoilValue(currentViewFieldsState);
|
const currentViewFields = useRecoilValue(currentViewFieldsState);
|
||||||
|
const currentViewFilters = useRecoilValue(currentViewFiltersState);
|
||||||
|
const currentViewSorts = useRecoilValue(currentViewSortsState);
|
||||||
|
|
||||||
const { objectMetadataItem } = useObjectMetadataItem({
|
const { objectMetadataItem } = useObjectMetadataItem({
|
||||||
objectNamePlural: 'opportunities',
|
objectNamePlural: 'opportunities',
|
||||||
@ -64,6 +72,11 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds();
|
const updateCompanyBoardCardIds = useUpdateCompanyBoardCardIds();
|
||||||
const updateCompanyBoard = useUpdateCompanyBoard();
|
const updateCompanyBoard = useUpdateCompanyBoard();
|
||||||
|
|
||||||
|
const setAvailableBoardCardFields = useSetRecoilScopedStateV2(
|
||||||
|
availableBoardCardFieldsScopedState,
|
||||||
|
'company-board-view',
|
||||||
|
);
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
useFindManyObjectRecords({
|
||||||
objectNamePlural: 'pipelineSteps',
|
objectNamePlural: 'pipelineSteps',
|
||||||
filter: {},
|
filter: {},
|
||||||
@ -75,23 +88,21 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const whereFilters = useMemo(() => {
|
const filter = turnFiltersIntoWhereClauseV2(
|
||||||
return {
|
mapViewFiltersToFilters(currentViewFilters),
|
||||||
and: [
|
objectMetadataItem?.fields ?? [],
|
||||||
{
|
);
|
||||||
pipelineStepId: {
|
|
||||||
in: pipelineSteps.map((pipelineStep) => pipelineStep.id),
|
const orderBy = turnSortsIntoOrderByV2(
|
||||||
},
|
mapViewSortsToSorts(currentViewSorts),
|
||||||
},
|
objectMetadataItem?.fields ?? [],
|
||||||
...[],
|
);
|
||||||
],
|
|
||||||
};
|
|
||||||
}, [pipelineSteps]) as any;
|
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
useFindManyObjectRecords({
|
||||||
skip: !pipelineSteps.length,
|
skip: !pipelineSteps.length,
|
||||||
objectNamePlural: 'opportunities',
|
objectNamePlural: 'opportunities',
|
||||||
filter: whereFilters,
|
filter: filter,
|
||||||
|
orderBy: orderBy,
|
||||||
onCompleted: useCallback(
|
onCompleted: useCallback(
|
||||||
(data: PaginatedObjectTypeResults<Opportunity>) => {
|
(data: PaginatedObjectTypeResults<Opportunity>) => {
|
||||||
const pipelineProgresses: Array<Opportunity> = data.edges.map(
|
const pipelineProgresses: Array<Opportunity> = data.edges.map(
|
||||||
@ -137,39 +148,6 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
sortDefinitions,
|
sortDefinitions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const setAvailableBoardCardFields = useRecoilCallback(
|
|
||||||
({ snapshot, set }) =>
|
|
||||||
(availableBoardCardFields: any) => {
|
|
||||||
const availableBoardCardFieldsFromState = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
availableBoardCardFieldsScopedState({
|
|
||||||
scopeId: 'company-board-view',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
if (
|
|
||||||
!isDeeplyEqual(
|
|
||||||
availableBoardCardFieldsFromState,
|
|
||||||
availableBoardCardFields,
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
set(
|
|
||||||
availableBoardCardFieldsScopedState({
|
|
||||||
scopeId: 'company-board-view',
|
|
||||||
}),
|
|
||||||
availableBoardCardFields,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
useRecoilScopedStateV2(
|
|
||||||
availableBoardCardFieldsScopedState,
|
|
||||||
'company-board-view',
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const availableTableColumns = columnDefinitions.filter(
|
const availableTableColumns = columnDefinitions.filter(
|
||||||
filterAvailableTableColumns,
|
filterAvailableTableColumns,
|
||||||
@ -179,11 +157,12 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
}, [columnDefinitions, setAvailableBoardCardFields]);
|
}, [columnDefinitions, setAvailableBoardCardFields]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setViewObjectMetadataId?.('company');
|
if (!objectMetadataItem) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setViewObjectMetadataId?.(objectMetadataItem.id);
|
||||||
setViewType?.(ViewType.Kanban);
|
setViewType?.(ViewType.Kanban);
|
||||||
}, [setViewObjectMetadataId, setViewType]);
|
}, [objectMetadataItem, setViewObjectMetadataId, setViewType]);
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
|
||||||
|
|
||||||
const loading = !companies;
|
const loading = !companies;
|
||||||
|
|
||||||
@ -194,9 +173,8 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
if (!loading && opportunities && companies) {
|
if (!loading && opportunities && companies) {
|
||||||
setActionBarEntries();
|
setActionBarEntries();
|
||||||
setContextMenuEntries();
|
setContextMenuEntries();
|
||||||
|
|
||||||
updateCompanyBoard(pipelineSteps, opportunities, companies);
|
updateCompanyBoard(pipelineSteps, opportunities, companies);
|
||||||
setEntityCountInCurrentView(companies.length);
|
setEntityCountInCurrentView(opportunities.length);
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
companies,
|
companies,
|
||||||
@ -212,10 +190,13 @@ export const HooksCompanyBoardEffect = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentViewFields) {
|
if (currentViewFields) {
|
||||||
setBoardCardFields(
|
setBoardCardFields(
|
||||||
mapViewFieldsToBoardFieldDefinitions(currentViewFields, []),
|
mapViewFieldsToBoardFieldDefinitions(
|
||||||
|
currentViewFields,
|
||||||
|
columnDefinitions,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [currentViewFields, setBoardCardFields]);
|
}, [columnDefinitions, currentViewFields, setBoardCardFields]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
|
||||||
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
|
||||||
@ -10,25 +12,24 @@ import { formatFieldMetadataItemsAsSortDefinitions } from '../utils/formatFieldM
|
|||||||
export const useComputeDefinitionsFromFieldMetadata = (
|
export const useComputeDefinitionsFromFieldMetadata = (
|
||||||
objectMetadataItem?: Nullable<ObjectMetadataItem>,
|
objectMetadataItem?: Nullable<ObjectMetadataItem>,
|
||||||
) => {
|
) => {
|
||||||
if (!objectMetadataItem) {
|
const activeFieldMetadataItems = useMemo(
|
||||||
return {
|
() =>
|
||||||
columnDefinitions: [],
|
objectMetadataItem
|
||||||
filterDefinitions: [],
|
? objectMetadataItem.fields.filter(({ isActive }) => isActive)
|
||||||
sortDefinitions: [],
|
: [],
|
||||||
};
|
[objectMetadataItem],
|
||||||
}
|
|
||||||
|
|
||||||
const activeFieldMetadataItems = objectMetadataItem.fields.filter(
|
|
||||||
({ isActive }) => isActive,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const columnDefinitions: ColumnDefinition<FieldMetadata>[] =
|
const columnDefinitions: ColumnDefinition<FieldMetadata>[] = useMemo(
|
||||||
activeFieldMetadataItems.map((field, index) =>
|
() =>
|
||||||
formatFieldMetadataItemAsColumnDefinition({
|
activeFieldMetadataItems.map((field, index) =>
|
||||||
position: index,
|
formatFieldMetadataItemAsColumnDefinition({
|
||||||
field,
|
position: index,
|
||||||
}),
|
field,
|
||||||
);
|
}),
|
||||||
|
),
|
||||||
|
[activeFieldMetadataItems],
|
||||||
|
);
|
||||||
|
|
||||||
const filterDefinitions = formatFieldMetadataItemsAsFilterDefinitions({
|
const filterDefinitions = formatFieldMetadataItemsAsFilterDefinitions({
|
||||||
fields: activeFieldMetadataItems,
|
fields: activeFieldMetadataItems,
|
||||||
|
|||||||
@ -13,8 +13,10 @@ export const formatFieldMetadataItemsAsFilterDefinitions = ({
|
|||||||
![
|
![
|
||||||
FieldMetadataType.DateTime,
|
FieldMetadataType.DateTime,
|
||||||
FieldMetadataType.Number,
|
FieldMetadataType.Number,
|
||||||
|
FieldMetadataType.Currency,
|
||||||
FieldMetadataType.Text,
|
FieldMetadataType.Text,
|
||||||
].includes(field.type)
|
].includes(field.type) ||
|
||||||
|
field.name === 'probability'
|
||||||
) {
|
) {
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
@ -34,5 +36,7 @@ const formatFieldMetadataItemAsFilterDefinition = ({
|
|||||||
? 'DATE_TIME'
|
? 'DATE_TIME'
|
||||||
: field.type === FieldMetadataType.Number
|
: field.type === FieldMetadataType.Number
|
||||||
? 'NUMBER'
|
? 'NUMBER'
|
||||||
|
: field.type === FieldMetadataType.Currency
|
||||||
|
? 'CURRENCY'
|
||||||
: 'TEXT',
|
: 'TEXT',
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
export type MetadataFieldDataType =
|
|
||||||
| 'BOOLEAN'
|
|
||||||
| 'DATE_TIME'
|
|
||||||
| 'ENUM'
|
|
||||||
| 'MONEY'
|
|
||||||
| 'NUMBER'
|
|
||||||
| 'RELATION'
|
|
||||||
| 'TEXT'
|
|
||||||
| 'URL';
|
|
||||||
@ -9,9 +9,6 @@ export type FieldType =
|
|||||||
| 'DOUBLE_TEXT'
|
| 'DOUBLE_TEXT'
|
||||||
| 'EMAIL'
|
| 'EMAIL'
|
||||||
| 'ENUM'
|
| 'ENUM'
|
||||||
| 'MONEY_AMOUNT_'
|
|
||||||
| 'MONEY_AMOUNT'
|
|
||||||
| 'MONEY'
|
|
||||||
| 'NUMBER'
|
| 'NUMBER'
|
||||||
| 'PHONE'
|
| 'PHONE'
|
||||||
| 'PROBABILITY'
|
| 'PROBABILITY'
|
||||||
|
|||||||
@ -33,9 +33,9 @@ export const MultipleFiltersDropdownContent = () => {
|
|||||||
{filterDefinitionUsedInDropdown.type === 'TEXT' && (
|
{filterDefinitionUsedInDropdown.type === 'TEXT' && (
|
||||||
<ObjectFilterDropdownTextSearchInput />
|
<ObjectFilterDropdownTextSearchInput />
|
||||||
)}
|
)}
|
||||||
{filterDefinitionUsedInDropdown.type === 'NUMBER' && (
|
{['NUMBER', 'CURRENCY'].includes(
|
||||||
<ObjectFilterDropdownNumberSearchInput />
|
filterDefinitionUsedInDropdown.type,
|
||||||
)}
|
) && <ObjectFilterDropdownNumberSearchInput />}
|
||||||
{filterDefinitionUsedInDropdown.type === 'DATE_TIME' && (
|
{filterDefinitionUsedInDropdown.type === 'DATE_TIME' && (
|
||||||
<ObjectFilterDropdownDateSearchInput />
|
<ObjectFilterDropdownDateSearchInput />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1 +1,6 @@
|
|||||||
export type FilterType = 'TEXT' | 'DATE_TIME' | 'ENTITY' | 'NUMBER';
|
export type FilterType =
|
||||||
|
| 'TEXT'
|
||||||
|
| 'DATE_TIME'
|
||||||
|
| 'ENTITY'
|
||||||
|
| 'NUMBER'
|
||||||
|
| 'CURRENCY';
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export const getOperandsForFilterType = (
|
|||||||
switch (filterType) {
|
switch (filterType) {
|
||||||
case 'TEXT':
|
case 'TEXT':
|
||||||
return [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain];
|
return [ViewFilterOperand.Contains, ViewFilterOperand.DoesNotContain];
|
||||||
|
case 'CURRENCY':
|
||||||
case 'NUMBER':
|
case 'NUMBER':
|
||||||
case 'DATE_TIME':
|
case 'DATE_TIME':
|
||||||
return [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan];
|
return [ViewFilterOperand.GreaterThan, ViewFilterOperand.LessThan];
|
||||||
|
|||||||
@ -62,6 +62,23 @@ export const turnFiltersIntoWhereClauseV2 = (
|
|||||||
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
case 'CURRENCY':
|
||||||
|
switch (filter.operand) {
|
||||||
|
case ViewFilterOperand.GreaterThan:
|
||||||
|
whereClause[correspondingField.name] = {
|
||||||
|
amountMicros: { gte: parseFloat(filter.value) * 1000000 },
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case ViewFilterOperand.LessThan:
|
||||||
|
whereClause[correspondingField.name] = {
|
||||||
|
amountMicros: { lte: parseFloat(filter.value) * 1000000 },
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
throw new Error(
|
||||||
|
`Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
|
||||||
|
);
|
||||||
|
}
|
||||||
case 'DATE_TIME':
|
case 'DATE_TIME':
|
||||||
switch (filter.operand) {
|
switch (filter.operand) {
|
||||||
case ViewFilterOperand.GreaterThan:
|
case ViewFilterOperand.GreaterThan:
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBo
|
|||||||
|
|
||||||
const StyledBoardContainer = styled.div`
|
const StyledBoardContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,39 @@ export const seedOpportunity = async (
|
|||||||
personId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5',
|
personId: '86083141-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||||
companyId: 'fe256b39-3ec3-4fe3-8997-b76aa0bfa408',
|
companyId: 'fe256b39-3ec3-4fe3-8997-b76aa0bfa408',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: '53f66647-0543-4cc2-9f96-95cc699960f2',
|
||||||
|
amountAmountMicros: 2000000,
|
||||||
|
amountCurrencyCode: 'USD',
|
||||||
|
closeDate: new Date(),
|
||||||
|
probability: 0.5,
|
||||||
|
pipelineStepId: 'd8361722-03fb-4e65-bd4f-ec9e52e5ec0a',
|
||||||
|
pointOfContactId: '93c72d2e-f517-42fd-80ae-14173b3b70ae',
|
||||||
|
personId: '93c72d2e-f517-42fd-80ae-14173b3b70ae',
|
||||||
|
companyId: '118995f3-5d81-46d6-bf83-f7fd33ea6102',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '81ab695d-2f89-406f-90ea-180f433b2445',
|
||||||
|
amountAmountMicros: 300000,
|
||||||
|
amountCurrencyCode: 'USD',
|
||||||
|
closeDate: new Date(),
|
||||||
|
probability: 0.5,
|
||||||
|
pipelineStepId: '30b14887-d592-427d-bd97-6e670158db02',
|
||||||
|
pointOfContactId: '9b324a88-6784-4449-afdf-dc62cb8702f2',
|
||||||
|
personId: '9b324a88-6784-4449-afdf-dc62cb8702f2',
|
||||||
|
companyId: '460b6fb1-ed89-413a-b31a-962986e67bb4',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '9b059852-35b1-4045-9cde-42f715148954',
|
||||||
|
amountAmountMicros: 4000000,
|
||||||
|
amountCurrencyCode: 'USD',
|
||||||
|
closeDate: new Date(),
|
||||||
|
probability: 0.5,
|
||||||
|
pipelineStepId: '30b14887-d592-427d-bd97-6e670158db02',
|
||||||
|
pointOfContactId: '98406e26-80f1-4dff-b570-a74942528de3',
|
||||||
|
personId: '98406e26-80f1-4dff-b570-a74942528de3',
|
||||||
|
companyId: '460b6fb1-ed89-413a-b31a-962986e67bb4',
|
||||||
|
},
|
||||||
])
|
])
|
||||||
.execute();
|
.execute();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user