336 lines
11 KiB
TypeScript
336 lines
11 KiB
TypeScript
import ThingsFilter from '@/components/shared/ThingFilterModal';
|
|
import { DATE_TIME_FORMAT, DEFAULT_PAGE_SIZE, HTTPSTATUS } from '@/constants';
|
|
import {
|
|
apiGetAlarms,
|
|
apiUnconfirmAlarm,
|
|
} from '@/services/master/AlarmController';
|
|
import {
|
|
CloseOutlined,
|
|
DeleteOutlined,
|
|
FilterOutlined,
|
|
} from '@ant-design/icons';
|
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
|
import { FormattedMessage, useIntl, useModel } from '@umijs/max';
|
|
import { Button, Flex, message, Popconfirm, Progress, Tooltip } from 'antd';
|
|
import moment from 'moment';
|
|
import { useRef, useState } from 'react';
|
|
import AlarmDescription from './components/AlarmDescription';
|
|
import AlarmFormConfirm from './components/AlarmFormConfirm';
|
|
|
|
const AlarmPage = () => {
|
|
const tableRef = useRef<ActionType>();
|
|
const [selectedKey, setSelectedKey] = useState<React.Key>();
|
|
const [thingFilterVisible, setThingFilterVisible] = useState<boolean>(false);
|
|
const [thingFilterDatas, setThingFilterDatas] = useState<string[]>([]);
|
|
const intl = useIntl();
|
|
const [messageApi, contextHolder] = message.useMessage();
|
|
const { initialState } = useModel('@@initialState');
|
|
const { currentUserProfile } = initialState || {};
|
|
|
|
const columns: ProColumns<MasterModel.Alarm>[] = [
|
|
{
|
|
title: intl.formatMessage({
|
|
id: 'common.name',
|
|
defaultMessage: 'Name',
|
|
}),
|
|
dataIndex: 'name',
|
|
key: 'name',
|
|
copyable: true,
|
|
},
|
|
{
|
|
title: intl.formatMessage({
|
|
id: 'master.alarms.severity',
|
|
defaultMessage: 'Severity',
|
|
}),
|
|
dataIndex: 'level',
|
|
key: 'level',
|
|
responsive: ['lg', 'md', 'sm'],
|
|
filters: true,
|
|
onFilter: true,
|
|
valueType: 'select',
|
|
valueEnum: {
|
|
0: {
|
|
text: intl.formatMessage({
|
|
id: 'common.level.normal',
|
|
defaultMessage: 'Normal',
|
|
}),
|
|
status: 'Success',
|
|
},
|
|
1: {
|
|
text: intl.formatMessage({
|
|
id: 'common.level.warning',
|
|
defaultMessage: 'Warning',
|
|
}),
|
|
status: 'Warning',
|
|
},
|
|
2: {
|
|
text: intl.formatMessage({
|
|
id: 'common.level.critical',
|
|
defaultMessage: 'Critical',
|
|
}),
|
|
status: 'Error',
|
|
},
|
|
3: {
|
|
text: intl.formatMessage({
|
|
id: 'common.level.sos',
|
|
defaultMessage: 'SOS',
|
|
}),
|
|
status: 'Error',
|
|
},
|
|
},
|
|
},
|
|
|
|
{
|
|
title: intl.formatMessage({
|
|
id: 'sgw.ship',
|
|
defaultMessage: 'Source',
|
|
}),
|
|
dataIndex: 'thing_name',
|
|
key: 'thing_name',
|
|
responsive: ['lg', 'md', 'sm'],
|
|
ellipsis: true,
|
|
copyable: true,
|
|
// render: (dom, row) => {
|
|
// return (
|
|
// <Paragraph copyable>
|
|
// <Link
|
|
// onClick={() => {
|
|
// const t = row?.thing_type;
|
|
// const path = `/devices/${row?.thing_id}/${t}`;
|
|
// history.push({
|
|
// pathname: path,
|
|
// });
|
|
// }}
|
|
// >
|
|
// {dom}
|
|
// </Link>
|
|
// </Paragraph>
|
|
// );
|
|
// },
|
|
// render: (_, item) => {
|
|
// return <Paragraph copyable>{item?.thing_name}</Paragraph>
|
|
// }
|
|
},
|
|
{
|
|
title: intl.formatMessage({
|
|
id: 'master.alarms.occurred_at',
|
|
defaultMessage: 'Occured time',
|
|
}),
|
|
dataIndex: 'time',
|
|
key: 'time',
|
|
search: false,
|
|
render: (_, item) => {
|
|
return moment.unix(item.time!).format(DATE_TIME_FORMAT);
|
|
},
|
|
},
|
|
{
|
|
title: intl.formatMessage({
|
|
id: 'master.alarms.confirmed',
|
|
defaultMessage: 'Confirmed',
|
|
}),
|
|
dataIndex: 'confirmed',
|
|
responsive: ['lg', 'md'],
|
|
align: 'center',
|
|
width: '10%',
|
|
search: false,
|
|
render: (_, item) => {
|
|
return item?.confirmed ? (
|
|
<Progress type="circle" percent={100} size={24} />
|
|
) : null;
|
|
},
|
|
},
|
|
];
|
|
return (
|
|
<>
|
|
<ThingsFilter
|
|
isOpen={thingFilterVisible}
|
|
setIsOpen={setThingFilterVisible}
|
|
thingIds={thingFilterDatas}
|
|
onSubmit={(thingIds) => {
|
|
console.log('ThingIDs: ', thingIds);
|
|
setThingFilterDatas(thingIds);
|
|
tableRef.current?.reload();
|
|
}}
|
|
/>
|
|
{contextHolder}
|
|
<ProTable<MasterModel.Alarm>
|
|
actionRef={tableRef}
|
|
rowKey={(record) => `${record.thing_id}_${record.id}`}
|
|
columns={columns}
|
|
rowSelection={{
|
|
type: 'checkbox',
|
|
selectedRowKeys: selectedKey ? [selectedKey] : [],
|
|
onChange: (selectedKeys) => {
|
|
// Checkbox with max 1 row selection - toggle behavior
|
|
if (selectedKeys.length === 0) {
|
|
setSelectedKey(undefined);
|
|
} else {
|
|
// Get the key that's different from current selection (the newly clicked row)
|
|
const newKey = selectedKeys.find((key) => key !== selectedKey);
|
|
setSelectedKey(newKey ?? selectedKeys[0]);
|
|
}
|
|
},
|
|
}}
|
|
size="large"
|
|
tableAlertRender={({ selectedRows }) => {
|
|
const alarm = selectedRows[0];
|
|
return <AlarmDescription alarm={alarm} />;
|
|
}}
|
|
options={{
|
|
search: false,
|
|
setting: false,
|
|
density: false,
|
|
reload: true,
|
|
}}
|
|
toolbar={{
|
|
actions: [
|
|
<Tooltip
|
|
title={intl.formatMessage({ id: 'master.alarms.filter_things' })}
|
|
key="thing-filter-tooltip"
|
|
>
|
|
<Button
|
|
color={thingFilterDatas.length > 0 ? 'red' : 'default'}
|
|
icon={<FilterOutlined />}
|
|
variant="text"
|
|
onClick={() => setThingFilterVisible(true)}
|
|
/>
|
|
</Tooltip>,
|
|
],
|
|
}}
|
|
tableAlertOptionRender={({ selectedRows, onCleanSelected }) => {
|
|
const alarm = selectedRows[0];
|
|
return (
|
|
<Flex gap={10}>
|
|
{alarm?.confirmed || false ? (
|
|
<Popconfirm
|
|
title={intl.formatMessage({
|
|
id: 'master.alarms.unconfirm.body',
|
|
defaultMessage:
|
|
'Are you sure you want to unconfirm this alarm?',
|
|
})}
|
|
okText={intl.formatMessage({
|
|
id: 'common.yes',
|
|
defaultMessage: 'Yes',
|
|
})}
|
|
cancelText={intl.formatMessage({
|
|
id: 'common.no',
|
|
defaultMessage: 'No',
|
|
})}
|
|
onConfirm={async () => {
|
|
const body: MasterModel.ConfirmAlarmRequest = {
|
|
id: alarm.id,
|
|
thing_id: alarm.thing_id,
|
|
time: alarm.time,
|
|
};
|
|
try {
|
|
const resp = await apiUnconfirmAlarm(body);
|
|
if (resp.status === HTTPSTATUS.HTTP_SUCCESS) {
|
|
message.success({
|
|
content: intl.formatMessage({
|
|
id: 'master.alarms.unconfirm.success',
|
|
defaultMessage: 'Confirm alarm successfully',
|
|
}),
|
|
});
|
|
tableRef.current?.reload();
|
|
} else if (resp.status === HTTPSTATUS.HTTP_NOTFOUND) {
|
|
message.warning({
|
|
content: intl.formatMessage({
|
|
id: 'master.alarms.not_found',
|
|
defaultMessage:
|
|
'Alarm has expired or does not exist',
|
|
}),
|
|
});
|
|
tableRef.current?.reload();
|
|
} else {
|
|
throw new Error('Failed to confirm alarm');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error when unconfirm alarm: ', error);
|
|
message.error({
|
|
content: intl.formatMessage({
|
|
id: 'master.alarms.unconfirm.fail',
|
|
defaultMessage: 'Unconfirm alarm failed',
|
|
}),
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
<Button danger icon={<DeleteOutlined />} size="small">
|
|
<FormattedMessage id="master.alarms.unconfirm.title" />
|
|
</Button>
|
|
</Popconfirm>
|
|
) : (
|
|
<AlarmFormConfirm
|
|
alarm={alarm}
|
|
message={messageApi}
|
|
onFinish={(isReload) => {
|
|
if (isReload && tableRef.current) {
|
|
tableRef.current.reload();
|
|
}
|
|
}}
|
|
/>
|
|
)}
|
|
<Button
|
|
size="small"
|
|
icon={<CloseOutlined />}
|
|
onClick={onCleanSelected}
|
|
danger
|
|
/>
|
|
</Flex>
|
|
);
|
|
}}
|
|
pagination={{
|
|
defaultPageSize: DEFAULT_PAGE_SIZE * 2,
|
|
showSizeChanger: true,
|
|
pageSizeOptions: ['5', '10', '15', '20'],
|
|
showTotal: (total, range) =>
|
|
`${range[0]}-${range[1]}
|
|
${intl.formatMessage({
|
|
id: 'common.paginations.of',
|
|
defaultMessage: 'of',
|
|
})}
|
|
${total} ${intl.formatMessage({
|
|
id: 'master.alarms.table.pagination',
|
|
defaultMessage: 'alarms',
|
|
})}`,
|
|
}}
|
|
request={async (params) => {
|
|
const { current, pageSize, name, level, thing_name } = params;
|
|
const offset = current === 1 ? 0 : (current! - 1) * pageSize!;
|
|
const body: MasterModel.SearchAlarmPaginationBody = {
|
|
name: name,
|
|
order: 'name',
|
|
limit: pageSize,
|
|
offset: offset,
|
|
level: level as number | undefined,
|
|
thing_name: thing_name,
|
|
dir: 'desc',
|
|
};
|
|
if (thingFilterDatas.length > 0) {
|
|
body.thing_id = Array.isArray(thingFilterDatas)
|
|
? thingFilterDatas.join(',')
|
|
: thingFilterDatas;
|
|
}
|
|
|
|
try {
|
|
const res = await apiGetAlarms(body);
|
|
return {
|
|
data: res.alarms,
|
|
total: res.total,
|
|
success: true,
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
data: [],
|
|
total: 0,
|
|
success: false,
|
|
};
|
|
}
|
|
}}
|
|
></ProTable>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default AlarmPage;
|