import { ActionLink, ColumnDef, DataTable, Loading } from '@/components/shared' import AdaptableCard from '@/components/shared/AdaptableCard' import Container from '@/components/shared/Container' import { Button, Card, Dialog, FormContainer, FormItem, Input, Notification, Select, Table, Tabs, toast, } from '@/components/ui' import TBody from '@/components/ui/Table/TBody' import Td from '@/components/ui/Table/Td' import Th from '@/components/ui/Table/Th' import THead from '@/components/ui/Table/THead' import Tr from '@/components/ui/Table/Tr' import TabContent from '@/components/ui/Tabs/TabContent' import TabList from '@/components/ui/Tabs/TabList' import TabNav from '@/components/ui/Tabs/TabNav' import { getRoles, getUsers } from '@/services/identity.service' import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models' import { CreateUpdateOrganizationUnitDto, OrganizationUnitDto, } from '@/proxy/admin/organization-unit/models' import { ouDelete, ouDeleteMembers, ouDeleteRoles, ouGetAll, ouGetMembers, ouGetRoles, ouMoveAllUsers, ouPost, ouPut, ouPutMembers, ouPutMove, ouPutRoles, } from '@/services/organization-unit.service' import { SelectBoxOption } from '@/shared/types' import { useLocalization } from '@/utils/hooks/useLocalization' import TableNoRecords from '@/views/shared/TableNoRecords' import classNames from 'classnames' import { Field, FieldProps, Form, Formik, FormikHelpers } from 'formik' import isEmpty from 'lodash/isEmpty' import { memo, Suspense, useEffect, useMemo, useState } from 'react' import { NodeApi, NodeRendererProps } from 'react-arborist' import { Tree } from 'react-arborist/dist/module/components/tree' import { Helmet } from 'react-helmet' import { FaCheckCircle, FaUser, FaFolder, FaMinusCircle, FaPlusCircle, FaTrash, FaSitemap, FaCogs, FaTrashAlt, FaEdit, FaUsers, FaUserPlus, FaUserShield, } from 'react-icons/fa' import { object, string } from 'yup' import { ROUTES_ENUM } from '@/routes/route.constant' const schema = object().shape({ id: string(), parentId: string(), displayName: string().required(), }) const schemaMoveAllUsers = object().shape({ id: string().required(), newId: string().required(), }) interface TreeViewData { id: string name: string children?: TreeViewData[] } const convertToTreeViewData = ( items: (OrganizationUnitDto & { isAdded?: boolean })[], parentId?: string, ) => { const levelItems = items.filter((a) => a.parentId == parentId) if (!levelItems?.length) { return } const data: TreeViewData[] = [] for (let item of levelItems) { if (!item.id || item.isAdded) { continue } item.isAdded = true data.push({ id: item.id, name: item.displayName, children: convertToTreeViewData(items, item.id), }) } return data } interface DeleteTypeData { id: string name: 'Organization Unit' | 'User' | 'Role' } const OrganizationUnits = () => { const [loading, setLoading] = useState(true) const [ous, setOus] = useState([]) const [list, setList] = useState([]) const [activeOu, setActiveOu] = useState() const [dialogItem, setDialogItem] = useState() const [ouMembers, setOuMembers] = useState([]) const [userSelectionList, setUserSelectionList] = useState([]) const [userSelectedRows, setUserSelectedRows] = useState([]) const [roleSelectionList, setRoleSelectionList] = useState([]) const [ouRoles, setOuRoles] = useState([]) const [roleSelectedRows, setRoleSelectedRows] = useState([]) const [deleteRow, setDeleteRow] = useState() const [isMoveAllUsersOpen, setIsMoveAllUsersOpen] = useState(false) const [treeSearch, setTreeSearch] = useState('') const { translate } = useLocalization() const userSelectionColumns: ColumnDef[] = useMemo( () => [ { header: 'Name', accessorKey: 'fullName', cell: ({ row }) => ( <> {row.original.name} {row.original.surname} ), }, { header: 'Email', accessorKey: 'email', }, ], [], ) const roleSelectionColumns: ColumnDef[] = useMemo( () => [ { header: 'Name', accessorKey: 'Name', cell: ({ row }) => <>{row.original.name}, }, ], [], ) const handleUserRowSelect = (checked: boolean, row: IdentityUserDto) => { if (checked) { const newState = [...userSelectedRows, row.id!] setUserSelectedRows(newState) } else { const newState = [...userSelectedRows.filter((id) => id !== row.id)] setUserSelectedRows(newState) } } const handleRoleRowSelect = (checked: boolean, row: IdentityRoleDto) => { if (checked) { const newState = [...roleSelectedRows, row.id!] setRoleSelectedRows(newState) } else { const newState = [...roleSelectedRows.filter((id) => id !== row.id)] setRoleSelectedRows(newState) } } const fetchData = async () => { setLoading(true) const response = await ouGetAll() if (response.data?.items) { setOus( response.data.items.map((a) => ({ value: a.id, label: a.displayName, })), ) var list = convertToTreeViewData(response.data.items) ?? [] setList(list) } setLoading(false) } useEffect(() => { if (isEmpty(list)) { fetchData() } }, []) const handleDialogSubmit = async ( values: CreateUpdateOrganizationUnitDto, { setSubmitting }: FormikHelpers, ) => { setLoading(true) setSubmitting(true) try { if (values.id) { await ouPut(values) } else { await ouPost(values) } toast.push( {translate('::Kaydet')} , { placement: 'top-end', }, ) fetchData() onDialogClose() } catch (error) { toast.push( Hata , { placement: 'top-end', }, ) } finally { setLoading(false) setSubmitting(false) } } const onDialogClose = () => { setDialogItem(undefined) } const onDropdownItemClick = (node: NodeApi, eventKey: string) => { if (eventKey == 'edit') { setDialogItem({ id: node.data.id, displayName: node.data.name, parentId: node.parent?.isRoot ? undefined : node.parent?.data.id, }) } else if (eventKey == 'add-sub-unit') { setDialogItem({ displayName: '', parentId: node.data.id, }) } else if (eventKey == 'delete') { setDeleteRow({ id: node.data.id, name: 'Organization Unit' }) } } const onSelect = async (nodes: NodeApi[]) => { if (nodes.length === 0) { setActiveOu(undefined) } else { const node = nodes[0] setActiveOu(node.data.id) } } const fetchUsersAndRoles = async (id: string) => { try { setLoading(true) const memberList = await ouGetMembers(id) const members = memberList.data?.items ?? [] setOuMembers(members) setUserSelectedRows(members.map((a) => a.id!)) const roleList = await ouGetRoles(id) const roles = roleList.data?.items ?? [] setOuRoles(roles) setRoleSelectedRows(roles.map((a) => a.id!)) } catch (error) { toast.push( Hata , { placement: 'top-end', }, ) } finally { setLoading(false) } } useEffect(() => { const fn = async () => { setOuMembers([]) setUserSelectedRows([]) setOuRoles([]) setRoleSelectedRows([]) if (activeOu) { await fetchUsersAndRoles(activeOu) } } fn() }, [activeOu]) const handleEdit = async (id: string, name: string) => { setLoading(true) try { if (!id) { return } await ouPut({ id, displayName: name }) toast.push( {translate('::Kaydet')} , { placement: 'top-end', }, ) fetchData() } catch (error) { toast.push( Hata , { placement: 'top-end', }, ) } finally { setLoading(false) } } const handleMove = async (id: string, newParentId?: string) => { setLoading(true) try { if (!id) { return } await ouPutMove(id, newParentId) toast.push( {translate('::Kaydet')} , { placement: 'top-end', }, ) fetchData() } catch (error) { toast.push( Hata , { placement: 'top-end', }, ) } finally { setLoading(false) } } const Node = memo(({ node, style, dragHandle }: NodeRendererProps) => { return (
node.isInternal && node.toggle()} >
{node.isInternal && (node.isOpen ? : )}
{node.isEditing ? ( node.reset()} onKeyDown={(e) => { if (e.key === 'Escape') { node.reset() } if (e.key === 'Enter') { node.submit(e.currentTarget.value) } }} autoFocus /> ) : ( {node.data.name} )}
) }) return ( <>
} > { setTreeSearch(e.target.value) }} /> { if (dragIds.length > 0) { handleMove(dragIds[0], parentId ?? '') } }} onRename={({ id, name }) => { handleEdit(id, name) }} className="mt-2 cursor-pointer" searchTerm={treeSearch} indent={10} searchMatch={(node, term) => node.data.name.toLowerCase().includes(term.toLowerCase()) } width={'100%'} > {Node} }> {translate('::AbpIdentity.Users')} }> {translate('::AbpIdentity.Roles')} {activeOu ? ( { e.preventDefault() const response = await getUsers(0, 1000) setUserSelectionList(response.data?.items ?? []) }} > } > {!!ouMembers.length && ( )} {ouMembers.map((user) => ( ))}
Adı Soyadı E-Posta Durum
{user.name} {user.surname} {user.email} {user.isActive ? 'Aktif' : 'Pasif'}
) : (
{translate('::Abp.Identity.OrganizationUnit.Users.Description')}
)}
{activeOu ? ( { e.preventDefault() const response = await getRoles(0, 1000) setRoleSelectionList(response.data?.items ?? []) }} > } > {!!ouRoles.length && ( )} {ouRoles.map((role) => ( ))}
Rol
{role.name}
) : (
{translate('::Abp.Identity.OrganizationUnit.Roles.Description')}
)}
{translate('::Abp.Identity.OrganizationUnit.NewUnit')}

}> {({ touched, errors, isSubmitting }) => { return (
{/* Parent Name göster */}
) }}
0} onClose={() => setUserSelectionList([])} onRequestClose={() => setUserSelectionList([])} >
{translate('::Abp.Identity.OrganizationUnit.SelectMembers')}
selectable selectedRows={[...userSelectedRows]} columns={userSelectionColumns} data={userSelectionList} loading={loading} // pagingData={tableData} // onPaginationChange={handlePaginationChange} // onSelectChange={handleSelectChange} // Items per page // onSort={handleSort} onCheckBoxChange={handleUserRowSelect} // onIndeterminateCheckBoxChange={handleAllRowSelect} />
0} onClose={() => setRoleSelectionList([])} onRequestClose={() => setRoleSelectionList([])} >
{translate('::Abp.Identity.OrganizationUnit.SelectRoles')}
selectable selectedRows={[...roleSelectedRows]} columns={roleSelectionColumns} data={roleSelectionList} loading={loading} // pagingData={tableData} // onPaginationChange={handlePaginationChange} // onSelectChange={handleSelectChange} // Items per page // onSort={handleSort} onCheckBoxChange={handleRoleRowSelect} // onIndeterminateCheckBoxChange={handleAllRowSelect} />
setDeleteRow(null)} onRequestClose={() => setDeleteRow(null)} >
{translate('::Delete')}

{translate('::DeleteConfirmation')}

setIsMoveAllUsersOpen(false)} onRequestClose={() => setIsMoveAllUsersOpen(false)} >
{translate('::Abp.Identity.OrganizationUnit.MoveAllUsers')}
{ if (!values.id || values.id === values.newId) { return } setSubmitting(true) try { setLoading(true) await ouMoveAllUsers(values.id, values.newId) toast.push( {translate('::Abp.Identity.OrganizationUnit.MoveAllUsersMessage')} , { placement: 'top-end', }, ) await fetchUsersAndRoles(values.id) setIsMoveAllUsersOpen(false) } catch (error) { toast.push( Hata , { placement: 'top-end', }, ) } finally { setSubmitting(false) } }} > {({ touched, errors, values, isSubmitting }) => { return (
{({ field, form }: FieldProps) => ( option.value === values.newId)} onChange={(option) => form.setFieldValue(field.name, option?.value)} /> )}
) }}
) } export default OrganizationUnits