Complete Fix view work (#2272)

* Fix views

* Make view sorts and view filters functional

* Complete Company table view fix

* Fix model creation

* Start fixing board

* Complete work
This commit is contained in:
Charles Bochet
2023-10-29 16:29:00 +01:00
committed by GitHub
parent 685d342170
commit 9bab28912d
118 changed files with 1806 additions and 1413 deletions

View File

@ -28,7 +28,7 @@ import { getLogoUrlFromDomainName } from '~/utils';
import { CompanyNameEditableField } from '../../modules/companies/editable-field/components/CompanyNameEditableField';
import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer';
import { companyShowFieldDefinition } from './constants/companyShowFieldDefinition';
import { companyShowFieldDefinitions } from './constants/companyShowFieldDefinitions';
export const CompanyShow = () => {
const companyId = useParams().companyId ?? '';
@ -90,7 +90,7 @@ export const CompanyShow = () => {
avatarType="squared"
/>
<PropertyBox extraPadding={true}>
{companyShowFieldDefinition.map((fieldDefinition) => {
{companyShowFieldDefinitions.map((fieldDefinition) => {
return (
<FieldContext.Provider
key={company.id + fieldDefinition.fieldId}

View File

@ -1,51 +0,0 @@
import { FilterDefinitionByEntity } from '@/ui/data/filter/types/FilterDefinitionByEntity';
import {
IconBuildingSkyscraper,
IconCalendarEvent,
IconLink,
IconMap,
IconUser,
IconUsers,
} from '@/ui/display/icon/index';
import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect';
import { Company } from '~/generated/graphql';
export const companyAvailableFilters: FilterDefinitionByEntity<Company>[] = [
{
key: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
type: 'text',
},
{
key: 'employees',
label: 'Employees',
Icon: IconUsers,
type: 'number',
},
{
key: 'domainName',
label: 'URL',
Icon: IconLink,
type: 'text',
},
{
key: 'address',
label: 'Address',
Icon: IconMap,
type: 'text',
},
{
key: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
type: 'date',
},
{
key: 'accountOwnerId',
label: 'Account owner',
Icon: IconUser,
type: 'entity',
entitySelectComponent: <FilterDropdownUserSearchSelect />,
},
];

View File

@ -20,7 +20,7 @@ import {
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
import { User } from '~/generated/graphql';
export const companyShowFieldDefinition: FieldDefinition<FieldMetadata>[] = [
export const companyShowFieldDefinitions: FieldDefinition<FieldMetadata>[] = [
{
fieldId: 'domainName',
label: 'Domain name',

View File

@ -0,0 +1,52 @@
import { FilterDefinitionByEntity } from '@/ui/data/filter/types/FilterDefinitionByEntity';
import {
IconBuildingSkyscraper,
IconCalendarEvent,
IconLink,
IconMap,
IconUser,
IconUsers,
} from '@/ui/display/icon/index';
import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect';
import { Company } from '~/generated/graphql';
export const companyTableFilterDefinitions: FilterDefinitionByEntity<Company>[] =
[
{
fieldId: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
type: 'text',
},
{
fieldId: 'employees',
label: 'Employees',
Icon: IconUsers,
type: 'number',
},
{
fieldId: 'domainName',
label: 'URL',
Icon: IconLink,
type: 'text',
},
{
fieldId: 'address',
label: 'Address',
Icon: IconMap,
type: 'text',
},
{
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
type: 'date',
},
{
fieldId: 'accountOwnerId',
label: 'Account owner',
Icon: IconUser,
type: 'entity',
entitySelectComponent: <FilterDropdownUserSearchSelect />,
},
];

View File

@ -7,29 +7,29 @@ import {
IconUsers,
} from '@/ui/display/icon/index';
export const companyAvailableSorts: SortDefinition[] = [
export const companyTableSortDefinitions: SortDefinition[] = [
{
key: 'name',
fieldId: 'name',
label: 'Name',
Icon: IconBuildingSkyscraper,
},
{
key: 'employees',
fieldId: 'employees',
label: 'Employees',
Icon: IconUsers,
},
{
key: 'domainName',
fieldId: 'domainName',
label: 'Url',
Icon: IconLink,
},
{
key: 'address',
fieldId: 'address',
label: 'Address',
Icon: IconMap,
},
{
key: 'createdAt',
fieldId: 'createdAt',
label: 'Creation',
Icon: IconCalendarEvent,
},

View File

@ -1,3 +1,5 @@
import styled from '@emotion/styled';
import { CompanyBoard } from '@/companies/board/components/CompanyBoard';
import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton';
@ -11,6 +13,11 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'
import { useUpdatePipelineStageMutation } from '~/generated/graphql';
import { opportunitiesBoardOptions } from '~/pages/opportunities/opportunitiesBoardOptions';
const StyledBoardContainer = styled.div`
display: flex;
width: 100%;
`;
export const Opportunities = () => {
const { handlePipelineStageAdd, handlePipelineStageDelete } =
usePipelineStages();
@ -51,11 +58,13 @@ export const Opportunities = () => {
scopeId="opportunities"
CustomRecoilScopeContext={CompanyBoardRecoilScopeContext}
>
<CompanyBoard
onColumnAdd={handlePipelineStageAdd}
onColumnDelete={handlePipelineStageDelete}
onEditColumnTitle={handleEditColumnTitle}
/>
<StyledBoardContainer>
<CompanyBoard
onColumnAdd={handlePipelineStageAdd}
onColumnDelete={handlePipelineStageDelete}
onEditColumnTitle={handleEditColumnTitle}
/>
</StyledBoardContainer>
</RecoilScope>
</BoardOptionsContext.Provider>
</PageBody>

View File

@ -8,31 +8,31 @@ import {
} from '@/ui/display/icon/index';
import { PipelineProgress } from '~/generated/graphql';
import { FilterDropdownPeopleSearchSelect } from '../../modules/people/components/FilterDropdownPeopleSearchSelect';
import { FilterDropdownPeopleSearchSelect } from '../../../modules/people/components/FilterDropdownPeopleSearchSelect';
export const opportunitiesFilters: FilterDefinitionByEntity<PipelineProgress>[] =
export const opportunityBoardFilterDefinitions: FilterDefinitionByEntity<PipelineProgress>[] =
[
{
key: 'amount',
fieldId: 'amount',
label: 'Amount',
Icon: IconCurrencyDollar,
type: 'number',
},
{
key: 'closeDate',
fieldId: 'closeDate',
label: 'Close date',
Icon: IconCalendarEvent,
type: 'date',
},
{
key: 'companyId',
fieldId: 'companyId',
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
{
key: 'pointOfContactId',
fieldId: 'pointOfContactId',
label: 'Point of contact',
Icon: IconUser,
type: 'entity',

View File

@ -1,19 +1,19 @@
import { SortDefinition } from '@/ui/data/sort/types/SortDefinition';
import { IconCalendarEvent, IconCurrencyDollar } from '@/ui/display/icon/index';
export const opportunitiesSorts: SortDefinition[] = [
export const opportunityBoardSortDefinitions: SortDefinition[] = [
{
key: 'createdAt',
fieldId: 'createdAt',
label: 'Creation',
Icon: IconCalendarEvent,
},
{
key: 'amount',
fieldId: 'amount',
label: 'Amount',
Icon: IconCurrencyDollar,
},
{
key: 'closeDate',
fieldId: 'closeDate',
label: 'Expected close date',
Icon: IconCalendarEvent,
},

View File

@ -2,12 +2,12 @@ import { CompanyBoardCard } from '@/companies/components/CompanyBoardCard';
import { NewCompanyProgressButton } from '@/companies/components/NewCompanyProgressButton';
import { BoardOptions } from '@/ui/layout/board/types/BoardOptions';
import { opportunitiesFilters } from './opportunities-filters';
import { opportunitiesSorts } from './opportunities-sorts';
import { opportunityBoardFilterDefinitions } from './constants/opportunityBoardFilterDefinitions';
import { opportunityBoardSortDefinitions } from './constants/opportunityBoardSortDefinitions';
export const opportunitiesBoardOptions: BoardOptions = {
newCardComponent: <NewCompanyProgressButton />,
CardComponent: CompanyBoardCard,
filters: opportunitiesFilters,
sorts: opportunitiesSorts,
filterDefinitions: opportunityBoardFilterDefinitions,
sortDefinitions: opportunityBoardSortDefinitions,
};

View File

@ -2,7 +2,7 @@ import styled from '@emotion/styled';
import { v4 } from 'uuid';
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
import { PeopleTable } from '@/people/table/components/PeopleTable';
import { PersonTable } from '@/people/table/components/PersonTable';
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
import { DataTableActionBar } from '@/ui/data/data-table/action-bar/components/DataTableActionBar';
import { DataTableContextMenu } from '@/ui/data/data-table/context-menu/components/DataTableContextMenu';
@ -62,7 +62,7 @@ export const People = () => {
CustomRecoilScopeContext={TableRecoilScopeContext}
>
<StyledTableContainer>
<PeopleTable />
<PersonTable />
</StyledTableContainer>
<DataTableActionBar />
<DataTableContextMenu />

View File

@ -31,7 +31,7 @@ import {
import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField';
import { ShowPageContainer } from '../../modules/ui/layout/page/ShowPageContainer';
import { personShowFieldDefinition } from './constants/personShowFieldDefinition';
import { personShowFieldDefinition } from './constants/personShowFieldDefinitions';
export const PersonShow = () => {
const personId = useParams().personId ?? '';

View File

@ -0,0 +1,59 @@
import { FilterDropdownCompanySearchSelect } from '@/companies/components/FilterDropdownCompanySearchSelect';
import { FilterDefinitionByEntity } from '@/ui/data/filter/types/FilterDefinitionByEntity';
import {
IconBuildingSkyscraper,
IconCalendarEvent,
IconMail,
IconMap,
IconPhone,
IconUser,
} from '@/ui/display/icon/index';
import { Person } from '~/generated/graphql';
export const personTableFilterDefinitions: FilterDefinitionByEntity<Person>[] =
[
{
fieldId: 'firstName',
label: 'First name',
Icon: IconUser,
type: 'text',
},
{
fieldId: 'lastName',
label: 'Last name',
Icon: IconUser,
type: 'text',
},
{
fieldId: 'email',
label: 'Email',
Icon: IconMail,
type: 'text',
},
{
fieldId: 'companyId',
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
// TODO: replace this with a component that selects the dropdown to use based on the entity type
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
{
fieldId: 'phone',
label: 'Phone',
Icon: IconPhone,
type: 'text',
},
{
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
type: 'date',
},
{
fieldId: 'city',
label: 'City',
Icon: IconMap,
type: 'text',
},
];

View File

@ -9,9 +9,9 @@ import {
IconUser,
} from '@/ui/display/icon/index';
export const peopleAvailableSorts: SortDefinition[] = [
export const personTableSortDefinitions: SortDefinition[] = [
{
key: 'fullname',
fieldId: 'fullname',
label: 'People',
Icon: IconUser,
@ -21,7 +21,7 @@ export const peopleAvailableSorts: SortDefinition[] = [
],
},
{
key: 'company_name',
fieldId: 'company_name',
label: 'Company',
Icon: IconBuildingSkyscraper,
getOrderByTemplate: (direction: SortDirection) => [
@ -29,22 +29,22 @@ export const peopleAvailableSorts: SortDefinition[] = [
],
},
{
key: 'email',
fieldId: 'email',
label: 'Email',
Icon: IconMail,
},
{
key: 'phone',
fieldId: 'phone',
label: 'Phone',
Icon: IconPhone,
},
{
key: 'createdAt',
fieldId: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
},
{
key: 'city',
fieldId: 'city',
label: 'City',
Icon: IconMap,
},

View File

@ -1,58 +0,0 @@
import { FilterDropdownCompanySearchSelect } from '@/companies/components/FilterDropdownCompanySearchSelect';
import { FilterDefinitionByEntity } from '@/ui/data/filter/types/FilterDefinitionByEntity';
import {
IconBuildingSkyscraper,
IconCalendarEvent,
IconMail,
IconMap,
IconPhone,
IconUser,
} from '@/ui/display/icon/index';
import { Person } from '~/generated/graphql';
export const peopleAvailableFilters: FilterDefinitionByEntity<Person>[] = [
{
key: 'firstName',
label: 'First name',
Icon: IconUser,
type: 'text',
},
{
key: 'lastName',
label: 'Last name',
Icon: IconUser,
type: 'text',
},
{
key: 'email',
label: 'Email',
Icon: IconMail,
type: 'text',
},
{
key: 'companyId',
label: 'Company',
Icon: IconBuildingSkyscraper,
type: 'entity',
// TODO: replace this with a component that selects the dropdown to use based on the entity type
entitySelectComponent: <FilterDropdownCompanySearchSelect />,
},
{
key: 'phone',
label: 'Phone',
Icon: IconPhone,
type: 'text',
},
{
key: 'createdAt',
label: 'Created at',
Icon: IconCalendarEvent,
type: 'date',
},
{
key: 'city',
label: 'City',
Icon: IconMap,
type: 'text',
},
];

View File

@ -4,6 +4,7 @@ import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contex
import { PageAddTaskButton } from '@/activities/tasks/components/PageAddTaskButton';
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
import { FilterDropdownButton } from '@/ui/data/filter/components/FilterDropdownButton';
import { FilterScope } from '@/ui/data/filter/scopes/FilterScope';
import { IconArchive, IconCheck, IconCheckbox } from '@/ui/display/icon/index';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
import { PageBody } from '@/ui/layout/page/PageBody';
@ -47,30 +48,35 @@ export const Tasks = () => {
return (
<PageContainer>
<RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}>
<TasksEffect />
<PageHeader title="Tasks" Icon={IconCheckbox}>
<PageAddTaskButton />
</PageHeader>
<PageBody>
<StyledTasksContainer>
<TopBar
leftComponent={
<StyledTabListContainer>
<TabList context={TasksRecoilScopeContext} tabs={TASK_TABS} />
</StyledTabListContainer>
}
rightComponent={
<FilterDropdownButton
key="tasks-filter-dropdown-button"
hotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,
}}
/>
}
/>
<TaskGroups />
</StyledTasksContainer>
</PageBody>
<FilterScope filterScopeId="tasks-filter-scope">
<TasksEffect />
<PageHeader title="Tasks" Icon={IconCheckbox}>
<PageAddTaskButton />
</PageHeader>
<PageBody>
<StyledTasksContainer>
<TopBar
leftComponent={
<StyledTabListContainer>
<TabList
context={TasksRecoilScopeContext}
tabs={TASK_TABS}
/>
</StyledTabListContainer>
}
rightComponent={
<FilterDropdownButton
key="tasks-filter-dropdown-button"
hotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,
}}
/>
}
/>
<TaskGroups />
</StyledTasksContainer>
</PageBody>
</FilterScope>
</RecoilScope>
</PageContainer>
);

View File

@ -5,29 +5,27 @@ import { currentUserState } from '@/auth/states/currentUserState';
import { useFilter } from '@/ui/data/filter/hooks/useFilter';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { tasksFilters } from './tasks-filters';
import { tasksFilterDefinitions } from './tasks-filter-definitions';
export const TasksEffect = () => {
const [currentUser] = useRecoilState(currentUserState);
const { setSelectedFilters, setAvailableFilters } = useFilter();
const { setSelectedFilter, setAvailableFilterDefinitions } = useFilter();
useEffect(() => {
setAvailableFilters(tasksFilters);
}, [setAvailableFilters]);
setAvailableFilterDefinitions(tasksFilterDefinitions);
}, [setAvailableFilterDefinitions]);
useEffect(() => {
if (currentUser) {
setSelectedFilters([
{
key: 'assigneeId',
type: 'entity',
value: currentUser.id,
operand: ViewFilterOperand.Is,
displayValue: currentUser.displayName,
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
},
]);
setSelectedFilter({
fieldId: 'assigneeId',
value: currentUser.id,
operand: ViewFilterOperand.Is,
displayValue: currentUser.displayName,
displayAvatarUrl: currentUser.avatarUrl ?? undefined,
definition: tasksFilterDefinitions[0],
});
}
}, [currentUser, setSelectedFilters]);
}, [currentUser, setSelectedFilter]);
return <></>;
};

View File

@ -3,9 +3,9 @@ import { IconUser, IconUserCircle } from '@/ui/display/icon';
import { FilterDropdownUserSearchSelect } from '@/users/components/FilterDropdownUserSearchSelect';
import { Activity } from '~/generated/graphql';
export const tasksFilters: FilterDefinitionByEntity<Activity>[] = [
export const tasksFilterDefinitions: FilterDefinitionByEntity<Activity>[] = [
{
key: 'assigneeId',
fieldId: 'assigneeId',
label: 'Assignee',
Icon: IconUser,
type: 'entity',