import React, { FC, useState, useCallback, useEffect, } from 'react'; import { useTranslation } from 'react-i18next'; import { TFunctionResult } from 'i18next'; import dateFnsFormat from 'date-fns/format'; import Xss from '~/services/xss'; import { IUserGroupHasId, IUserGroupRelation, IUserHasId } from '~/interfaces/user'; import { CustomWindow } from '~/interfaces/global'; type Props = { headerLabel?: TFunctionResult, userGroups: IUserGroupHasId[], userGroupRelations: IUserGroupRelation[], childUserGroups: IUserGroupHasId[], isAclEnabled: boolean, onDelete?: (userGroup: IUserGroupHasId) => void | Promise, }; /* * Utility */ const generateGroupIdToUsersMap = (userGroupRelations: IUserGroupRelation[]): Record[]> => { const userGroupMap = {}; userGroupRelations.forEach((relation) => { const group = relation.relatedGroup as string; // must be an id of related group const users: Partial[] = userGroupMap[group] || []; users.push(relation.relatedUser as IUserHasId); // register userGroupMap[group] = users; }); return userGroupMap; }; const generateGroupIdToChildGroupsMap = (childUserGroups: IUserGroupHasId[]): Record => { const map = {}; childUserGroups.forEach((group) => { const parentId = group.parent as string; // must be an id const groups: Partial[] = map[parentId] || []; groups.push(group); // register map[parentId] = groups; }); return map; }; const UserGroupTable: FC = (props: Props) => { const xss: Xss = (window as CustomWindow).xss; const { t } = useTranslation(); /* * State */ const [groupIdToUsersMap, setGroupIdToUsersMap] = useState(generateGroupIdToUsersMap(props.userGroupRelations)); const [groupIdToChildGroupsMap, setGroupIdToChildGroupsMap] = useState(generateGroupIdToChildGroupsMap(props.childUserGroups)); /* * Function */ const onClickDelete = useCallback((e) => { // no preventDefault if (props.onDelete == null) { return; } const groupId = e.target.getAttribute('data-user-group-id'); const group = props.userGroups.find((group) => { return group._id === groupId; }); if (group == null) { return; } props.onDelete(group); }, [props]); /* * useEffect */ useEffect(() => { setGroupIdToUsersMap(generateGroupIdToUsersMap(props.userGroupRelations)); setGroupIdToChildGroupsMap(generateGroupIdToChildGroupsMap(props.childUserGroups)); }, [props.userGroupRelations, props.childUserGroups]); return ( <>

{props.headerLabel}

{props.userGroups.map((group) => { const users = groupIdToUsersMap[group._id]; return ( {props.isAclEnabled ? ( ) : ( ) } {props.isAclEnabled ? ( ) : ( ) } ); })}
{t('Name')} {t('Description')} {t('User')} {t('ChildUserGroup')} {t('Created')}
{xss.process(group.name)}{xss.process(group.name)}{xss.process(group.description)}
    {users != null && users.map((user) => { return
  • {xss.process(user.username)}
  • ; })}
    {groupIdToChildGroupsMap[group._id] != null && groupIdToChildGroupsMap[group._id].map((group) => { return (
  • {props.isAclEnabled ? ( {xss.process(group.name)} ) : (

    {xss.process(group.name)}

    ) }
  • ); })}
{dateFnsFormat(new Date(group.createdAt), 'yyyy-MM-dd')}
{t('Edit')}
); }; export default UserGroupTable;