import React, { FC, useState, useCallback, } from 'react'; import { useTranslation } from 'react-i18next'; import UserGroupForm from '../UserGroup/UserGroupForm'; import UserGroupTable from '../UserGroup/UserGroupTable'; import UserGroupCreateModal from '../UserGroup/UserGroupCreateModal'; import UserGroupDeleteModal from '../UserGroup/UserGroupDeleteModal'; import UserGroupDropdown from '../UserGroup/UserGroupDropdown'; import UserGroupUserTable from './UserGroupUserTable'; import UserGroupUserModal from './UserGroupUserModal'; import UserGroupPageList from './UserGroupPageList'; import { apiv3Get, apiv3Put, apiv3Delete, apiv3Post, } from '~/client/util/apiv3-client'; import { toastSuccess, toastError } from '~/client/util/apiNotification'; import { IPageHasId } from '~/interfaces/page'; import { IUserGroup, IUserGroupHasId, } from '~/interfaces/user'; import { useSWRxUserGroupPages, useSWRxUserGroupRelationList, useSWRxChildUserGroupList, useSWRxSelectableUserGroups, } from '~/stores/user-group'; import { useIsAclEnabled } from '~/stores/context'; const UserGroupDetailPage: FC = () => { const { t } = useTranslation(); const adminUserGroupDetailElem = document.getElementById('admin-user-group-detail'); /* * State (from AdminUserGroupDetailContainer) */ const [userGroup, setUserGroup] = useState(JSON.parse(adminUserGroupDetailElem?.getAttribute('data-user-group') || 'null')); const [relatedPages, setRelatedPages] = useState([]); // For page list const [searchType, setSearchType] = useState('partial'); const [isAlsoMailSearched, setAlsoMailSearched] = useState(false); const [isAlsoNameSearched, setAlsoNameSearched] = useState(false); const [selectedUserGroup, setSelectedUserGroup] = useState(undefined); // not null but undefined (to use defaultProps in UserGroupDeleteModal) const [isCreateModalShown, setCreateModalShown] = useState(false); const [isDeleteModalShown, setDeleteModalShown] = useState(false); /* * Fetch */ const { data: userGroupPages } = useSWRxUserGroupPages(userGroup._id, 10, 0); const { data: childUserGroupsList, mutate: mutateChildUserGroups } = useSWRxChildUserGroupList([userGroup._id], true); const childUserGroups = childUserGroupsList != null ? childUserGroupsList.childUserGroups : []; const grandChildUserGroups = childUserGroupsList != null ? childUserGroupsList.grandChildUserGroups : []; const childUserGroupIds = childUserGroups.map(group => group._id); const { data: userGroupRelationList, mutate: mutateUserGroupRelations } = useSWRxUserGroupRelationList(childUserGroupIds); const childUserGroupRelations = userGroupRelationList != null ? userGroupRelationList : []; const { data: selectableUserGroups, mutate: mutateSelectableUserGroups } = useSWRxSelectableUserGroups(userGroup._id); const { data: isAclEnabled } = useIsAclEnabled(); /* * Function */ // TODO 85062: old name: switchIsAlsoMailSearched const toggleIsAlsoMailSearched = useCallback(() => { setAlsoMailSearched(prev => !prev); }, []); // TODO 85062: old name: switchIsAlsoNameSearched const toggleAlsoNameSearched = useCallback(() => { setAlsoNameSearched(prev => !prev); }, []); const switchSearchType = useCallback((searchType) => { setSearchType(searchType); }, []); const updateUserGroup = useCallback(async(param: Partial) => { try { const res = await apiv3Put<{ userGroup: IUserGroupHasId }>(`/user-groups/${userGroup._id}`, param); const { userGroup: newUserGroup } = res.data; setUserGroup(newUserGroup); toastSuccess(t('toaster.update_successed', { target: t('UserGroup') })); } catch (err) { toastError(err); } }, [t, userGroup._id, setUserGroup]); const fetchApplicableUsers = useCallback(async(searchWord) => { const res = await apiv3Get(`/user-groups/${userGroup._id}/unrelated-users`, { searchWord, searchType, isAlsoMailSearched, isAlsoNameSearched, }); const { users } = res.data; return users; }, [searchType, isAlsoMailSearched, isAlsoNameSearched]); // TODO 85062: will be used in UserGroupUserFormByInput const addUserByUsername = useCallback(async(username: string) => { await apiv3Post(`/user-groups/${userGroup._id}/users/${username}`); mutateUserGroupRelations(); }, [userGroup, mutateUserGroupRelations]); const removeUserByUsername = useCallback(async(username: string) => { await apiv3Delete(`/user-groups/${userGroup._id}/users/${username}`); mutateUserGroupRelations(); }, [userGroup, mutateUserGroupRelations]); const onClickAddChildButtonHandler = async(selectedUserGroup: IUserGroupHasId) => { try { await apiv3Put(`/user-groups/${selectedUserGroup._id}`, { name: selectedUserGroup.name, description: selectedUserGroup.description, parentId: userGroup._id, forceUpdateParents: false, }); mutateSelectableUserGroups(); mutateChildUserGroups(); toastSuccess(t('toaster.update_successed', { target: t('UserGroup') })); } catch (err) { toastError(err); } }; // TODO 87614: UserGroup New creation form can be displayed in modal const onClickCreateChildGroupButtonHandler = () => { console.log('button clicked!'); }; const showCreateModal = useCallback(() => { setCreateModalShown(true); }, [setCreateModalShown]); const hideCreateModal = useCallback(() => { setCreateModalShown(false); }, [setCreateModalShown]); const createChildUserGroup = useCallback(async(userGroupData: IUserGroup) => { try { await apiv3Post('/user-groups', { name: userGroupData.name, description: userGroupData.description, parentId: userGroup._id, }); toastSuccess(t('toaster.update_successed', { target: t('UserGroup') })); } catch (err) { toastError(err); } }, [userGroup, t]); const showDeleteModal = useCallback(async(group: IUserGroupHasId) => { setSelectedUserGroup(group); setDeleteModalShown(true); }, [setSelectedUserGroup, setDeleteModalShown]); const hideDeleteModal = useCallback(() => { setSelectedUserGroup(undefined); setDeleteModalShown(false); }, [setSelectedUserGroup, setDeleteModalShown]); const deleteChildUserGroupById = useCallback(async(deleteGroupId: string, actionName: string, transferToUserGroupId: string) => { try { const res = await apiv3Delete(`/user-groups/${deleteGroupId}`, { actionName, transferToUserGroupId, }); // sync await mutateChildUserGroups(); setSelectedUserGroup(undefined); setDeleteModalShown(false); toastSuccess(`Deleted ${res.data.userGroups.length} groups.`); } catch (err) { toastError(new Error('Unable to delete the groups')); } }, [mutateChildUserGroups, setSelectedUserGroup, setDeleteModalShown]); /* * Dependencies */ if (userGroup == null) { return <>; } return (
{t('admin:user_group_management.back_to_list')} {/* TODO 85062: Link to the ancestors group */}

{t('admin:user_group_management.user_list')}

{t('admin:user_group_management.child_group_list')}

<>

{t('Page')}

); }; export default UserGroupDetailPage;