feat(project): base smatec's frontend

This commit is contained in:
Tran Anh Tuan
2026-01-21 11:48:57 +07:00
commit 5c2a909bed
138 changed files with 43666 additions and 0 deletions

View File

@@ -0,0 +1,484 @@
import { DATE_TIME_FORMAT, DEFAULT_PAGE_SIZE } from '@/constants';
import { apiQueryLogs } from '@/services/master/LogController';
import { apiQueryUsers } from '@/services/master/UserController';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { DatePicker } from 'antd/lib';
import dayjs from 'dayjs';
import { useRef } from 'react';
const SystemLogs = () => {
const intl = useIntl();
const tableRef = useRef<ActionType>();
const actions = [
//Alarm
{
title: intl.formatMessage({
id: 'master.logs.things.alarm.confirm',
defaultMessage: 'Alarm confirm',
}),
value: '0-0',
selectable: false,
children: [
{
value: 'things.alarm_confirm',
title: intl.formatMessage({
id: 'master.logs.things.confirm',
defaultMessage: 'Confirm',
}),
},
{
value: 'things.alarm_unconfirm',
title: intl.formatMessage({
id: 'master.logs.things.unconfirm',
defaultMessage: 'Unconfirm',
}),
},
],
},
//Things
{
title: intl.formatMessage({
id: 'master.logs.things',
defaultMessage: 'Things',
}),
value: '0-1',
selectable: false,
children: [
{
value: 'things.create',
title: intl.formatMessage({
id: 'master.logs.things.create',
defaultMessage: 'Create new thing',
}),
},
{
value: 'things.update',
title: intl.formatMessage({
id: 'master.logs.things.update',
defaultMessage: 'Update thing',
}),
},
{
value: 'things.remove',
title: intl.formatMessage({
id: 'master.logs.things.remove',
defaultMessage: 'Remove thing',
}),
},
{
value: 'things.share',
title: intl.formatMessage({
id: 'master.logs.things.share',
defaultMessage: 'Share thing',
}),
},
{
value: 'things.unshare',
title: intl.formatMessage({
id: 'master.logs.things.unshare',
defaultMessage: 'Unshare thing',
}),
},
{
value: 'things.update_key',
title: intl.formatMessage({
id: 'master.logs.things.update_key',
defaultMessage: 'Update key thing',
}),
},
],
},
// Users
{
title: intl.formatMessage({
id: 'master.logs.users',
defaultMessage: 'Users',
}),
value: '0-2',
selectable: false,
children: [
{
value: 'users.create',
title: intl.formatMessage({
id: 'master.logs.users.create',
defaultMessage: 'Register user',
}),
},
{
value: 'users.update',
title: intl.formatMessage({
id: 'master.logs.users.update',
defaultMessage: 'Update user',
}),
},
{
value: 'users.remove',
title: intl.formatMessage({
id: 'master.logs.users.remove',
defaultMessage: 'Remove user',
}),
},
{
value: 'users.login',
title: intl.formatMessage({
id: 'master.logs.users.login',
defaultMessage: 'User login',
}),
},
],
},
// Groups
{
title: intl.formatMessage({
id: 'master.logs.groups',
defaultMessage: 'Groups',
}),
value: '0-3',
selectable: false,
children: [
{
value: 'group.create',
title: intl.formatMessage({
id: 'master.logs.groups.create',
defaultMessage: 'Create new group',
}),
},
{
value: 'group.update',
title: intl.formatMessage({
id: 'master.logs.groups.update',
defaultMessage: 'Update group',
}),
},
{
value: 'group.remove',
title: intl.formatMessage({
id: 'master.logs.groups.remove',
defaultMessage: 'Remove group',
}),
},
{
value: 'group.assign_thing',
title: intl.formatMessage({
id: 'master.logs.groups.assign_thing',
defaultMessage: 'Assign thing to group',
}),
},
{
value: 'group.assign_user',
title: intl.formatMessage({
id: 'master.logs.groups.assign_user',
defaultMessage: 'Assign user to group',
}),
},
{
value: 'group.unassign_thing',
title: intl.formatMessage({
id: 'master.logs.groups.unassign_thing',
defaultMessage: 'Remove thing from group',
}),
},
{
value: 'group.unassign_user',
title: intl.formatMessage({
id: 'master.logs.groups.unassign_user',
defaultMessage: 'Remove user from group',
}),
},
],
},
// Ships
{
title: intl.formatMessage({
id: 'master.logs.ships',
defaultMessage: 'Ships',
}),
value: '0-4',
selectable: false,
children: [
{
value: 'ships.create',
title: intl.formatMessage({
id: 'master.logs.ships.create',
defaultMessage: 'Create new ship',
}),
},
{
value: 'ships.update',
title: intl.formatMessage({
id: 'master.logs.ships.update',
defaultMessage: 'Update ship',
}),
},
{
value: 'ships.remove',
title: intl.formatMessage({
id: 'master.logs.ships.remove',
defaultMessage: 'Remove ship',
}),
},
{
value: 'ships.assign_thing',
title: intl.formatMessage({
id: 'master.logs.ships.assign_thing',
defaultMessage: 'Assign thing to ship',
}),
},
{
value: 'ships.assign_user',
title: intl.formatMessage({
id: 'master.logs.ships.assign_user',
defaultMessage: 'Assign user to ship',
}),
},
{
value: 'ships.unassign_thing',
title: intl.formatMessage({
id: 'master.logs.ships.unassign_thing',
defaultMessage: 'Remove thing from ship',
}),
},
{
value: 'ships.unassign_user',
title: intl.formatMessage({
id: 'master.logs.ships.unassign_user',
defaultMessage: 'Remove user from ship',
}),
},
],
},
// Trips
{
title: intl.formatMessage({
id: 'master.logs.trips',
defaultMessage: 'Trips',
}),
value: '0-5',
selectable: false,
children: [
{
value: 'trips.create',
title: intl.formatMessage({
id: 'master.logs.trips.create',
defaultMessage: 'Create new ship',
}),
},
{
value: 'trips.update',
title: intl.formatMessage({
id: 'master.logs.trips.update',
defaultMessage: 'Update ship',
}),
},
{
value: 'trips.remove',
title: intl.formatMessage({
id: 'master.logs.trips.remove',
defaultMessage: 'Remove ship',
}),
},
{
value: 'trips.approve',
title: intl.formatMessage({
id: 'master.logs.trips.approve',
defaultMessage: 'Approve trip',
}),
},
{
value: 'trips.request_approve',
title: intl.formatMessage({
id: 'master.logs.trips.request_approve',
defaultMessage: 'Request approval for trip',
}),
},
{
value: 'trips.unassign_thing',
title: intl.formatMessage({
id: 'master.logs.trips.unassign_thing',
defaultMessage: 'Remove thing from ship',
}),
},
{
value: 'trips.unassign_user',
title: intl.formatMessage({
id: 'master.logs.trips.unassign_user',
defaultMessage: 'Remove user from ship',
}),
},
],
},
];
const queryUserSource = async (): Promise<MasterModel.ProfileResponse[]> => {
try {
const body: MasterModel.SearchUserPaginationBody = {
offset: 0,
limit: 100,
order: 'email',
dir: 'asc',
};
const resp = await apiQueryUsers(body);
return resp?.users ?? [];
} catch {
return [];
}
};
const columns: ProColumns<MasterModel.Message>[] = [
{
title: intl.formatMessage({
id: 'master.logs.date.text',
defaultMessage: 'Date',
}),
key: 'dateTimeRange',
dataIndex: 'time',
width: '20%',
valueType: 'dateTimeRange',
initialValue: [dayjs().add(-1, 'day'), dayjs()],
search: {
transform: (value) => ({ startTime: value[0], endTime: value[1] }),
},
render: (_, row) => {
return dayjs.unix(row?.time || 0).format(DATE_TIME_FORMAT);
},
renderFormItem: (_, config, form) => {
return (
<DatePicker.RangePicker
width="50%"
presets={[
{
label: intl.formatMessage({
id: 'master.logs.search.yesterday',
defaultMessage: 'Yesterday',
}),
value: [dayjs().add(-1, 'day'), dayjs()],
},
{
label: intl.formatMessage({
id: 'master.logs.search.last_week',
defaultMessage: 'Last Week',
}),
value: [dayjs().add(-7, 'day'), dayjs()],
},
{
label: intl.formatMessage({
id: 'master.logs.search.last_month',
defaultMessage: 'Last Month',
}),
value: [dayjs().add(-30, 'day'), dayjs()],
},
]}
onChange={(dates) => {
form.setFieldsValue({ dateTimeRange: dates });
}}
/>
);
},
},
{
title: intl.formatMessage({
id: 'master.logs.email.text',
defaultMessage: 'Email',
}),
dataIndex: 'publisher',
valueType: 'select',
fieldProps: { mode: 'multiple' },
width: '25%',
request: async () => {
const users = await queryUserSource();
return users.map((u) => ({
label: u.email,
value: u.email,
}));
},
},
{
title: intl.formatMessage({
id: 'master.logs.action.text',
defaultMessage: 'Action',
}),
dataIndex: 'subtopic',
valueType: 'treeSelect',
width: '25%',
fieldProps: {
treeCheckable: true,
multiple: true,
},
request: async () => actions,
render: (_, item) => {
const childs = actions.flatMap((a) => a.children || []);
const action = childs.find((a) => a?.value === item.subtopic);
return action?.title ?? '...';
},
},
];
return (
<ProTable<MasterModel.Message>
actionRef={tableRef}
columns={columns}
rowKey={(item) =>
`${item.subtopic}:${item.time}:${item.publisher}:${item.name}`
}
size="large"
options={{
search: false,
setting: false,
density: false,
reload: true,
}}
pagination={{
defaultPageSize: DEFAULT_PAGE_SIZE * 2,
showSizeChanger: true,
pageSizeOptions: ['10', '15', '20'],
showTotal: (total, range) =>
`${range[0]}-${range[1]}
${intl.formatMessage({
id: 'common.paginations.of',
defaultMessage: 'of',
})}
${total} ${intl.formatMessage({
id: 'master.logs.table.pagination',
defaultMessage: 'activities',
})}`,
}}
request={async (params) => {
try {
const { current, pageSize, subtopic, publisher, startTime, endTime } =
params;
const offset = current === 1 ? 0 : (current! - 1) * pageSize!;
const body: MasterModel.SearchLogPaginationBody = {
limit: pageSize,
offset: offset,
from: startTime
? typeof startTime === 'string'
? dayjs(startTime).unix()
: startTime.unix()
: undefined,
to: endTime
? typeof endTime === 'string'
? dayjs(endTime).unix()
: endTime.unix()
: undefined,
publisher: publisher?.length ? publisher.join(',') : undefined,
subtopic: subtopic?.length ? subtopic.join(',') : undefined,
};
const resp = await apiQueryLogs(body, 'user_logs');
return {
data: resp.messages || [],
success: true,
total: resp.total || 0,
};
} catch (error) {
console.error('Error when get logs: ', error);
return {
data: [],
success: false,
total: 0,
};
}
}}
/>
);
};
export default SystemLogs;