import IconFont from '@/components/IconFont'; import TreeGroup from '@/components/shared/TreeGroup'; import { HTTPSTATUS } from '@/constants'; import { apiDeleteGroup, apiUpdateGroup, } from '@/services/master/GroupController'; import { DeleteOutlined, EditOutlined, ExclamationCircleOutlined, PlusOutlined, } from '@ant-design/icons'; import { ProCard, ProDescriptions } from '@ant-design/pro-components'; import { FormattedMessage, useIntl, useModel } from '@umijs/max'; import { Button, Grid, message, Modal } from 'antd'; import { Dropdown, MenuProps, Tooltip } from 'antd/lib'; import { useState } from 'react'; import CreateOrUpdateGroup from './components/CreateOrUpdateGroup'; type MenuItem = Required['items'][number]; const ManagerGroupPage = () => { const { useBreakpoint } = Grid; const { initialState } = useModel('@@initialState'); const { currentUserProfile } = initialState || {}; const intl = useIntl(); const screens = useBreakpoint(); const [selectedItem, setSelectedItem] = useState< MasterModel.GroupNode | undefined >(); const [selectedGroup, setSelectedGroup] = useState< MasterModel.GroupNode | undefined >(); const { groups, getGroups } = useModel('master.useGroups'); const [handleChildModal, setHandleChildModal] = useState(false); const [type, setType] = useState<'create-root' | 'create-child' | 'update'>( 'create-root', ); const [messageApi, contextHolder] = message.useMessage(); const [modalKey, setModalKey] = useState(0); const findGroupById = ( groups: MasterModel.GroupNode[], id: string, ): MasterModel.GroupNode | undefined => { for (const group of groups) { if (group.id === id) return group; if (group.children) { const found = findGroupById(group.children, id); if (found) return found; } } return undefined; }; const handleUpdate = async (group: Partial) => { const key = 'update_group'; const { name, description, parent_id, code, short_name } = group; const editGroup = parent_id ? { ...selectedItem, name: name, parent_id: parent_id, metadata: { code: code, short_name: short_name, }, description: description, } : { ...selectedItem, name: name, metadata: { code: code, short_name: short_name, }, description: description, }; try { messageApi.open({ type: 'loading', content: intl.formatMessage({ id: 'common.updating', defaultMessage: 'updating...', }), key, }); await apiUpdateGroup({ ...editGroup }); messageApi.open({ type: 'success', content: intl.formatMessage({ id: 'master.groups.update.success', defaultMessage: 'Updated successfully', }), key, }); await getGroups(); return true; } catch (error) { messageApi.open({ type: 'error', content: intl.formatMessage({ id: 'master.groups.update.failed', defaultMessage: 'Updating failed, please try again!', }), key, }); return false; } }; const showDeleteConfirm = (group: MasterModel.GroupNode) => { Modal.confirm({ title: intl.formatMessage({ id: 'master.groups.delete.confirm', defaultMessage: 'Are you sure delete this group', }), content: selectedItem?.name, icon: , okText: intl.formatMessage({ id: 'common.yes', defaultMessage: 'Yes' }), okType: 'danger', cancelText: intl.formatMessage({ id: 'common.no', defaultMessage: 'No' }), async onOk() { try { const resp = await apiDeleteGroup(group.id); if (resp.status === HTTPSTATUS.HTTP_NOCONTENT) { messageApi.success( intl.formatMessage({ id: 'master.groups.delete.success', defaultMessage: 'Deleted group successfully', }), ); setSelectedItem(undefined); await getGroups(); } else if (resp.status === HTTPSTATUS.HTTP_SERVERERROR) { messageApi.warning( intl.formatMessage({ id: 'master.groups.delete.failed_internal', defaultMessage: 'The group contains devices or users and cannot be deleted', }), ); } else { throw new Error('Delete group failed'); } } catch (error) { console.error('Error when delete group ', error); messageApi.error( intl.formatMessage({ id: 'master.groups.delete.failed', defaultMessage: 'Delete group failed', }), ); } }, }); }; const onItemClick = ({ key }: { key: string }) => { const splitIndex = key.indexOf('-'); const action = key.substring(0, splitIndex); const groupId = key.substring(splitIndex + 1); const groupNode = findGroupById(groups || [], groupId); console.log('GroupName', groupNode?.name); setSelectedItem(groupNode); setSelectedGroup(groupNode); if (action === '1') { setType('create-child'); } else if (action === '2') { setType('update'); } else if (action === '3') { showDeleteConfirm(groupNode!); return; } // Increment modalKey to force remount component setModalKey((prev) => prev + 1); setHandleChildModal(true); }; return ( <> {contextHolder} } onClick={() => { setType('create-root'); setSelectedItem(undefined); setModalKey((prev) => prev + 1); setHandleChildModal(true); }} > ), ]} > { const groupNode = findGroupById(groups || [], item.key as string); const menus: MenuItem[] = [ { label: ( {intl.formatMessage({ id: 'master.groups.add', defaultMessage: 'Add child', })} ), key: `1-${groupNode?.id}`, icon: , disabled: groupNode?.metadata?.has_thing === true, }, { label: intl.formatMessage({ id: 'common.edit', defaultMessage: 'Update', }), key: `2-${groupNode?.id}`, icon: , }, { label: ( {intl.formatMessage({ id: 'common.delete', defaultMessage: 'Delete', })} ), key: `3-${groupNode?.id}`, icon: , disabled: groupNode?.metadata?.has_thing === true, }, ]; return ( {typeof item.title === 'function' ? item.title(item) : item.title} ); }} multiple={false} onSelected={(value: string | string[] | null) => { if (!groups) { setSelectedItem(undefined); return; } // Find the selected group from model if (value && !Array.isArray(value)) { const found = findGroupById(groups, value); setSelectedItem(found); } else { setSelectedItem(undefined); } }} /> {selectedItem?.name && ( <> > column={1} bordered title={selectedItem.name} extra={[ , , , ]} dataSource={{ name: selectedItem.name, code: selectedItem.metadata?.code || '', short_name: selectedItem.metadata?.short_name || '', description: selectedItem.description || '', }} columns={[ { title: intl.formatMessage({ id: 'common.name', defaultMessage: 'Name', }), dataIndex: 'name', }, { title: intl.formatMessage({ id: 'master.groups.code', defaultMessage: 'Code', }), dataIndex: 'code', }, { title: intl.formatMessage({ id: 'master.groups.short_name', defaultMessage: 'Short name', }), dataIndex: 'short_name', }, { title: intl.formatMessage({ id: 'common.description', defaultMessage: 'Description', }), dataIndex: 'description', }, ]} editable={{ onSave: async (_, record) => { const updatedData: MasterModel.GroupNode = { ...selectedItem, name: record.name || '', description: record.description || '', metadata: { ...selectedItem.metadata, code: record.code, short_name: record.short_name, }, }; const success = await handleUpdate(updatedData); if (success) { setSelectedItem(updatedData); return true; } return false; }, }} /> )} ); }; export default ManagerGroupPage;