Skip to content

Commit 28e12d4

Browse files
authored
feat: toggle board field visibilities (#1547)
Closes #1537, Closes #1539
1 parent 67f1da0 commit 28e12d4

31 files changed

+492
-168
lines changed
Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
import { useEffect } from 'react';
12
import { MemoryRouter } from 'react-router-dom';
23
import { Meta, StoryObj } from '@storybook/react';
34

45
import { CompanyBoardCard } from '@/companies/components/CompanyBoardCard';
6+
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
57
import { BoardCardIdContext } from '@/ui/board/contexts/BoardCardIdContext';
8+
import { boardCardFieldsScopedState } from '@/ui/board/states/boardCardFieldsScopedState';
69
import { BoardColumnRecoilScopeContext } from '@/ui/board/states/recoil-scope-contexts/BoardColumnRecoilScopeContext';
710
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
11+
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
812
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
13+
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
914
import { graphqlMocks } from '~/testing/graphqlMocks';
1015
import { mockedPipelineProgressData } from '~/testing/mock-data/pipeline-progress';
1116

@@ -16,26 +21,43 @@ const meta: Meta<typeof CompanyBoardCard> = {
1621
title: 'Modules/Companies/CompanyBoardCard',
1722
component: CompanyBoardCard,
1823
decorators: [
19-
(Story) => (
20-
<RecoilScope SpecificContext={CompanyBoardRecoilScopeContext}>
21-
<HooksCompanyBoard />
22-
<RecoilScope SpecificContext={BoardColumnRecoilScopeContext}>
23-
<BoardCardIdContext.Provider value={mockedPipelineProgressData[1].id}>
24-
<MemoryRouter>
25-
<Story />
26-
</MemoryRouter>
27-
</BoardCardIdContext.Provider>
28-
</RecoilScope>
29-
</RecoilScope>
30-
),
24+
(Story, context) => {
25+
const [, setBoardCardFields] = useRecoilScopedState(
26+
boardCardFieldsScopedState,
27+
context.parameters.recoilScopeContext,
28+
);
29+
30+
useEffect(() => {
31+
setBoardCardFields(pipelineAvailableFieldDefinitions);
32+
}, [setBoardCardFields]);
33+
34+
return (
35+
<>
36+
<HooksCompanyBoard />
37+
<RecoilScope SpecificContext={BoardColumnRecoilScopeContext}>
38+
<BoardCardIdContext.Provider
39+
value={mockedPipelineProgressData[1].id}
40+
>
41+
<MemoryRouter>
42+
<Story />
43+
</MemoryRouter>
44+
</BoardCardIdContext.Provider>
45+
</RecoilScope>
46+
</>
47+
);
48+
},
49+
ComponentWithRecoilScopeDecorator,
3150
ComponentDecorator,
3251
],
52+
args: { scopeContext: CompanyBoardRecoilScopeContext },
53+
argTypes: { scopeContext: { control: false } },
3354
parameters: {
3455
msw: graphqlMocks,
56+
recoilScopeContext: CompanyBoardRecoilScopeContext,
3557
},
3658
};
3759

3860
export default meta;
3961
type Story = StoryObj<typeof CompanyBoardCard>;
4062

41-
export const CompanyCompanyBoardCard: Story = {};
63+
export const Default: Story = {};

front/src/modules/companies/board/components/CompanyBoard.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
12
import {
23
EntityBoard,
34
type EntityBoardProps,
@@ -21,6 +22,7 @@ export const CompanyBoard = ({ ...props }: CompanyBoardProps) => {
2122
availableSorts: opportunitiesBoardOptions.sorts,
2223
objectId: 'company',
2324
scopeContext: CompanyBoardRecoilScopeContext,
25+
fieldDefinitions: pipelineAvailableFieldDefinitions,
2426
});
2527

2628
return (

front/src/modules/companies/components/CompanyBoardCard.tsx

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
1-
import { ReactNode, useContext } from 'react';
1+
import { type Context, type ReactNode, useContext } from 'react';
22
import styled from '@emotion/styled';
3-
import { useRecoilState, useRecoilValue } from 'recoil';
3+
import { useRecoilState } from 'recoil';
44

55
import { BoardCardIdContext } from '@/ui/board/contexts/BoardCardIdContext';
66
import { useCurrentCardSelected } from '@/ui/board/hooks/useCurrentCardSelected';
7-
import { viewFieldsDefinitionsState } from '@/ui/board/states/viewFieldsDefinitionsState';
7+
import { visibleBoardCardFieldsScopedSelector } from '@/ui/board/states/selectors/visibleBoardCardFieldsScopedSelector';
88
import { EntityChipVariant } from '@/ui/chip/components/EntityChip';
99
import { GenericEditableField } from '@/ui/editable-field/components/GenericEditableField';
1010
import { EditableFieldDefinitionContext } from '@/ui/editable-field/contexts/EditableFieldDefinitionContext';
1111
import { EditableFieldEntityIdContext } from '@/ui/editable-field/contexts/EditableFieldEntityIdContext';
1212
import { EditableFieldMutationContext } from '@/ui/editable-field/contexts/EditableFieldMutationContext';
1313
import { Checkbox, CheckboxVariant } from '@/ui/input/components/Checkbox';
14+
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
1415
import { useUpdateOnePipelineProgressMutation } from '~/generated/graphql';
1516
import { getLogoUrlFromDomainName } from '~/utils';
1617

1718
import { companyProgressesFamilyState } from '../states/companyProgressesFamilyState';
1819

1920
import { CompanyChip } from './CompanyChip';
2021

22+
type OwnProps = {
23+
scopeContext: Context<string | null>;
24+
};
25+
2126
const StyledBoardCard = styled.div<{ selected: boolean }>`
2227
background-color: ${({ theme, selected }) =>
2328
selected ? theme.accent.quaternary : theme.background.secondary};
@@ -98,7 +103,7 @@ const StyledFieldContainer = styled.div`
98103
width: 100%;
99104
`;
100105

101-
export function CompanyBoardCard() {
106+
export function CompanyBoardCard({ scopeContext }: OwnProps) {
102107
const { currentCardSelected, setCurrentCardSelected } =
103108
useCurrentCardSelected();
104109
const boardCardId = useContext(BoardCardIdContext);
@@ -108,7 +113,10 @@ export function CompanyBoardCard() {
108113
);
109114
const { pipelineProgress, company } = companyProgress ?? {};
110115

111-
const viewFieldsDefinitions = useRecoilValue(viewFieldsDefinitionsState);
116+
const visibleBoardCardFields = useRecoilScopedValue(
117+
visibleBoardCardFieldsScopedSelector,
118+
scopeContext,
119+
);
112120

113121
// boardCardId check can be moved to a wrapper to avoid unnecessary logic above
114122
if (!company || !pipelineProgress || !boardCardId) {
@@ -157,23 +165,21 @@ export function CompanyBoardCard() {
157165
value={useUpdateOnePipelineProgressMutation}
158166
>
159167
<EditableFieldEntityIdContext.Provider value={boardCardId}>
160-
{viewFieldsDefinitions.map((viewField) => {
161-
return (
162-
<PreventSelectOnClickContainer key={viewField.key}>
163-
<EditableFieldDefinitionContext.Provider
164-
value={{
165-
key: viewField.key,
166-
name: viewField.name,
167-
Icon: viewField.Icon,
168-
type: viewField.metadata.type,
169-
metadata: viewField.metadata,
170-
}}
171-
>
172-
<GenericEditableField />
173-
</EditableFieldDefinitionContext.Provider>
174-
</PreventSelectOnClickContainer>
175-
);
176-
})}
168+
{visibleBoardCardFields.map((viewField) => (
169+
<PreventSelectOnClickContainer key={viewField.key}>
170+
<EditableFieldDefinitionContext.Provider
171+
value={{
172+
key: viewField.key,
173+
name: viewField.name,
174+
Icon: viewField.Icon,
175+
type: viewField.metadata.type,
176+
metadata: viewField.metadata,
177+
}}
178+
>
179+
<GenericEditableField />
180+
</EditableFieldDefinitionContext.Provider>
181+
</PreventSelectOnClickContainer>
182+
))}
177183
</EditableFieldEntityIdContext.Provider>
178184
</EditableFieldMutationContext.Provider>
179185
</StyledBoardCardBody>

front/src/modules/companies/components/HooksCompanyBoard.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { useEffect, useMemo } from 'react';
2-
import { useRecoilState, useSetRecoilState } from 'recoil';
2+
import { useRecoilState } from 'recoil';
33

4-
import { pipelineAvailableFieldDefinitions } from '@/pipeline/constants/pipelineAvailableFieldDefinitions';
54
import { useBoardActionBarEntries } from '@/ui/board/hooks/useBoardActionBarEntries';
65
import { useBoardContextMenuEntries } from '@/ui/board/hooks/useBoardContextMenuEntries';
76
import { isBoardLoadedState } from '@/ui/board/states/isBoardLoadedState';
8-
import { viewFieldsDefinitionsState } from '@/ui/board/states/viewFieldsDefinitionsState';
97
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
108
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
119
import { availableFiltersScopedState } from '@/ui/view-bar/states/availableFiltersScopedState';
@@ -26,17 +24,13 @@ import { useUpdateCompanyBoard } from '../hooks/useUpdateCompanyBoardColumns';
2624
import { CompanyBoardRecoilScopeContext } from '../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
2725

2826
export function HooksCompanyBoard() {
29-
const setFieldsDefinitionsState = useSetRecoilState(
30-
viewFieldsDefinitionsState,
31-
);
3227
const [, setAvailableFilters] = useRecoilScopedState(
3328
availableFiltersScopedState,
3429
CompanyBoardRecoilScopeContext,
3530
);
3631

3732
useEffect(() => {
3833
setAvailableFilters(opportunitiesBoardOptions.filters);
39-
setFieldsDefinitionsState(pipelineAvailableFieldDefinitions);
4034
});
4135

4236
const [, setIsBoardLoaded] = useRecoilState(isBoardLoadedState);

front/src/modules/pipeline/constants/pipelineAvailableFieldDefinitions.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const pipelineAvailableFieldDefinitions: ViewFieldDefinition<ViewFieldMet
2020
key: 'closeDate',
2121
name: 'Close Date',
2222
Icon: IconCalendarEvent,
23+
index: 0,
2324
metadata: {
2425
type: 'date',
2526
fieldName: 'closeDate',
@@ -30,6 +31,7 @@ export const pipelineAvailableFieldDefinitions: ViewFieldDefinition<ViewFieldMet
3031
key: 'amount',
3132
name: 'Amount',
3233
Icon: IconCurrencyDollar,
34+
index: 1,
3335
metadata: {
3436
type: 'number',
3537
fieldName: 'amount',
@@ -40,6 +42,7 @@ export const pipelineAvailableFieldDefinitions: ViewFieldDefinition<ViewFieldMet
4042
key: 'probability',
4143
name: 'Probability',
4244
Icon: IconProgressCheck,
45+
index: 2,
4346
metadata: {
4447
type: 'probability',
4548
fieldName: 'probability',
@@ -50,6 +53,7 @@ export const pipelineAvailableFieldDefinitions: ViewFieldDefinition<ViewFieldMet
5053
key: 'pointOfContact',
5154
name: 'Point of Contact',
5255
Icon: IconUser,
56+
index: 3,
5357
metadata: {
5458
type: 'relation',
5559
fieldName: 'pointOfContact',

front/src/modules/ui/board/components/BoardHeader.tsx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type ComponentProps, useCallback } from 'react';
1+
import type { ComponentProps } from 'react';
22

33
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
44
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
@@ -29,27 +29,22 @@ export function BoardHeader<SortField>({
2929
availableSorts,
3030
defaultViewName,
3131
}: BoardHeaderProps<SortField>) {
32-
const OptionsDropdownButton = useCallback(
33-
() => (
34-
<BoardOptionsDropdown
35-
customHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }}
36-
onStageAdd={onStageAdd}
37-
onViewsChange={onViewsChange}
38-
scopeContext={scopeContext}
39-
/>
40-
),
41-
[onStageAdd, onViewsChange, scopeContext],
42-
);
43-
4432
return (
4533
<RecoilScope SpecificContext={DropdownRecoilScopeContext}>
4634
<ViewBar
4735
availableSorts={availableSorts}
4836
defaultViewName={defaultViewName}
4937
onViewsChange={onViewsChange}
5038
onViewSubmit={onViewSubmit}
39+
optionsDropdownButton={
40+
<BoardOptionsDropdown
41+
customHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }}
42+
onStageAdd={onStageAdd}
43+
onViewsChange={onViewsChange}
44+
scopeContext={scopeContext}
45+
/>
46+
}
5147
optionsDropdownKey={BoardOptionsDropdownKey}
52-
OptionsDropdownButton={OptionsDropdownButton}
5348
scopeContext={scopeContext}
5449
/>
5550
</RecoilScope>

0 commit comments

Comments
 (0)