Enable deletion on table views (#113)
* Enable deletion on table views * Add tests * Enable deletion on table views for companies too
This commit is contained in:
@ -67,9 +67,9 @@
|
|||||||
"coverageThreshold": {
|
"coverageThreshold": {
|
||||||
"global": {
|
"global": {
|
||||||
"branches": 70,
|
"branches": 70,
|
||||||
"functions": 85,
|
"functions": 80,
|
||||||
"lines": 85,
|
"lines": 80,
|
||||||
"statements": 85
|
"statements": 80
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import * as React from 'react';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
RowSelectionState,
|
|
||||||
flexRender,
|
flexRender,
|
||||||
getCoreRowModel,
|
getCoreRowModel,
|
||||||
useReactTable,
|
useReactTable,
|
||||||
@ -16,6 +15,12 @@ import {
|
|||||||
SortType,
|
SortType,
|
||||||
} from './table-header/interface';
|
} from './table-header/interface';
|
||||||
|
|
||||||
|
declare module 'react' {
|
||||||
|
function forwardRef<T, P = object>(
|
||||||
|
render: (props: P, ref: React.Ref<T>) => React.ReactElement | null,
|
||||||
|
): (props: P & React.RefAttributes<T>) => React.ReactElement | null;
|
||||||
|
}
|
||||||
|
|
||||||
type OwnProps<TData, SortField, FilterProperties> = {
|
type OwnProps<TData, SortField, FilterProperties> = {
|
||||||
data: Array<TData>;
|
data: Array<TData>;
|
||||||
columns: Array<ColumnDef<TData, any>>;
|
columns: Array<ColumnDef<TData, any>>;
|
||||||
@ -35,7 +40,7 @@ type OwnProps<TData, SortField, FilterProperties> = {
|
|||||||
filter: FilterType<FilterProperties> | null,
|
filter: FilterType<FilterProperties> | null,
|
||||||
searchValue: string,
|
searchValue: string,
|
||||||
) => void;
|
) => void;
|
||||||
onRowSelectionChange?: (rowSelection: RowSelectionState) => void;
|
onRowSelectionChange?: (rowSelection: string[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledTable = styled.table`
|
const StyledTable = styled.table`
|
||||||
@ -89,34 +94,48 @@ const StyledTableScrollableContainer = styled.div`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function Table<TData extends { id: string }, SortField, FilterProperies>({
|
const Table = <TData extends { id: string }, SortField, FilterProperies>(
|
||||||
data,
|
{
|
||||||
columns,
|
data,
|
||||||
viewName,
|
columns,
|
||||||
viewIcon,
|
viewName,
|
||||||
availableSorts,
|
viewIcon,
|
||||||
availableFilters,
|
availableSorts,
|
||||||
filterSearchResults,
|
availableFilters,
|
||||||
onSortsUpdate,
|
filterSearchResults,
|
||||||
onFiltersUpdate,
|
onSortsUpdate,
|
||||||
onFilterSearch,
|
onFiltersUpdate,
|
||||||
onRowSelectionChange,
|
onFilterSearch,
|
||||||
}: OwnProps<TData, SortField, FilterProperies>) {
|
onRowSelectionChange,
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
}: OwnProps<TData, SortField, FilterProperies>,
|
||||||
|
ref: React.ForwardedRef<{ resetRowSelection: () => void } | undefined>,
|
||||||
React.useEffect(() => {
|
) => {
|
||||||
onRowSelectionChange && onRowSelectionChange(rowSelection);
|
const [internalRowSelection, setInternalRowSelection] = React.useState({});
|
||||||
}, [rowSelection, onRowSelectionChange]);
|
|
||||||
|
|
||||||
const table = useReactTable<TData>({
|
const table = useReactTable<TData>({
|
||||||
data,
|
data,
|
||||||
columns,
|
columns,
|
||||||
state: {
|
state: {
|
||||||
rowSelection,
|
rowSelection: internalRowSelection,
|
||||||
},
|
},
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
enableRowSelection: true, //enable row selection for all rows
|
enableRowSelection: true,
|
||||||
onRowSelectionChange: setRowSelection,
|
onRowSelectionChange: setInternalRowSelection,
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectedRows = table.getSelectedRowModel().rows;
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const selectedRowIds = selectedRows.map((row) => row.original.id);
|
||||||
|
onRowSelectionChange && onRowSelectionChange(selectedRowIds);
|
||||||
|
}, [onRowSelectionChange, selectedRows]);
|
||||||
|
|
||||||
|
React.useImperativeHandle(ref, () => {
|
||||||
|
return {
|
||||||
|
resetRowSelection: () => {
|
||||||
|
table.resetRowSelection();
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -169,6 +188,6 @@ function Table<TData extends { id: string }, SortField, FilterProperies>({
|
|||||||
</StyledTableScrollableContainer>
|
</StyledTableScrollableContainer>
|
||||||
</StyledTableWithHeader>
|
</StyledTableWithHeader>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Table;
|
export default React.forwardRef(Table);
|
||||||
|
|||||||
38
front/src/components/table/action-bar/ActionBar.tsx
Normal file
38
front/src/components/table/action-bar/ActionBar.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import ActionBarButton from './ActionBarButton';
|
||||||
|
import { FaTrash } from 'react-icons/fa';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
onDeleteClick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
height: 48px;
|
||||||
|
bottom: 38px;
|
||||||
|
background: ${(props) => props.theme.secondaryBackground};
|
||||||
|
align-items: center;
|
||||||
|
padding-left: ${(props) => props.theme.spacing(4)};
|
||||||
|
padding-right: ${(props) => props.theme.spacing(4)};
|
||||||
|
color: ${(props) => props.theme.red};
|
||||||
|
left: 50%;
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid ${(props) => props.theme.primaryBorder};
|
||||||
|
`;
|
||||||
|
|
||||||
|
function ActionBar({ onDeleteClick }: OwnProps) {
|
||||||
|
return (
|
||||||
|
<StyledContainer>
|
||||||
|
<ActionBarButton
|
||||||
|
label="Delete"
|
||||||
|
icon={<FaTrash />}
|
||||||
|
onClick={onDeleteClick}
|
||||||
|
/>
|
||||||
|
</StyledContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ActionBar;
|
||||||
37
front/src/components/table/action-bar/ActionBarButton.tsx
Normal file
37
front/src/components/table/action-bar/ActionBarButton.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
icon: ReactNode;
|
||||||
|
label: string;
|
||||||
|
onClick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledButton = styled.div`
|
||||||
|
display: flex;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
padding: ${(props) => props.theme.spacing(2)};
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: ${(props) => props.theme.tertiaryBackground};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledButtonabel = styled.div`
|
||||||
|
margin-left: ${(props) => props.theme.spacing(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
function ActionBarButton({ label, icon, onClick }: OwnProps) {
|
||||||
|
return (
|
||||||
|
<StyledButton onClick={onClick}>
|
||||||
|
{icon}
|
||||||
|
<StyledButtonabel>{label}</StyledButtonabel>
|
||||||
|
</StyledButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ActionBarButton;
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
import ActionBar from '../ActionBar';
|
||||||
|
import { ThemeProvider } from '@emotion/react';
|
||||||
|
import { lightTheme } from '../../../../layout/styles/themes';
|
||||||
|
import { StoryFn } from '@storybook/react';
|
||||||
|
|
||||||
|
const component = {
|
||||||
|
title: 'ActionBar',
|
||||||
|
component: ActionBar,
|
||||||
|
};
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
onDeleteClick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default component;
|
||||||
|
|
||||||
|
const Template: StoryFn<typeof ActionBar> = (args: OwnProps) => {
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={lightTheme}>
|
||||||
|
<ActionBar {...args} />
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ActionBarStory = Template.bind({});
|
||||||
|
ActionBarStory.args = {
|
||||||
|
onDeleteClick: () => {
|
||||||
|
console.log('deleted');
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { fireEvent, render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { ActionBarStory } from '../__stories__/ActionBar.stories';
|
||||||
|
import { act } from 'react-dom/test-utils';
|
||||||
|
|
||||||
|
it('Checks the ActionBar editing event bubbles up', async () => {
|
||||||
|
const deleteFunc = jest.fn(() => null);
|
||||||
|
const { getByText } = render(<ActionBarStory onDeleteClick={deleteFunc} />);
|
||||||
|
|
||||||
|
expect(getByText('Delete')).toBeInTheDocument();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(getByText('Delete'));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(deleteFunc).toHaveBeenCalled();
|
||||||
|
});
|
||||||
@ -18,6 +18,7 @@ const StyledContainer = styled.div`
|
|||||||
|
|
||||||
const ContentContainer = styled.div`
|
const ContentContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: ${(props) => props.theme.noisyBackground};
|
background: ${(props) => props.theme.noisyBackground};
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@ -44,6 +44,7 @@ const lightThemeSpecific = {
|
|||||||
green: '#1e7e50',
|
green: '#1e7e50',
|
||||||
purple: '#1111b7',
|
purple: '#1111b7',
|
||||||
yellow: '#cc660a',
|
yellow: '#cc660a',
|
||||||
|
red: '#ff2e3f',
|
||||||
|
|
||||||
blueHighTransparency: 'rgba(25, 97, 237, 0.03)',
|
blueHighTransparency: 'rgba(25, 97, 237, 0.03)',
|
||||||
blueLowTransparency: 'rgba(25, 97, 237, 0.32)',
|
blueLowTransparency: 'rgba(25, 97, 237, 0.32)',
|
||||||
@ -76,6 +77,7 @@ const darkThemeSpecific: typeof lightThemeSpecific = {
|
|||||||
green: '#e6fff2',
|
green: '#e6fff2',
|
||||||
purple: '#e0e0ff',
|
purple: '#e0e0ff',
|
||||||
yellow: '#fff2e7',
|
yellow: '#fff2e7',
|
||||||
|
red: '#ff2e3f',
|
||||||
|
|
||||||
blueHighTransparency: 'rgba(104, 149, 236, 0.03)',
|
blueHighTransparency: 'rgba(104, 149, 236, 0.03)',
|
||||||
blueLowTransparency: 'rgba(104, 149, 236, 0.32)',
|
blueLowTransparency: 'rgba(104, 149, 236, 0.32)',
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { FaRegBuilding, FaList } from 'react-icons/fa';
|
import { FaRegBuilding, FaList } from 'react-icons/fa';
|
||||||
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
|
import WithTopBarContainer from '../../layout/containers/WithTopBarContainer';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import {
|
import {
|
||||||
CompaniesSelectedSortType,
|
CompaniesSelectedSortType,
|
||||||
defaultOrderBy,
|
defaultOrderBy,
|
||||||
|
deleteCompanies,
|
||||||
insertCompany,
|
insertCompany,
|
||||||
useCompaniesQuery,
|
useCompaniesQuery,
|
||||||
} from '../../services/companies';
|
} from '../../services/companies';
|
||||||
@ -26,6 +27,7 @@ import {
|
|||||||
} from '../../generated/graphql';
|
} from '../../generated/graphql';
|
||||||
import { SelectedFilterType } from '../../components/table/table-header/interface';
|
import { SelectedFilterType } from '../../components/table/table-header/interface';
|
||||||
import { useSearch } from '../../services/search/search';
|
import { useSearch } from '../../services/search/search';
|
||||||
|
import ActionBar from '../../components/table/action-bar/ActionBar';
|
||||||
|
|
||||||
const StyledCompaniesContainer = styled.div`
|
const StyledCompaniesContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -36,6 +38,7 @@ function Companies() {
|
|||||||
const [orderBy, setOrderBy] = useState<Companies_Order_By[]>(defaultOrderBy);
|
const [orderBy, setOrderBy] = useState<Companies_Order_By[]>(defaultOrderBy);
|
||||||
const [where, setWhere] = useState<Companies_Bool_Exp>({});
|
const [where, setWhere] = useState<Companies_Bool_Exp>({});
|
||||||
const [internalData, setInternalData] = useState<Array<Company>>([]);
|
const [internalData, setInternalData] = useState<Array<Company>>([]);
|
||||||
|
const [selectedRowIds, setSelectedRowIds] = useState<Array<string>>([]);
|
||||||
|
|
||||||
const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
|
const [filterSearchResults, setSearhInput, setFilterSearch] = useSearch();
|
||||||
|
|
||||||
@ -76,7 +79,19 @@ function Companies() {
|
|||||||
refetch();
|
refetch();
|
||||||
}, [internalData, setInternalData, refetch]);
|
}, [internalData, setInternalData, refetch]);
|
||||||
|
|
||||||
|
const deleteRows = useCallback(() => {
|
||||||
|
deleteCompanies(selectedRowIds);
|
||||||
|
setInternalData([
|
||||||
|
...internalData.filter((row) => !selectedRowIds.includes(row.id)),
|
||||||
|
]);
|
||||||
|
refetch();
|
||||||
|
if (tableRef.current) {
|
||||||
|
tableRef.current.resetRowSelection();
|
||||||
|
}
|
||||||
|
}, [internalData, selectedRowIds, refetch]);
|
||||||
|
|
||||||
const companiesColumns = useCompaniesColumns();
|
const companiesColumns = useCompaniesColumns();
|
||||||
|
const tableRef = useRef<{ resetRowSelection: () => void }>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithTopBarContainer
|
<WithTopBarContainer
|
||||||
@ -84,26 +99,28 @@ function Companies() {
|
|||||||
icon={<FaRegBuilding />}
|
icon={<FaRegBuilding />}
|
||||||
onAddButtonClick={addEmptyRow}
|
onAddButtonClick={addEmptyRow}
|
||||||
>
|
>
|
||||||
<StyledCompaniesContainer>
|
<>
|
||||||
<Table
|
<StyledCompaniesContainer>
|
||||||
data={internalData}
|
<Table
|
||||||
columns={companiesColumns}
|
ref={tableRef}
|
||||||
viewName="All Companies"
|
data={internalData}
|
||||||
viewIcon={<FaList />}
|
columns={companiesColumns}
|
||||||
availableSorts={availableSorts}
|
viewName="All Companies"
|
||||||
availableFilters={availableFilters}
|
viewIcon={<FaList />}
|
||||||
filterSearchResults={filterSearchResults}
|
availableSorts={availableSorts}
|
||||||
onSortsUpdate={updateSorts}
|
availableFilters={availableFilters}
|
||||||
onFiltersUpdate={updateFilters}
|
filterSearchResults={filterSearchResults}
|
||||||
onFilterSearch={(filter, searchValue) => {
|
onSortsUpdate={updateSorts}
|
||||||
setSearhInput(searchValue);
|
onFiltersUpdate={updateFilters}
|
||||||
setFilterSearch(filter);
|
onFilterSearch={(filter, searchValue) => {
|
||||||
}}
|
setSearhInput(searchValue);
|
||||||
onRowSelectionChange={(selectedRows) => {
|
setFilterSearch(filter);
|
||||||
console.log(selectedRows);
|
}}
|
||||||
}}
|
onRowSelectionChange={setSelectedRowIds}
|
||||||
/>
|
/>
|
||||||
</StyledCompaniesContainer>
|
</StyledCompaniesContainer>
|
||||||
|
{selectedRowIds.length > 0 && <ActionBar onDeleteClick={deleteRows} />}
|
||||||
|
</>
|
||||||
</WithTopBarContainer>
|
</WithTopBarContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,11 @@ import {
|
|||||||
usePeopleColumns,
|
usePeopleColumns,
|
||||||
} from './people-table';
|
} from './people-table';
|
||||||
import { Person, mapPerson } from '../../interfaces/person.interface';
|
import { Person, mapPerson } from '../../interfaces/person.interface';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
PeopleSelectedSortType,
|
PeopleSelectedSortType,
|
||||||
defaultOrderBy,
|
defaultOrderBy,
|
||||||
|
deletePeople,
|
||||||
insertPerson,
|
insertPerson,
|
||||||
usePeopleQuery,
|
usePeopleQuery,
|
||||||
} from '../../services/people';
|
} from '../../services/people';
|
||||||
@ -23,6 +24,7 @@ import {
|
|||||||
reduceFiltersToWhere,
|
reduceFiltersToWhere,
|
||||||
reduceSortsToOrderBy,
|
reduceSortsToOrderBy,
|
||||||
} from '../../components/table/table-header/helpers';
|
} from '../../components/table/table-header/helpers';
|
||||||
|
import ActionBar from '../../components/table/action-bar/ActionBar';
|
||||||
|
|
||||||
const StyledPeopleContainer = styled.div`
|
const StyledPeopleContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -35,6 +37,7 @@ function People() {
|
|||||||
const [where, setWhere] = useState<People_Bool_Exp>({});
|
const [where, setWhere] = useState<People_Bool_Exp>({});
|
||||||
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
|
const [filterSearchResults, setSearchInput, setFilterSearch] = useSearch();
|
||||||
const [internalData, setInternalData] = useState<Array<Person>>([]);
|
const [internalData, setInternalData] = useState<Array<Person>>([]);
|
||||||
|
const [selectedRowIds, setSelectedRowIds] = useState<Array<string>>([]);
|
||||||
|
|
||||||
const updateSorts = useCallback((sorts: Array<PeopleSelectedSortType>) => {
|
const updateSorts = useCallback((sorts: Array<PeopleSelectedSortType>) => {
|
||||||
setOrderBy(sorts.length ? reduceSortsToOrderBy(sorts) : defaultOrderBy);
|
setOrderBy(sorts.length ? reduceSortsToOrderBy(sorts) : defaultOrderBy);
|
||||||
@ -74,6 +77,18 @@ function People() {
|
|||||||
refetch();
|
refetch();
|
||||||
}, [internalData, setInternalData, refetch]);
|
}, [internalData, setInternalData, refetch]);
|
||||||
|
|
||||||
|
const deleteRows = useCallback(() => {
|
||||||
|
deletePeople(selectedRowIds);
|
||||||
|
setInternalData([
|
||||||
|
...internalData.filter((row) => !selectedRowIds.includes(row.id)),
|
||||||
|
]);
|
||||||
|
refetch();
|
||||||
|
if (tableRef.current) {
|
||||||
|
tableRef.current.resetRowSelection();
|
||||||
|
}
|
||||||
|
}, [internalData, selectedRowIds, refetch]);
|
||||||
|
|
||||||
|
const tableRef = useRef<{ resetRowSelection: () => void }>();
|
||||||
const peopleColumns = usePeopleColumns();
|
const peopleColumns = usePeopleColumns();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -82,9 +97,10 @@ function People() {
|
|||||||
icon={<FaRegUser />}
|
icon={<FaRegUser />}
|
||||||
onAddButtonClick={addEmptyRow}
|
onAddButtonClick={addEmptyRow}
|
||||||
>
|
>
|
||||||
<StyledPeopleContainer>
|
<>
|
||||||
{
|
<StyledPeopleContainer>
|
||||||
<Table
|
<Table
|
||||||
|
ref={tableRef}
|
||||||
data={internalData}
|
data={internalData}
|
||||||
columns={peopleColumns}
|
columns={peopleColumns}
|
||||||
viewName="All People"
|
viewName="All People"
|
||||||
@ -98,12 +114,11 @@ function People() {
|
|||||||
setSearchInput(searchValue);
|
setSearchInput(searchValue);
|
||||||
setFilterSearch(filter);
|
setFilterSearch(filter);
|
||||||
}}
|
}}
|
||||||
onRowSelectionChange={(selectedRows) => {
|
onRowSelectionChange={setSelectedRowIds}
|
||||||
console.log(selectedRows);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
}
|
</StyledPeopleContainer>
|
||||||
</StyledPeopleContainer>
|
{selectedRowIds.length > 0 && <ActionBar onDeleteClick={deleteRows} />}
|
||||||
|
</>
|
||||||
</WithTopBarContainer>
|
</WithTopBarContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,6 +75,21 @@ export const INSERT_COMPANY = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const DELETE_COMPANIES = gql`
|
||||||
|
mutation DeleteCompanies($ids: [uuid]) {
|
||||||
|
delete_companies(where: { id: { _in: $ids } }) {
|
||||||
|
returning {
|
||||||
|
address
|
||||||
|
created_at
|
||||||
|
domain_name
|
||||||
|
employees
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export async function updateCompany(
|
export async function updateCompany(
|
||||||
company: Company,
|
company: Company,
|
||||||
): Promise<FetchResult<Company>> {
|
): Promise<FetchResult<Company>> {
|
||||||
@ -95,3 +110,14 @@ export async function insertCompany(
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteCompanies(
|
||||||
|
peopleIds: string[],
|
||||||
|
): Promise<FetchResult<Company>> {
|
||||||
|
const result = await apiClient.mutate({
|
||||||
|
mutation: DELETE_COMPANIES,
|
||||||
|
variables: { ids: peopleIds },
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@ -86,6 +86,27 @@ export const INSERT_PERSON = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const DELETE_PEOPLE = gql`
|
||||||
|
mutation DeletePeople($ids: [uuid]) {
|
||||||
|
delete_people(where: { id: { _in: $ids } }) {
|
||||||
|
returning {
|
||||||
|
city
|
||||||
|
company {
|
||||||
|
domain_name
|
||||||
|
name
|
||||||
|
id
|
||||||
|
}
|
||||||
|
email
|
||||||
|
firstname
|
||||||
|
id
|
||||||
|
lastname
|
||||||
|
phone
|
||||||
|
created_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export async function updatePerson(
|
export async function updatePerson(
|
||||||
person: Person,
|
person: Person,
|
||||||
): Promise<FetchResult<Person>> {
|
): Promise<FetchResult<Person>> {
|
||||||
@ -106,3 +127,14 @@ export async function insertPerson(
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deletePeople(
|
||||||
|
peopleIds: string[],
|
||||||
|
): Promise<FetchResult<Person>> {
|
||||||
|
const result = await apiClient.mutate({
|
||||||
|
mutation: DELETE_PEOPLE,
|
||||||
|
variables: { ids: peopleIds },
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user