Skip to content

Commit

Permalink
Add all filters to tables + make column width fixed (#133)
Browse files Browse the repository at this point in the history
* Add additional filters on companies and people page

* Make colunn width fixed

* Remove duplicate declaration of Unknown type
  • Loading branch information
charlesBochet authored May 21, 2023
1 parent 3370499 commit 67353ed
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 86 deletions.
3 changes: 2 additions & 1 deletion front/src/components/editable-cell/EditableCellWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ type StyledEditModeContainerProps = {
const StyledNonEditModeContainer = styled.div`
display: flex;
align-items: center;
width: 100%;
width: calc(100% - ${(props) => props.theme.spacing(5)});
height: 100%;
padding-left: ${(props) => props.theme.spacing(2)};
padding-right: ${(props) => props.theme.spacing(2)};
overflow: hidden;
`;

const StyledEditModeContainer = styled.div<StyledEditModeContainerProps>`
Expand Down
6 changes: 5 additions & 1 deletion front/src/components/form/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ const StyledContainer = styled.span`
input[type='checkbox']::before {
content: '';
border: 1px solid ${(props) => props.theme.text80};
border: 1px solid ${(props) => props.theme.text40};
width: 12px;
height: 12px;
border-radius: 2px;
display: block;
}
input[type='checkbox']:hover::before {
border: 1px solid ${(props) => props.theme.text80};
}
input[type='checkbox']:checked::before {
border: 1px solid ${(props) => props.theme.blue};
}
Expand Down
8 changes: 7 additions & 1 deletion front/src/components/table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const StyledTable = styled.table`
border-collapse: collapse;
margin-left: ${(props) => props.theme.spacing(2)};
margin-right: ${(props) => props.theme.spacing(2)};
table-layout: fixed;
th {
border-collapse: collapse;
Expand Down Expand Up @@ -148,7 +149,12 @@ const Table = <
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
<th
key={header.id}
style={{
width: `${header.getSize()}px`,
}}
>
{header.isPlaceholder
? null
: flexRender(
Expand Down
40 changes: 21 additions & 19 deletions front/src/components/table/table-header/FilterDropdownButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,25 +91,27 @@ export const FilterDropdownButton = <TData extends FilterableFieldsType>({
);
}

return filterSearchResults.results.map((result, index) => (
<DropdownButton.StyledDropdownItem
key={`fields-value-${index}`}
onClick={() => {
onFilterSelect({
key: selectedFilter.key,
label: selectedFilter.label,
value: result.value,
displayValue: result.render(result.value),
icon: selectedFilter.icon,
operand: selectedFilterOperand,
});
setIsUnfolded(false);
setSelectedFilter(undefined);
}}
>
{result.render(result.value)}
</DropdownButton.StyledDropdownItem>
));
return filterSearchResults.results.map((result, index) => {
return (
<DropdownButton.StyledDropdownItem
key={`fields-value-${index}`}
onClick={() => {
onFilterSelect({
key: selectedFilter.key,
label: selectedFilter.label,
value: result.value,
displayValue: result.render(result.value),
icon: selectedFilter.icon,
operand: selectedFilterOperand,
});
setIsUnfolded(false);
setSelectedFilter(undefined);
}}
>
{result.render(result.value)}
</DropdownButton.StyledDropdownItem>
);
});
};

function renderValueSelection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const StyledChip = styled.div`
padding: ${(props) => props.theme.spacing(1) + ' ' + props.theme.spacing(2)};
margin-left: ${(props) => props.theme.spacing(2)};
font-size: ${(props) => props.theme.fontSizeSmall};
align-items: center;
`;
const StyledIcon = styled.div`
margin-right: ${(props) => props.theme.spacing(1)};
Expand Down
2 changes: 2 additions & 0 deletions front/src/interfaces/entities/generic.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export type AnyEntity = {
__typename: string;
} & Record<string, any>;

export type UnknownType = void;

export type GqlType<T> = T extends Company
? GraphqlQueryCompany
: T extends Person
Expand Down
7 changes: 5 additions & 2 deletions front/src/interfaces/filters/interface.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ReactNode } from 'react';
import { SearchConfigType } from '../search/interface';
import { AnyEntity, BoolExpType } from '../entities/generic.interface';
import {
AnyEntity,
BoolExpType,
UnknownType,
} from '../entities/generic.interface';

export type FilterableFieldsType = AnyEntity;
export type FilterWhereRelationType = AnyEntity;
type UnknownType = void;
export type FilterWhereType = FilterWhereRelationType | string | UnknownType;

export type FilterConfigType<
Expand Down
30 changes: 13 additions & 17 deletions front/src/interfaces/search/interface.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import { DocumentNode } from 'graphql';
import { ReactNode } from 'react';
import {
Companies_Bool_Exp,
People_Bool_Exp,
Users_Bool_Exp,
} from '../../generated/graphql';
import { AnyEntity, GqlType } from '../entities/generic.interface';

type UnknownType = void;
AnyEntity,
BoolExpType,
GqlType,
UnknownType,
} from '../entities/generic.interface';

export type SearchConfigType<
SearchType extends AnyEntity | UnknownType = AnyEntity,
> = SearchType extends AnyEntity
SearchType extends AnyEntity | UnknownType = UnknownType,
> = SearchType extends UnknownType
? {
query: DocumentNode;
template: (
searchInput: string,
) => People_Bool_Exp | Companies_Bool_Exp | Users_Bool_Exp;
template: (searchInput: string) => any;
resultMapper: (data: any) => any;
}
: {
query: DocumentNode;
template: (searchInput: string) => BoolExpType<SearchType>;
resultMapper: (data: GqlType<SearchType>) => {
value: SearchType;
render: (value: SearchType) => ReactNode;
};
}
: {
query: DocumentNode;
template: (searchInput: string) => any;
resultMapper: (data: any) => any;
};
6 changes: 6 additions & 0 deletions front/src/pages/companies/companies-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export const useCompaniesColumns = () => {
onChange={props.row.getToggleSelectedHandler()}
/>
),
size: 25,
},
columnHelper.accessor('name', {
header: () => (
Expand All @@ -68,6 +69,7 @@ export const useCompaniesColumns = () => {
ChipComponent={CompanyChip}
/>
),
size: 120,
}),
columnHelper.accessor('employees', {
header: () => (
Expand All @@ -89,6 +91,7 @@ export const useCompaniesColumns = () => {
}}
/>
),
size: 70,
}),
columnHelper.accessor('domainName', {
header: () => (
Expand All @@ -104,6 +107,7 @@ export const useCompaniesColumns = () => {
}}
/>
),
size: 100,
}),
columnHelper.accessor('address', {
header: () => (
Expand All @@ -119,6 +123,7 @@ export const useCompaniesColumns = () => {
}}
/>
),
size: 170,
}),
columnHelper.accessor('creationDate', {
header: () => (
Expand All @@ -134,6 +139,7 @@ export const useCompaniesColumns = () => {
}}
/>
),
size: 70,
}),
columnHelper.accessor('accountOwner', {
header: () => (
Expand Down
94 changes: 66 additions & 28 deletions front/src/pages/companies/companies-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import {
TbLink,
TbMapPin,
TbSum,
TbUser,
} from 'react-icons/tb';
import { Company } from '../../interfaces/entities/company.interface';
import { FilterConfigType } from '../../interfaces/filters/interface';
import { SEARCH_USER_QUERY } from '../../services/api/search/search';
import { User, mapToUser } from '../../interfaces/entities/user.interface';

export const nameFilter = {
key: 'company_name',
Expand All @@ -31,6 +34,33 @@ export const nameFilter = {
],
} satisfies FilterConfigType<Company, string>;

export const employeesFilter = {
key: 'company_employees',
label: 'Employees',
icon: <TbSum size={16} />,
type: 'text',
operands: [
{
label: 'Greater than',
id: 'greater_than',
whereTemplate: (searchString) => ({
employees: {
_gte: isNaN(Number(searchString)) ? undefined : Number(searchString),
},
}),
},
{
label: 'Less than',
id: 'less_than',
whereTemplate: (searchString) => ({
employees: {
_lte: isNaN(Number(searchString)) ? undefined : Number(searchString),
},
}),
},
],
} satisfies FilterConfigType<Company, string>;

export const urlFilter = {
key: 'company_domain_name',
label: 'Url',
Expand Down Expand Up @@ -77,33 +107,6 @@ export const addressFilter = {
],
} satisfies FilterConfigType<Company, string>;

export const employeesFilter = {
key: 'company_employees',
label: 'Employees',
icon: <TbSum size={16} />,
type: 'text',
operands: [
{
label: 'Greater than',
id: 'greater_than',
whereTemplate: (searchString) => ({
employees: {
_gte: isNaN(Number(searchString)) ? undefined : Number(searchString),
},
}),
},
{
label: 'Less than',
id: 'less_than',
whereTemplate: (searchString) => ({
employees: {
_lte: isNaN(Number(searchString)) ? undefined : Number(searchString),
},
}),
},
],
} satisfies FilterConfigType<Company, string>;

export const creationDateFilter = {
key: 'company_created_at',
label: 'Created At',
Expand Down Expand Up @@ -131,10 +134,45 @@ export const creationDateFilter = {
],
} satisfies FilterConfigType<Company, string>;

export const accountOwnerFilter = {
key: 'account_owner_name',
label: 'Account Owner',
icon: <TbUser size={16} />,
type: 'relation',
searchConfig: {
query: SEARCH_USER_QUERY,
template: (searchString: string) => ({
displayName: { _ilike: `%${searchString}%` },
}),
resultMapper: (data) => ({
value: mapToUser(data),
render: (owner) => owner.displayName,
}),
},
selectedValueRender: (owner) => owner.displayName || '',
operands: [
{
label: 'Is',
id: 'is',
whereTemplate: (owner) => ({
account_owner: { displayName: { _eq: owner.displayName } },
}),
},
{
label: 'Is not',
id: 'is_not',
whereTemplate: (owner) => ({
_not: { account_owner: { displayName: { _eq: owner.displayName } } },
}),
},
],
} satisfies FilterConfigType<Company, User>;

export const availableFilters = [
nameFilter,
employeesFilter,
urlFilter,
addressFilter,
employeesFilter,
creationDateFilter,
accountOwnerFilter,
];
Loading

0 comments on commit 67353ed

Please sign in to comment.