|
@@ -19,6 +19,8 @@ import ListSubheader from "@mui/material/ListSubheader"; |
|
|
import groupBy from "lodash/groupBy"; |
|
|
import groupBy from "lodash/groupBy"; |
|
|
import uniqBy from "lodash/uniqBy"; |
|
|
import uniqBy from "lodash/uniqBy"; |
|
|
import { useTranslation } from "react-i18next"; |
|
|
import { useTranslation } from "react-i18next"; |
|
|
|
|
|
import union from "lodash/union"; |
|
|
|
|
|
import intersectionBy from "lodash/intersectionBy"; |
|
|
|
|
|
|
|
|
export interface LabelGroup { |
|
|
export interface LabelGroup { |
|
|
id: number; |
|
|
id: number; |
|
@@ -47,6 +49,10 @@ interface ItemListProps { |
|
|
items: LabelWithId[], |
|
|
items: LabelWithId[], |
|
|
checkedItems: LabelWithId[], |
|
|
checkedItems: LabelWithId[], |
|
|
) => React.MouseEventHandler; |
|
|
) => React.MouseEventHandler; |
|
|
|
|
|
handleToggleAllInGroup: ( |
|
|
|
|
|
groupItems: LabelWithId[], |
|
|
|
|
|
checkedItems: LabelWithId[], |
|
|
|
|
|
) => React.MouseEventHandler; |
|
|
handleToggle: (item: LabelWithId) => React.MouseEventHandler; |
|
|
handleToggle: (item: LabelWithId) => React.MouseEventHandler; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -56,6 +62,7 @@ const ItemList: React.FC<ItemListProps> = ({ |
|
|
label, |
|
|
label, |
|
|
handleToggle, |
|
|
handleToggle, |
|
|
handleToggleAll, |
|
|
handleToggleAll, |
|
|
|
|
|
handleToggleAllInGroup, |
|
|
}) => { |
|
|
}) => { |
|
|
const { t } = useTranslation(); |
|
|
const { t } = useTranslation(); |
|
|
const groups: LabelGroup[] = uniqBy( |
|
|
const groups: LabelGroup[] = uniqBy( |
|
@@ -111,14 +118,34 @@ const ItemList: React.FC<ItemListProps> = ({ |
|
|
> |
|
|
> |
|
|
{groups.map((group) => { |
|
|
{groups.map((group) => { |
|
|
const groupItems = groupedItems[group.id]; |
|
|
const groupItems = groupedItems[group.id]; |
|
|
|
|
|
const selectedGroupItems = intersectionBy( |
|
|
|
|
|
checkedItems, |
|
|
|
|
|
groupItems, |
|
|
|
|
|
"id", |
|
|
|
|
|
); |
|
|
if (!groupItems) return null; |
|
|
if (!groupItems) return null; |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<React.Fragment key={group.id}> |
|
|
<React.Fragment key={group.id}> |
|
|
<ListSubheader |
|
|
<ListSubheader |
|
|
disableSticky |
|
|
disableSticky |
|
|
sx={{ paddingBlock: 2, lineHeight: 1.8 }} |
|
|
|
|
|
|
|
|
onClick={handleToggleAllInGroup(groupItems, checkedItems)} |
|
|
|
|
|
sx={{ |
|
|
|
|
|
paddingBlock: 2, |
|
|
|
|
|
lineHeight: 1.8, |
|
|
|
|
|
display: "flex", |
|
|
|
|
|
alignItems: "center", |
|
|
|
|
|
}} |
|
|
> |
|
|
> |
|
|
|
|
|
<ListItemIcon> |
|
|
|
|
|
<Checkbox |
|
|
|
|
|
checked={selectedGroupItems.length === groupItems.length} |
|
|
|
|
|
indeterminate={ |
|
|
|
|
|
selectedGroupItems.length !== groupItems.length && |
|
|
|
|
|
selectedGroupItems.length !== 0 |
|
|
|
|
|
} |
|
|
|
|
|
/> |
|
|
|
|
|
</ListItemIcon> |
|
|
{group.name} |
|
|
{group.name} |
|
|
</ListSubheader> |
|
|
</ListSubheader> |
|
|
{groupItems.map((item) => { |
|
|
{groupItems.map((item) => { |
|
@@ -210,6 +237,18 @@ const TransferList: React.FC<TransferListProps> = ({ |
|
|
setCheckedList(differenceBy(checkedList, rightListChecked, "id")); |
|
|
setCheckedList(differenceBy(checkedList, rightListChecked, "id")); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleToggleAllInGroup = React.useCallback( |
|
|
|
|
|
(groupItems: LabelWithId[], checkedItems: LabelWithId[]) => () => { |
|
|
|
|
|
const selectedGroupItems = intersectionBy(checkedItems, groupItems, "id"); |
|
|
|
|
|
if (selectedGroupItems.length !== groupItems.length) { |
|
|
|
|
|
setCheckedList(union(checkedList, groupItems)); |
|
|
|
|
|
} else { |
|
|
|
|
|
setCheckedList(differenceBy(checkedList, groupItems, "id")); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
[checkedList], |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<Stack spacing={2} direction="row" alignItems="center" position="relative"> |
|
|
<Stack spacing={2} direction="row" alignItems="center" position="relative"> |
|
|
<ItemList |
|
|
<ItemList |
|
@@ -218,6 +257,7 @@ const TransferList: React.FC<TransferListProps> = ({ |
|
|
label={allItemsLabel} |
|
|
label={allItemsLabel} |
|
|
handleToggleAll={handleToggleAll} |
|
|
handleToggleAll={handleToggleAll} |
|
|
handleToggle={handleToggle} |
|
|
handleToggle={handleToggle} |
|
|
|
|
|
handleToggleAllInGroup={handleToggleAllInGroup} |
|
|
/> |
|
|
/> |
|
|
<ItemList |
|
|
<ItemList |
|
|
items={rightList} |
|
|
items={rightList} |
|
@@ -225,6 +265,7 @@ const TransferList: React.FC<TransferListProps> = ({ |
|
|
label={selectedItemsLabel} |
|
|
label={selectedItemsLabel} |
|
|
handleToggleAll={handleToggleAll} |
|
|
handleToggleAll={handleToggleAll} |
|
|
handleToggle={handleToggle} |
|
|
handleToggle={handleToggle} |
|
|
|
|
|
handleToggleAllInGroup={handleToggleAllInGroup} |
|
|
/> |
|
|
/> |
|
|
<Stack |
|
|
<Stack |
|
|
spacing={1} |
|
|
spacing={1} |
|
|