Add new line on Table Views (#110)

Add addition on Companies table
This commit is contained in:
Charles Bochet
2023-05-07 23:41:22 +02:00
committed by GitHub
parent 8c7815af79
commit 50a4a97145
15 changed files with 329 additions and 154 deletions

View File

@ -1,16 +1,18 @@
import { FaRegBuilding, FaList } from 'react-icons/fa';
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
import styled from '@emotion/styled';
import { useState, useCallback } from 'react';
import { useState, useCallback, useEffect } from 'react';
import { v4 as uuidv4 } from 'uuid';
import {
CompaniesSelectedSortType,
defaultOrderBy,
insertCompany,
useCompaniesQuery,
} from '../../services/companies';
import Table from '../../components/table/Table';
import { mapCompany } from '../../interfaces/company.interface';
import { Company, mapCompany } from '../../interfaces/company.interface';
import {
companiesColumns,
useCompaniesColumns,
availableFilters,
availableSorts,
} from './companies-table';
@ -33,6 +35,7 @@ const StyledCompaniesContainer = styled.div`
function Companies() {
const [orderBy, setOrderBy] = useState<Companies_Order_By[]>(defaultOrderBy);
const [where, setWhere] = useState<Companies_Bool_Exp>({});
const [internalData, setInternalData] = useState<Array<Company>>([]);
const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
@ -47,13 +50,43 @@ function Companies() {
[],
);
const { data } = useCompaniesQuery(orderBy, where);
const { data, loading, refetch } = useCompaniesQuery(orderBy, where);
useEffect(() => {
if (!loading) {
if (data) {
setInternalData(data.companies.map(mapCompany));
}
}
}, [loading, setInternalData, data]);
const addEmptyRow = useCallback(() => {
const newCompany: Company = {
id: uuidv4(),
name: '',
domain_name: '',
employees: 0,
address: '',
opportunities: [],
creationDate: new Date(),
accountOwner: null,
};
insertCompany(newCompany);
setInternalData([newCompany, ...internalData]);
refetch();
}, [internalData, setInternalData, refetch]);
const companiesColumns = useCompaniesColumns();
return (
<WithTopBarContainer title="Companies" icon={<FaRegBuilding />}>
<WithTopBarContainer
title="Companies"
icon={<FaRegBuilding />}
onAddButtonClick={addEmptyRow}
>
<StyledCompaniesContainer>
<Table
data={data ? data.companies.map(mapCompany) : []}
data={internalData}
columns={companiesColumns}
viewName="All Companies"
viewIcon={<FaList />}

View File

@ -18,7 +18,7 @@ const mocks = [
request: {
query: GET_COMPANIES,
variables: {
orderBy: [{ name: 'asc' }],
orderBy: [{ created_at: 'desc' }],
where: {},
},
},

View File

@ -115,3 +115,24 @@ it('Checks company address edit is updating data', async () => {
expect(getByText('21 rue de clignancourt')).toBeInTheDocument();
});
});
it('Checks insert data is appending a new line', async () => {
const { getByText, getByTestId, container } = render(<CompaniesDefault />);
await waitFor(() => {
expect(getByText('Airbnb')).toBeDefined();
});
const tableRows = container.querySelectorAll<HTMLElement>('table tbody tr');
expect(tableRows.length).toBe(6);
act(() => {
fireEvent.click(getByTestId('add-button'));
});
await waitFor(() => {
const tableRows = container.querySelectorAll<HTMLElement>('table tbody tr');
expect(tableRows.length).toBe(7);
});
});

View File

@ -38,6 +38,7 @@ import {
import EditableDate from '../../components/table/editable-cell/EditableDate';
import EditableRelation from '../../components/table/editable-cell/EditableRelation';
import { GraphqlQueryUser, PartialUser } from '../../interfaces/user.interface';
import { useMemo } from 'react';
export const availableSorts = [
{
@ -136,139 +137,150 @@ export const availableFilters = [
] satisfies Array<FilterType<Companies_Bool_Exp>>;
const columnHelper = createColumnHelper<Company>();
export const companiesColumns = [
columnHelper.accessor('id', {
header: () => (
<Checkbox id="company-select-all" name="company-select-all" />
),
cell: (props) => (
<Checkbox
id={`company-selected-${props.row.original.id}`}
name={`company-selected-${props.row.original.id}`}
/>
),
}),
columnHelper.accessor('name', {
header: () => <ColumnHead viewName="Name" viewIcon={<FaRegBuilding />} />,
cell: (props) => (
<EditableChip
value={props.row.original.name}
placeholder="Name"
picture={`https://www.google.com/s2/favicons?domain=${props.row.original.domain_name}&sz=256`}
changeHandler={(value: string) => {
const company = props.row.original;
company.name = value;
updateCompany(company);
}}
ChipComponent={CompanyChip}
/>
),
}),
columnHelper.accessor('employees', {
header: () => <ColumnHead viewName="Employees" viewIcon={<FaUsers />} />,
cell: (props) => (
<EditableText
content={props.row.original.employees.toFixed(0)}
changeHandler={(value) => {
const company = props.row.original;
company.employees = parseInt(value);
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('domain_name', {
header: () => <ColumnHead viewName="URL" viewIcon={<FaLink />} />,
cell: (props) => (
<EditableText
content={props.row.original.domain_name}
changeHandler={(value) => {
const company = props.row.original;
company.domain_name = value;
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('address', {
header: () => <ColumnHead viewName="Address" viewIcon={<FaMapPin />} />,
cell: (props) => (
<EditableText
content={props.row.original.address}
changeHandler={(value) => {
const company = props.row.original;
company.address = value;
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('creationDate', {
header: () => <ColumnHead viewName="Creation" viewIcon={<FaCalendar />} />,
cell: (props) => (
<EditableDate
value={props.row.original.creationDate}
changeHandler={(value: Date) => {
const company = props.row.original;
company.creationDate = value;
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('accountOwner', {
header: () => (
<ColumnHead viewName="Account Owner" viewIcon={<FaRegUser />} />
),
cell: (props) => (
<EditableRelation<PartialUser, PersonChipPropsType>
relation={props.row.original.accountOwner}
searchPlaceholder="Account Owner"
ChipComponent={PersonChip}
chipComponentPropsMapper={(
accountOwner: PartialUser,
): PersonChipPropsType => {
return {
name: accountOwner.displayName,
};
}}
changeHandler={(relation: PartialUser) => {
const company = props.row.original;
if (company.accountOwner) {
company.accountOwner.id = relation.id;
} else {
company.accountOwner = {
id: relation.id,
email: relation.email,
displayName: relation.displayName,
};
}
updateCompany(company);
}}
searchFilter={
{
key: 'account_owner_name',
label: 'Account Owner',
icon: <FaUser />,
whereTemplate: () => {
return {};
},
searchQuery: SEARCH_USER_QUERY,
searchTemplate: (searchInput: string) => ({
displayName: { _ilike: `%${searchInput}%` },
}),
searchResultMapper: (accountOwner: GraphqlQueryUser) => ({
displayValue: accountOwner.displayName,
value: {
id: accountOwner.id,
email: accountOwner.email,
displayName: accountOwner.displayName,
},
}),
operands: [],
} satisfies FilterType<Users_Bool_Exp>
}
/>
),
}),
];
export const useCompaniesColumns = () => {
return useMemo(() => {
return [
columnHelper.accessor('id', {
header: () => (
<Checkbox id="company-select-all" name="company-select-all" />
),
cell: (props) => (
<Checkbox
id={`company-selected-${props.row.original.id}`}
name={`company-selected-${props.row.original.id}`}
/>
),
}),
columnHelper.accessor('name', {
header: () => (
<ColumnHead viewName="Name" viewIcon={<FaRegBuilding />} />
),
cell: (props) => (
<EditableChip
value={props.row.original.name}
placeholder="Name"
picture={`https://www.google.com/s2/favicons?domain=${props.row.original.domain_name}&sz=256`}
changeHandler={(value: string) => {
const company = props.row.original;
company.name = value;
updateCompany(company);
}}
ChipComponent={CompanyChip}
/>
),
}),
columnHelper.accessor('employees', {
header: () => (
<ColumnHead viewName="Employees" viewIcon={<FaUsers />} />
),
cell: (props) => (
<EditableText
content={props.row.original.employees.toFixed(0)}
changeHandler={(value) => {
const company = props.row.original;
company.employees = parseInt(value);
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('domain_name', {
header: () => <ColumnHead viewName="URL" viewIcon={<FaLink />} />,
cell: (props) => (
<EditableText
content={props.row.original.domain_name}
changeHandler={(value) => {
const company = props.row.original;
company.domain_name = value;
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('address', {
header: () => <ColumnHead viewName="Address" viewIcon={<FaMapPin />} />,
cell: (props) => (
<EditableText
content={props.row.original.address}
changeHandler={(value) => {
const company = props.row.original;
company.address = value;
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('creationDate', {
header: () => (
<ColumnHead viewName="Creation" viewIcon={<FaCalendar />} />
),
cell: (props) => (
<EditableDate
value={props.row.original.creationDate}
changeHandler={(value: Date) => {
const company = props.row.original;
company.creationDate = value;
updateCompany(company);
}}
/>
),
}),
columnHelper.accessor('accountOwner', {
header: () => (
<ColumnHead viewName="Account Owner" viewIcon={<FaRegUser />} />
),
cell: (props) => (
<EditableRelation<PartialUser, PersonChipPropsType>
relation={props.row.original.accountOwner}
searchPlaceholder="Account Owner"
ChipComponent={PersonChip}
chipComponentPropsMapper={(
accountOwner: PartialUser,
): PersonChipPropsType => {
return {
name: accountOwner.displayName,
};
}}
changeHandler={(relation: PartialUser) => {
const company = props.row.original;
if (company.accountOwner) {
company.accountOwner.id = relation.id;
} else {
company.accountOwner = {
id: relation.id,
email: relation.email,
displayName: relation.displayName,
};
}
updateCompany(company);
}}
searchFilter={
{
key: 'account_owner_name',
label: 'Account Owner',
icon: <FaUser />,
whereTemplate: () => {
return {};
},
searchQuery: SEARCH_USER_QUERY,
searchTemplate: (searchInput: string) => ({
displayName: { _ilike: `%${searchInput}%` },
}),
searchResultMapper: (accountOwner: GraphqlQueryUser) => ({
displayValue: accountOwner.displayName,
value: {
id: accountOwner.id,
email: accountOwner.email,
displayName: accountOwner.displayName,
},
}),
operands: [],
} satisfies FilterType<Users_Bool_Exp>
}
/>
),
}),
];
}, []);
};

View File

@ -44,10 +44,18 @@ function People() {
[],
);
const addEmptyRow = useCallback(() => {
console.log('add row');
}, []);
const { data } = usePeopleQuery(orderBy, where);
return (
<WithTopBarContainer title="People" icon={<FaRegUser />}>
<WithTopBarContainer
title="People"
icon={<FaRegUser />}
onAddButtonClick={addEmptyRow}
>
<StyledPeopleContainer>
{
<Table